Construirea de aplicaţii web de nivel enterprise poate fi complexă şi poate consuma mult timp.
ABP Commercial oferă infrastructura de bază pentru toate soluţiile moderne bazate pe ASP.NET Core de nivel enterprise. De la proiectare până la implementare, întregul ciclu de dezvoltare este împuternicit de funcţiile şi modulele integrate ale ABP.
",
+ "StartupTemplatesShortDescription": "Şabloanele de pornire vă fac să începeţi proiectul în câteva secunde.",
+ "UIFrameworksOptions": "UI frameworks options;",
+ "DatabaseProviderOptions": "Opţiuni furnizor de bază de date;",
+ "PreBuiltApplicationModules": "Module de aplicaţii pre-construite",
+ "PreBuiltApplicationModulesShortDescription": "Cele mai comune cerinţe de aplicaţie sunt deja dezvoltate pentru dumneavoastră sub formă de module reutilizabile.",
+ "Account": "Cont",
+ "Blogging": "Blogging",
+ "Identity": "Identitate",
+ "IdentityServer": "Identity Server",
+ "Saas": "Saas",
+ "LanguageManagement": "Administrarea limbilor",
+ "TextTemplateManagement": "Text Template Management",
+ "SeeAllModules": "Vezi toate modulele",
+ "ABPSuite": "ABP Suite",
+ "AbpSuiteShortDescription": "ABP Suite este un instrument complementar pentru ABP Commercial.",
+ "AbpSuiteExplanation": "Vă permite să creaţi pagini web în câteva minute. Este un instrument .NET Core global, care poate fi instalat din linia de comandă. Poate crea o nouă soluţie ABP, poate genera pagini CRUD, începând de la baza de date până la front-end.",
+ "Details": "Detalii",
+ "LeptonTheme": "Tema Lepton",
+ "ProfessionalModernUIThemes": "Teme UI profesionale, moderne",
+ "LeptonThemeExplanation": "Lepton oferă o gamă de teme de administrare Bootstrap, care servesc ca o bază solidă pentru orice proiect care necesită tabloul de bord de administrare.",
+ "DefaultTheme": "Tema Default",
+ "MaterialTheme": "Tema Material",
+ "Default2Theme": "Tema Default 2",
+ "DarkTheme": "Tema Dark",
+ "DarkBlueTheme": "Tema Dark Blue",
+ "LightTheme": "Tema Light",
+ "ProudToWorkWith": "Mândru să lucrez cu",
+ "OurConsumers": "Sute de întreprinderi şi dezvoltatori din peste 50 de ţări din jurul lumii se bazează pe ABP Commercial.",
+ "JoinOurConsumers": "Alăturaţi-va lor şi construiţi produse uimitoare rapid.",
+ "AdditionalServicesExplanation": "Aveţi nevoie de servicii suplimentare sau personalizate? Noi şi partenerii noştri vi le putem oferi;",
+ "CustomProjectDevelopment": "Custom Project Development",
+ "CustomProjectDevelopmentExplanation": "Dezvoltatori dedicaţi pentru proiectele dumneavoastră personalizate.",
+ "PortingExistingProjects": "Portarea proiectelor existente",
+ "PortingExistingProjectsExplanation": "Migrarea proiectelor dumneavoastră vechi pe platforma ABP.",
+ "LiveSupport": "Asistenţă live",
+ "LiveSupportExplanation": "Opţiune de asistenţă live la distanţă oricând aveţi nevoie.",
+ "Training": "Instruire",
+ "TrainingExplanation": "Instruire dedicată pentru dezvoltatorii dumneavoastră.",
+ "OnBoarding": "Integrare",
+ "OnBoardingExplanation": "Ajutor pentru configurarea dezvoltării, mediilor CI & CD.",
+ "PrioritizedTechnicalSupport": "Asistenţă tehnică prioritară",
+ "PremiumSupportExplanation": "Pe lângă excelentul suport comunitar al framework-ului ABP, echipa noastră de asistenţă răspunde la întrebările tehnice şi la problemele utilizatorilor comerciali cu prioritate crescută.",
+ "SeeTheSupportOptions": "Vedeţi opţiunile de asistenţă",
+ "Contact": "Contact",
+ "TellUsWhatYouNeed": "Spuneţi-ne de ce aveţi nevoie.",
+ "YourMessage": "Mesajul dumneavoastră",
+ "YourFullName": "Numele dumneavoastră complet",
+ "EmailField": "Adresa de email",
+ "YourEmailAddress": "Adresa dumneavoastră de email",
+ "HowMayWeHelpYou": "Cum vă putem ajuta?",
+ "SendMessage": "Trimite mesaj",
+ "Success": "Succes",
+ "WeWillReplyYou": "Am primit mesajul dumneavoastră şi vă vom contacta cât de repede posibil.",
+ "GoHome": "Navigaţi acasă",
+ "CreateLiveDemo": "Crează Demo Live",
+ "RegisterToTheNewsletter": "Înregistraţi-va la newsletter pentru a primi informaţii despre ABP.IO, inclusiv lansări noi etc.",
+ "EnterYourEmailOrLogin": "Introduceţi-vă adresa de email pentru a vă crea demo-ul sau Autentificaţi-vă folosind contul existent.",
+ "ApplicationTemplate": "Application Template",
+ "ApplicationTemplateExplanation": "Şablonul de pornire a aplicaţiei este utilizat pentru a crea o nouă aplicaţie web.",
+ "EfCoreProvider": "Entity Framework (susţine SQL Server, MySQL, PostgreSQL, Oracle şi altele)",
+ "AlreadyIncludedInTemplateModules": "Următoarele module sunt deja incluse şi configurate în acest şablon:",
+ "ApplicationTemplateArchitecture": "Acest şablon de aplicaţie susţine arhitecturi structurate pe nivele, în care nivelul UI, nivelul API şi serviciul de autentificare sunt separate fizic.",
+ "SeeTheGuideOrGoToTheLiveDemo": "Consultaţi ghidul dezvoltatorului pentru informaţii tehnice despre acest şablon sau mergeţi la demo-ul live.",
+ "DeveloperGuide": "Ghidul dezvoltatorului",
+ "ModuleTemplate": "Module Template",
+ "ModuleTemplateExplanation1": "Vreţi să creaţi un modul pe care sa-l reutilizaţi în cadrul diferitelor aplicaţii? Acest şablon de pornire pregăteşte totul pentru a putea începe să creaţi un modul sau un microserviciu reutilizabil.",
+ "ModuleTemplateExplanation2": "
Puteţi susţine cadre UI simple sau multiple, furnizori unici sau multipli pentru baza de date pentru un singur modul. Şablonul de pornire este configurat pentru a rula şi testa modulul dumneavoastră într-o aplicaţie minimă, în plus faţă de infrastructura de testare şi integrare.
Consultaţi ghidul dezvoltatorului pentru informaţii tehnice despre acest şablon.
",
+ "WithAllStyleOptions": "cu toate opţiunile de stil",
+ "Demo": "Demo",
+ "SeeAllModules": "Vezi toate modulele",
+ "ABPCLIExplanation": "ABP CLI (Command Line Interface) este un instrument de linii de comandă pentru executarea unor operaţii comune pentru soluţiile ABP.",
+ "ABPSuiteEasilyCURD": "Suita ABP este un instrument care vă permite crearea cu uşurinţă a paginilor CRUD",
+ "WeAreHereToHelp": "Suntem aici să Ajutăm",
+ "BrowseOrAskQuestion": "Puteţi răsfoi subiectele noastre de ajutor sau puteţi căuta în cadrul secţiunii întrebărilor frecvent adresate, sau ne puteţi adresa o întrebare folosind formularul de contact.",
+ "SearchQuestionPlaceholder": "Caută în întrebările frecvent adresate",
+ "WhatIsTheABPCommercial": "Ce este ABP Commercial?",
+ "WhatAreDifferencesThanAbpFramework": "Care sunt diferenţele dintre ABP Framework şi ABP Comercial?",
+ "ABPCommercialExplanation": "ABP Commercial este un set de module premium, instrumente, teme şi servicii construite pe baza ABP framework. ABP Commercial este dezvoltat şi întreţinut de către aceeaşi echipă din spatele ABP framework.",
+ "WhatAreDifferencesThanABPFrameworkExplanation": "
ABP framework este un framework de dezvoltare de aplicaţii modulare, compatibil cu micro-servicii dedicate ASP.NET Core. Oferă o arhitectură completă şi o infrastructură puternică pentru a vă face să vă concentraţi asupra propriului cod, mai degrabă decât să vă repetaţi pentru fiecare proiect nou. Se bazează pe cele mai bune practici de dezvoltare software, şi pe instrumentele populare pe care le cunoaşteţi deja.
ABP Framework este complet gratuit, open-source şi bazat pe comunitate. De asemenea, oferă şi o temă gratuită şi câteva module pre-construite (de exemplu, gestionarea identităţii şi a chiriaşilor).
",
+ "VisitTheFrameworkVSCommercialDocument": "Accesaţi următorul link, pentru mai multe informaţii {1} ",
+ "ABPCommercialFollowingBenefits": "ABP Commercial adaugă următoarele beneficii peste framework-ul ABP;",
+ "Professional": "Profesional",
+ "UIThemes": "Teme UI",
+ "EnterpriseModules": "Module de aplicaţii pregătite pentru întreprinderi, bogate în funcţionalităţi, pre-construite (e.g. Identity Server management, SaaS management, language management)",
+ "ToolingToSupport": "Instrumente pentru a vă susţine productivitatea de dezvoltare (e.g. Suita ABP)",
+ "PremiumSupportLink": "Asistenţă premium",
+ "WhatDoIDownloadABPCommercial": "Ce descarc când cumpăr ABP Commercial?",
+ "CreateUnlimitedSolutions": "Odată ce aţi cumpărat o licenţă ABP Commercial, veţi putea să creaţi soluţii nelimitate, descrise în documentul Noţiuni de bază.",
+ "ABPCommercialSolutionExplanation": "Când creaţi o aplicaţie nouă, veţi primi o soluţie de Visual Studio (un şablon de pornire) bazat pe preferinţele dumneavoastră. Soluţia descărcată conţine module comerciale şi teme pre-instalate şi configurate pentru dumneavoastră. Puteţi şterge un modul pre-instalat sau să adăugaţi altul dacă doriţi. Toate modulele şi temele folosesc un pachet NuGet/NPM în mod implicit.",
+ "StartDevelopWithTutorials": "Soluţia descărcată este bine structurată şi documentată. Puteţi începe să vă dezvoltaţi codul dumneavoastră pe baza unuia dintre tutoriale",
+ "TryTheCommercialDemo": "Puteţi încerca versiunea demo pentru a vedea un exemplu de aplicaţie creată folosind şablonul de pornire ABP Commercial.",
+ "HowManyProducts": "Câte produse/soluţii diferite pot construi folosind ABP Commercial?",
+ "HowManyProductsExplanation": "Nu există nicio limită pentru crearea unui proiect ABP. Puteţi crea cât de multe proiecte doriţi, pe care să le dezvoltaţi sau încărcaţi pe diferite servere.",
+ "HowManyDevelopers": "Câţi dezvoltatori pot lucra pe ABP Commercial?",
+ "HowManyDevelopersExplanation": "Licenţele de ABP Commercial sunt per dezvoltator. Tipuri diferite de licenţă au limite diferite de dezvoltatori. Totuşi, puteţi ataşa mai mulţi dezvoltatori unei licenţe oricând doriţi. Consultaţi preţurile pentru tipurile de licenţă, limitele de dezvoltatori şi costurile adiţionale pentru dezvoltatori.",
+ "ChangingLicenseType": "Pe viitor pot să schimb tipul licenţei?",
+ "ChangingLicenseTypeExplanation": "Puteţi adăuga oricând noi dezvoltatori în licenţa dumneavoastră de acelaşi tip. Consultaţi \"Câţi dezvoltatori pot lucra pe ABP Commercial?\". De asemenea, puteţi opta pentru o licenţă superioară prin plătirea achitarea de preţ. Atunci când optaţi pentru o licenţă superioară, veţi avea parte de beneficiile noii licenţe, însă acest lucru nu va schimba data expirării licenţei.",
+ "LicenseExtendUpgradeDiff": "Care este diferenţa dintre prelungirea licenţei şi îmbunătăţirea acesteia?",
+ "LicenseExtendUpgradeDiffExplanation": "Prelungirea: Prin prelungirea/reînnoirea licenţei dumneavoastră, veţi continua să aveţi acces la asistenţă premium, şi veţi avea parte de actualizările majore ale modulelor şi temelor. Pe lângă asta, veţi putea în continuare să creaţi proiecte noi. Veţi putea folosi în continuare suita ABP, ceea ce va accelera dezvoltarea.Îmbunătăţirea: Prin îmbunătăţirea licenţei dumneavoastră, veţi promova la un plan de licenţă superior, care vă va permite să beneficiaţi de anumite avantaje. Consultaţi tabelul de comparare a licenţelor pentru a verifica diferenţele dintre planurile de licenţă.Pe de altă parte, când îmbunătăţiţi licenţa, data de expirare a acesteia nu se va schimba!Pentru a vă extinde data de încheiere a licenţei, va trebui să vă extindeţi licenţa.",
+ "LicenseRenewalCost": "Care este costul de reînnoire a licenţei dupa 1 an?",
+ "LicenseRenewalCostExplanation": "Rata de reînnoire (extindere) a tuturor licenţelor ABP Comercial reprezintă {0} din preţul listei licenţelor. Preţul de reînnoire a licenţei standard de echipă este de ${1}, cel pentru licenţa standard de afaceri este de ${2} iar cel pentru licenţa standard enterprise este de ${3}. Dacă deja sunteţi clientul nostru, autentificaţi-vă pentru a examina preţurile disponibile pentru reînnoire.",
+ "HowDoIRenewMyLicense": "Cum îmi reînnoiesc licenţa?",
+ "HowDoIRenewMyLicenseExplanation": "Puteţi să vă reînnoiţi licenţa prin accesarea paginii pagina de gestionare a organizaţiei. Pentru a profita de tarifele noastre reduse de reînnoire anticipată, asiguraţi-vă că reînnoiţi înainte de expirarea licenţei. Totuşi, nu vă faceţi griji dacă nu ştiţi când expiră oportunitatea dumneavoastră de reînnoire anticipată. Veţi primi 2 e-mailuri de reamintire înainte de expirarea abonamentului. Vi le vom trimite cu 30, respectiv 7 zile înainte de expirare.",
+ "IsSourceCodeIncluded": "Licenţa mea include şi codul sursă al modulelor comerciale şi a temelor?",
+ "IsSourceCodeIncludedExplanation1": "Depinde de tipul de licenţă pe care aţi achiziţionat-o:",
+ "IsSourceCodeIncludedExplanation2": "Team: Soluţia dumneavoastră foloseste modulele şi temele sub formă de pachete NuGet şi NPM. Nu include şi codul lor sursă. În acest mod, puteţi cu uşurinţă să îmbunătăţiţi aceste module şi teme oricând este o nouă versiune disponibilă. Totuşi, nu veţi primi codul sursă al modulelor şi temelor.",
+ "IsSourceCodeIncludedExplanation3": "Business/Enterprise: Pe lângă licenţa de tip Team, veţi putea să descărcaţi codul sursă al oricărui modul sau al oricărei teme doriţi. Puteţi chiar să eliminaţi referinţele pachetelor NuGet/NPM pentru un anume modul, şi să adăugaţi codul sursă al acestuia direct în soluţia dumneavoastră pentru a-l putea modifica pe deplin.",
+ "IsSourceCodeIncludedExplanation4": "
Includerea codului sursă al unui modul în soluţia dumneavoastră vă oferă libertate maximă de a personaliza modulul respectiv. Totuşi, atunci nu va fi posibilă actualizarea automată a modulului atunci când o nouă versiune este publicată.
Niciuna dintre licenţe nu include codul sursă al suitei ABP, care este un instrument extern care generează cod pentru dumneavoastră şi contribuie la dezvoltare.
Consultaţi preţurile pentru alte diferenţe între tipurile de licenţe.
",
+ "ChangingDevelopers": "Pe viitor, pot schimba dezvoltatorii ataşaţi organizaţiei mele?",
+ "ChangingDevelopersExplanation": "În plus faţă de adăugarea de noi dezvoltatori la licenţa dumneavoastră, puteţi schimba şi dezvoltatorii existenţi(puteţi elimina un dezvoltator şi adăuga unul nou în locul lui) fără costuri suplimentare.",
+ "WhatHappensWhenLicenseEnds": "Ce se întâmplă când se încheie perioada licenţei mele?",
+ "WhatHappensWhenLicenseEndsExplanation1": "Tipul de licenţă ABP Comercial este o licenţă perpetuă. După ce vă expiră licenţa, puteţi continua dezvoltarea proiectului dumneavoastră. Şi nu sunteţi obligat să vă reînnoiţi licenţa. Licenţa dumneavoastră vine la pachet cu actualizări şi plan de asistenţă valabile timp de un an. Pentru a continua să beneficiaţi de noi caracteristici, îmbunătăţiri de performanţe, corectarea erorilor, asistenţă şi să continuaţi să utilizaţi suita ABP, asiguraţi-vă că vă reînnoiţi licenţa anual. Când vă expiră licenţa, nu veţi mai beneficia de niciunul din beneficiile următoare;",
+ "WhatHappensWhenLicenseEndsExplanation2": "Nu puteţi crea noi soluţii folosind ABP Commercial, dar puteţi continua dezvoltarea aplicaţiilor existente oricând.",
+ "WhatHappensWhenLicenseEndsExplanation3": "You will be able to get updates for the modules and themes within your MAJOR version. For example; if you are using v3.2.0 of a module, you can still get updates for v3.x.x (v3.3.0, v3.5.2... etc.) of that module. But you cannot get updates for the next major version (like v4.x, v5.x)",
+ "WhatHappensWhenLicenseEndsExplanation4": "Nu puteţi instala noi module şi teme adăugate pe platforma ABP Comercial după ce se încheie licenţa dumneavoastră.",
+ "WhatHappensWhenLicenseEndsExplanation5": "Nu puteţi folosi suita ABP.",
+ "WhatHappensWhenLicenseEndsExplanation6": "Nu veţi mai avea parte de asistenţă premium.",
+ "WhatHappensWhenLicenseEndsExplanation7": "Puteţi să vă reînnoiţi abonamentul dacă vreţi să continuaţi să aveţi parte de aceste beneficii. Dacă vă reînnoiţi abonamentul în termen de o lună după ce vă expiră licenţa, vi se aplică un discount de 20%.",
+ "WhenShouldIRenewMyLicense": "Când ar trebui să-mi reînnoiesc licenţa?",
+ "WhenShouldIRenewMyLicenseExplanation1": "Dacă vă reînnoiţi licenţa în termen de 1 lună după ce vă expiră licenţa, se va aplica un discount de 20%.",
+ "WhenShouldIRenewMyLicenseExplanation2": "Dacă vă reînnoiţi licenţa la o lună după ce aceasta a expirat, preţul de reînnoire va fi acelaşi cu cel iniţial, şi nu va fi aplicat niciun discount pentru reînnoirea dumneavoastră.",
+ "TrialPlan": "Aveţi un plan de încercare?",
+ "TrialPlanExplanation": "Pentru moment, ABP Comercial nu include un plan de încercare. Pentru licenţa de Team oferim înapoirea banilor în termen de 30 de zile. Puteţi să solicitaţi o restituire în primele 30 de zile. Pentru licenţele de tip Business şi Enterprise, noi asigurăm restituirea a 60% din sumă în 30 de zile. Acest lucru se datorează faptului că licenţele de tip Business şi Enterprise includ codul sursă complet al tuturor modulelor şi temelor.",
+ "DoYouAcceptBankWireTransfer": "Acceptaţi transfer bancar?",
+ "DoYouAcceptBankWireTransferExplanation": "Da, acceptăm transfer bancar. După trimiterea taxei de licenţă prin transfer bancar, trimiteţi-ne pe e-mail la info@abp.io chitanţa dumneavoastră şi tipul de licenţă solicitat. Informaţiile despre contul bancar internaţional al nostru:",
+ "HowToUpgrade": "Cum se actualizează aplicaţiile existente atunci când este disponibilă o nouă versiune?",
+ "HowToUpgradeExplanation1": "Cand creaţi o nouă aplicaţie folosind ABP Commercial, toate modulele şi tema sunt folosite sub formă de pachete NuGet şi NPM. Astfel, puteţi cu uşurinţă să actualizaţi pachetele atunci când o versiune nouă este disponibilă.",
+ "HowToUpgradeExplanation2": "Pe lângă actualizările standard NuGet-NPM, ABP CLI furnizează o comandă de actualizare automată care identifică şi actualizează toate pachetele legate de ABP din soluţia dumneavoastră.",
+ "DatabaseSupport": "Ce sisteme de baze de date sunt suportate?",
+ "DatabaseSupportExplanation": "ABP Framework în sine este agnostic din punct de vedere al bazei de date, şi poate funcţiona cu orice furnizor de baze de date prin natura sa. Consultaţi documentul de acces la date pentru o listă a furnizorilor implementaţi până în clipa de faţă.",
+ "UISupport": "Ce UI frameworks sunt suportate?",
+ "Supported": "Suportat",
+ "UISupportExplanation": "ABP Framework în sine este agnostic din punct de vedere al UI framework şi poate funcţiona cu orice UI framework. Cu toate acestea, şabloanele de pornire, UI-urile modulelor şi temele nu au fost implementate pentru toate module UIs. Consultaţi documentul de început pentru lista actualizată a opţiunilor UI.",
+ "MicroserviceSupport": "Suportă arhitectura de micro-servicii?",
+ "MicroserviceSupportExplanation1": "Unul din scopurile principale ale ABP framework este să furnizeze o structură convenabilă pentru crearea soluţiilor micro-service. Consultaţi documentul arhitectura micro-service pentru a înţelege cum ajută la crearea sistemelor de micro-servicii.",
+ "MicroserviceSupportExplanation2": "Toate modulele ABP Commercial sunt dezvoltate pentru a suporta scenarii de implementare a micro-serviciilor (cu propriul API şi bază de date) prin respectarea celor mai bune practici de dezvoltare a modulelor.",
+ "MicroserviceSupportExplanation3": "Vă oferim soluţie demo de micro-servicii care demonstrează o implementare a arhitecturii de micro-servicii pentru a vă ajuta să vă creaţi propria soluţie.",
+ "MicroserviceSupportExplanation4": "Deci, răspunsul pe scurt este \"da, suportă o arhitectură de micro-service\".",
+ "MicroserviceSupportExplanation5": "Totuşi, un sistem de tip micro-service reprezintă o soluţie, şi fiecare soluţie va avea cerinţe diferite, topologie de reţea, scenarii de comunicare, posibilităţi de autentificare, separarea bazei de date/împărţirea deciziilor, configurări în timp real, integrări de sisteme terţe parte şi multe altele.",
+ "MicroserviceSupportExplanation6": "ABP Framework şi ABP Commercial furnizează infrastructura pentru scenarii de micro-servicii, module de micro-servicii compatibile, exemple şi documentaţie pentru a vă ajuta să vă construiţi propria soluţie. Dar nu vă aşteptaţi să descărcaţi direct soluţia visurilor dumneavoastră. Veţi fi nevoit(ă) să o întelegeţi şi să puneţi câteva piese cap la cap pe baza cerinţelor dumneavoastră.",
+ "WhereCanIDownloadSourceCode": "De unde pot descărca codul sursă?",
+ "WhereCanIDownloadSourceCodeExplanation": "Puteţi descărca codul sursă al tuturor modulelor ABP, pachetelor Angular şi al temelor prin suita ABP sau ABP CLI. Consultaţi Cum descarc codul sursă?",
+ "ComputerLimitation": "Pe câte calculatoare se poate autentifica un dezvoltator atunci când foloseşte ABP ABP?",
+ "ComputerLimitationExplanation": "Permitem în mod specific {0} staţii per dezvoltator individual/autorizat. Ori de câte ori este nevoie ca un dezvoltator să dezvolte produse ABP Commercial pe o altă staţie, un e-mail ar trebui să fie trimis la license@abp.io pentru a explica situaţia, şi atunci vom face alocarea corespunzătoare în sistemul nostru.",
+ "RefundPolicy": "Aveţi o politică de rambursare?",
+ "RefundPolicyExplanation": "Puteţi solicita un ramburs în decurs de 30 de zile de la cumpărarea licenţei. Licenţele de tip Business şi Enterprise au opţiune de descărcare a codului sursă, prin urmare rambursul nu este posibil pentru licenţele Business and Enterprise (şi pentru oricare altă licenţă care beneficiază de dreptul de a primi codul sursă). În plus, nu se fac rambursări pentru reînnoiri şi achiziţii de licenţe suplimentare.",
+ "HowCanIRefundVat": "Cum pot deduce TVA-ul?",
+ "HowCanIRefundVatExplanation1": "Dacă aţi făcut plata folosind 2Checkout, puteţi deduce TVA-ul în contul dumneavoastră 2Checkout:",
+ "HowCanIRefundVatExplanation2": "Autentificaţi-vă în contul dumneavoastră 2Checkout",
+ "HowCanIRefundVatExplanation3": "Găsiţi comanda respectivă şi apăsaţi pe \"Deducerea tardivă a TVA-ului \" (introduceţi CUI-ul dumneavoastră)",
+ "HowCanIGetMyInvoice": "Cum îmi pot obţine factura?",
+ "HowCanIGetMyInvoiceExplanation": "Există două procesatori de plăţi pentru cumpărarea unei licenţă: PayU şi 2Checkout. Dacă veţi cumpăra o licenţă prin procesatorul 2Checkout, vă va trimite chitanţa PDF pe adresa dumneavoastră de email, consultaţi facturarea 2Checkout. Dacă veţi cumpăra o licenţă prin procesatorul PayU gateway sau prin transfer bancar, vă vom pregăti chitanţa şi vă vom trimite. Puteţi solicita chitanţa dumneavoastră din pagina de gestionare a organizaţiei.",
+ "Forum": "Forum",
+ "SupportExplanation": "Licenţele ABP Commercial furnizează asistenţă premium pe forum din partea unei echipe alcătuite din experţi ai ABP.",
+ "PrivateTicket": "Tichet privat",
+ "PrivateTicketExplanation": "Licenţa de tip Enterprise include de asemenea şi asistenţă privată cu sisteme de e-mail şi tichete.",
+ "AbpSuiteExplanation1": "Suita ABP vă permite să construiţi pagini web în decurs de câteva minute. Este un instrument global .NET Core care poate fi instalat din linia de comandă.",
+ "AbpSuiteExplanation2": "Poate crea o nouă soluţie ABP, genera paginii CRUD începând de la baza de date şi până la front-end. Pentru o prezentare tehnică consultaţi documentul",
+ "FastEasy": "Rapid şi usor",
+ "AbpSuiteExplanation3": "Suita ABP vă permite să creaţi pagini CRUD cu uşurinţă. Trebuie doar să vă definiţi entitatea şi proprietăţile sale, şi să lăsaţi restul în seama suitei ABP! Suita ABP generează tot codul necesar pentru pagina dumneavoastră CRUD în câteva secunde. Suportă interfeţe de utilizator Angular, MVC şi Blazor.",
+ "RichOptions": "Opţiuni ample",
+ "AbpSuiteExplanation4": "Suita ABP suportă multiple opţiuni UI precum Pagini Razor şi Angular. Suportă de asemenea şi baze de date multiple, precum MongoDB şi toate bazele de date suportate de EntityFramework Core (MS SQL Server, Oracle, MySql, PostgreSQL şi altele).",
+ "AbpSuiteExplanation5": "Partea bună este că dumneavoastră nu trebuie să vă faceţi griji despre aceste opţiuni. Suita ABP înţelege tipul proiectului dumneavoastră şi generează cod pentru proiectul dumneavoastră şi îl plasează în locul potrivit din proiect.",
+ "SourceCode": "Cod sursă",
+ "AbpSuiteExplanation6": "Suita ABP generează codul sursă pentru dumneavoastră! Nu generează fişiere magice pentru a genera pagina web. Suita ABP generează codul sursă petnru Entity, Repository, Application Service, Code First Migration, JavaScript/TypeScript şi CSHTML/HTML şi interfeţele necesare de asemenea. Suita ABP generează de asemenea codul respectând Cele mai bune practici ale dezvoltării software, deci nu trebuie să vă faceţi griji în legătură cu calitatea codului generat.",
+ "AbpSuiteExplanation7": "Deoarece aveţi codul sursă al blocurilor de construcţie ale paginii CRUD generate în straturile de aplicaţie corecte, puteţi modifica cu uşurinţă codul sursă şi puteţi injecta logica personalizată/business a codului generat.",
+ "CrossPlatform": "Platformă transversală",
+ "AbpSuiteExplanation8": "Suita ABP este construită cu .NET Core şi este o platformă transversală. Se execută ca o aplicaţie web pe calculatorul dumneavoastră local. O puteţi rula pe Windows, Mac şi Linux",
+ "OtherFeatures": "Alte funcţionalităţi",
+ "OtherFeatures1": "Actualizeată pachetele NuGet şi NPM din soluţia dumneavoastră cu uşurinţă.",
+ "OtherFeatures2": "Regenerează paginile deja generate de la zero.",
+ "OtherFeatures3": "Crează noi soluţii",
+ "ThanksForCreatingProject": "Mulţumim pentru că v-aţi creat proiectul!",
+ "HotToRunSolution": "Cum să rulaţi soluţia dumneavoastră?",
+ "HotToRunSolutionExplanation": "Consultaţi documentul de noţiuni de bază pentru a învăţa cum să vă configuraţi şi rulaţi aplicaţia.",
+ "GettingStarted": "Noţiuni de bază",
+ "WebAppDevTutorial": "Tutorial Web App Dev",
+ "WebAppDevTutorialExplanation": "Consultaţi tutorialul de dezvoltare a aplicaţiilor web pentru un exemplu de dezvoltare pas cu pas.",
+ "Document": "Document",
+ "UsingABPSuiteToCURD": "Folosind suita ABp pentru generarea şi utilizarea paginilor CRUD",
+ "SeeABPSuiteDocument": "Consultaţi documentaţia suitei ABP pentru a învăţa utilizarea suitei ABP.",
+ "AskQuestionsOnSupport": "Puteţi adresa întrebări pe ABP Commercial Support.",
+ "Documentation": "Documentaţie",
+ "SeeModulesDocument": "Consultaţi documentul modulelor pentru lista tuturor modulelor comerciale (pro) şi documentele acestora.",
+ "Pricing": "Preţuri",
+ "PricingExplanation": "Alegeţi caracteristicile şi funcţionalitatea nevoilor afacerii dumneavoastră acum. Actualizaţi-le cu uşurinţă pe măsură ce afacerea dumneavoastră se dezvoltă.",
+ "Team": "Team",
+ "Business": "Business",
+ "Enterprise": "Enterprise",
+ "Custom": "Personalizat",
+ "IncludedDeveloperLicenses": "Licenţe de dezvoltator incluse",
+ "CustomLicenceOrAdditionalServices": "Aveţi nevoie de o licenţă personalizată sau de servicii suplimentare?",
+ "CustomOrVolumeLicense": "Licenţă personalizată sau de volum",
+ "LiveTrainingSupport": "Instruire şi asistenţă în timp real",
+ "AndMore": "şi multe altele",
+ "AdditionalDeveloperLicense": "Licenţă suplimentară de dezvoltator",
+ "ProjectCount": "Număr de proiecte",
+ "AllProModules": "Toate modulele pro",
+ "AllProThemes": "Toate temele pro",
+ "AllProStartupTemplates": "Toate şabloanele de pornire pro",
+ "SourceCodeOfAllModules": "Codul sursă al tuturor modulelor",
+ "SourceCodeOfAllThemes": "Codul sursă al tuturor temelor",
+ "PerpetualLicense": "Licenţă perpetuă",
+ "UnlimitedServerDeployment": "Implementări nelimitate a serverului",
+ "YearUpgrade": "actualizare de 1 an",
+ "YearPremiumForumSupport": "Asistenţă premium pe forum de 1 an",
+ "ForumSupportIncidentCountYear": "Asistenţă pe forum număr de incidente/an",
+ "PrivateTicketEmailSupport": "Tichet privat şi asistenţă pe email",
+ "BuyNow": "Cumpără acum",
+ "PayViaAmexCard": "Cum pot plăti folosind cardul meu AMEX?",
+ "PayViaAmexCardDescription": "Procesatorul implicit 'Iyzico' s-ar putea să refuze anumite carduri AMEX ca măsură de securitate. În acest caz, puteţi plăti prin procesatorul alternativ '2Checkout'.",
+ "ThankYou": "Vă mulţumim",
+ "InvalidReCaptchaErrorMessage": "A intervenit o eroare în verificarea reCAPTCHA. Vă rugăm să încercaţi din nou.",
+ "CompanyName": "Nume companie",
+ "YourCompanyName": "Numele companiei dumneavoastră",
+ "FirstName": "Nume",
+ "LastName": "Prenume",
+ "Optional": "Opţional",
+ "YourFirstName": "Numele dumneavoastră",
+ "YourLastName": "Prenumele dumneavoastră",
+ "SpecialOffer": "Ofertă specială",
+ "SpecialOfferMessage": "Grăbiţi-vă! Preţurile sunt disponibile pentru o perioadă limitată.",
+ "DiscountRequest": "Cerere de discount",
+ "DiscountRequestDescribeCustomerQuestion": "Care din următoarele vă descrie?",
+ "DiscountRequestStudentEmailMessage": "Adresa de email trebuie să conţină 'edu'.",
+ "DiscountRequestDeveloperCount": "Câţi dezvoltatori aveţi?",
+ "DiscountRequestDeveloperCountExceedMessage": "Nu furnizăm licenţe reduse pentru companii care au peste {0} dezvoltatori.",
+ "DiscountRequestOrganizationName": "Numele companiei/organizaţiei/şcolii",
+ "Website": "Site web",
+ "GithubUsername": "Nume de utilizator GitHub",
+ "PhoneNumber": "Număr de telefon",
+ "Country": "Ţara",
+ "DescribeABPCommercialUsage": "Descrieţi proiectul pe care folosiţi să-l dezvoltaţi pe baza APB Commercial",
+ "DiscountRequestCertifyInformationMessage": "Certific că toate informaţiile sunt adevărate şi corecte.",
+ "DiscountRequestReceived": "Am primit solicitarea dumneavoastră de reducere.",
+ "DiscountRequestStatusMessage": "Vă vom răspunde după verificarea informaţiilor pe care le-aţi furnizat.",
+ "MVCOrRazorPages": "MVC (Razor Pages)",
+ "Angular": "Angular",
+ "Blazor": "Blazor",
+ "New": "New",
+ "MongoDB": "MongoDB",
+ "EBookDDD": "E-Book Domain Driven Design",
+ "PracticalGuideForImplementingDDD": "Această carte reprezintă un ghid practic pentru implementarea proiectării bazate pe domeniu în ABP Framework.",
+ "IntroducingDDD": "Introducing Domain Driven Design",
+ "DDDLayersAndCleanArchitecture": "DDD Layers & Clean Architecture",
+ "LayeringOfADotnetSolution": "Layering of a .NET Solution",
+ "ImplementingDDDBuildingBlocks": "Implementing DDD Building Blocks",
+ "DomainVsApplicationLogic": "Domain Logic vs Application Logic",
+ "SamplesAndDiscussions": "Exemple & Discuţii",
+ "Free": "Gratuit",
+ "Download": "Descarcă",
+ "DDDEBook": "DDD E-book",
+ "ImplementingDDD": "Implementing Domain Driven Design",
+ "DDDBookExplanation": "Ghid practic pentru implementarea proiectării bazate pe domeniu în ABP Framework.",
+ "Overview": "Prezentare generală",
+ "DDDBookPracticalGuide": "Acesta este un ghid practic pentru implementarea proiectării bazate pe domeniu (PBD). În timp ce detaliile de implementare se bazeată pe infrastructura ABP, conceptele de bază, principiile şi modelele sunt aplicabile în orice fel de soluţie, chiar dacă nu este o soluţie .NET.",
+ "TableOfContents": "Cuprins",
+ "IntroductionToImplementingDDD": "Introducere în implementarea proiectării bazate pe domeniu",
+ "WhatIsDDD": "Ce este proiectarea bazată pe domeniu?",
+ "Implementation": "Implementare",
+ "TheBigPicture": "Imaginea de ansamblu",
+ "TheBuildingBlock": "The Building Block",
+ "ExampleUseCase": "Exemplu de utilizare",
+ "DomainAndApplicationLogic": "Domain Logic & Application Logic",
+ "Author": "Autor",
+ "PublishedOn": "Publicat în",
+ "Page": "Pagina",
+ "FreeEBook": "E-Book gratuit",
+ "EBookSignInForDownload": "Pentru a descărca e-book-ul trebuie să vă autentificaţi",
+ "SignIn": "Autentificare",
+ "Or": "Sau",
+ "TellUsAboutYourself": "Spuneţi-ne despre dumneavoastră",
+ "Surname": "Nume",
+ "DoYouAgreePrivacyPolicy": "Sunt de acord cu Termenii şi condiţiile şi Politica de confidenţialitate.",
+ "VolosoftMarketingInformationMessage": "Sunt de acord să primesc informaţii, sfaturi şi oferte despre soluţii pentru afaceri şi organizaţii şi alte produse şi servicii Volosoft.",
+ "VolosoftSharingInformationMessage": "Sunt de acord ca Volosoft să partajeze informaţiile mele cu partenerii selectaţi astfel încât să primesc informaţii relevante despre produsele şi serviciile lor.",
+ "WeWillSendYouADownloadLink": "Un link pentru descărcarea e-book-ului a fost trimis către {0}. Verificaţi-vă căsuţele de inbox / junk / spam!",
+ "InvalidFormInputs": "Vă rugăm să introduceţi informaţia validă specificată în formular.",
+ "DDDBookEmailBody": "Vă mulţumim. Pentru a descărca e-book-ul, click aici.",
+ "FreeDDDEBook": "DDD E-Book gratuit"
+ }
+}
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json
new file mode 100644
index 0000000000..7b93754482
--- /dev/null
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/ro-RO.json
@@ -0,0 +1,147 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "Permission:CommunityArticle": "Articol comunitar",
+ "Permission:Edit": "Modifică",
+ "Waiting": "În aşteptare",
+ "Approved": "Aprobat",
+ "Rejected": "Respins",
+ "Wait": "Pune în aşteptare",
+ "Approve": "Aprobă",
+ "Reject": "Respinge",
+ "ReadArticle": "Citeşte articolul",
+ "Status": "Starea",
+ "ContentSource": "Sursa conţinutului",
+ "Details": "Detalii",
+ "Url": "Url",
+ "Title": "Titlu",
+ "CreationTime": "Data creării",
+ "Save": "Salvează",
+ "SameUrlAlreadyExist": "Dacă doriţi să adăugaţi acest articol, ar trebui să schimbaţi adresa Url, întrucât aceeaşi adresa url există deja!",
+ "UrlIsNotValid": "Url-ul nu este valid.",
+ "UrlNotFound" : "Url nu a fost găsit.",
+ "UrlContentNotFound": "Conţinutul url-ului nu a fost găsit.",
+ "Summary": "Rezumat",
+ "MostRead": "Cele mai citite",
+ "Latest": "Recente",
+ "ContributeAbpCommunity": "Contribuiţi la comunitatea ABP",
+ "SubmitYourArticle": "Trimiteţi-vă postul",
+ "ContributionGuide": "Ghid de contribuţie",
+ "BugReport": "Raportează eroare",
+ "SeeAllArticles": "Vezi toate postările",
+ "WelcomeToABPCommunity!": "Bun venit în comunitatea ABP!",
+ "MyProfile": "Profilul meu",
+ "MyOrganizations": "Organizaţia mea",
+ "EmailNotValid": "Vă rugăm să introduceţi o adresa de email validă.",
+ "FeatureRequest": "Cerere de funcţionalitate",
+ "CreateArticleTitleInfo": "Titlul postării care va apărea în lista postărilor.",
+ "CreateArticleSummaryInfo": "Un scurt rezumat al postării care va apărea în lista postărilor.",
+ "CreateArticleCoverInfo": "Pentru crearea unei postări eficace, adăugaţi o poză de copertă. Încărcaţi imagini cu raport de aspect 16:9 pentru cea mai bună vizualizare. Dimensiunea maximă a fişierului: 1MB.",
+ "ThisExtensionIsNotAllowed": "Această extensie nu este permisă.",
+ "TheFileIsTooLarge": "Dimensiunea fişierului este prea mare.",
+ "GoToTheArticle": "Vezi articolul",
+ "Contribute": "Contribuie",
+ "OverallProgress": "Progres total",
+ "Done": "Gata",
+ "Open": "Deschide",
+ "Closed": "Închis",
+ "LatestQuestionOnThe": "Ultima întrebare de pe",
+ "Stackoverflow": "Stackoverflow",
+ "Votes": "voturi",
+ "Answer": "Răspunde",
+ "Views": "vizualizări",
+ "Answered": "Răspunse",
+ "WaitingForYourAnswer": "În aşteptarea răspunsului dumneavoastră",
+ "Asked": "întrebate",
+ "AllQuestions": "Toate întrebările",
+ "NextVersion": "Următoarea versiune",
+ "MilestoneErrorMessage": "Nu s-au putut obţine detaliile de referinţă actuale de pe Github.",
+ "QuestionItemErrorMessage": "Nu s-au putut obţine detaliile de referinţă actuale de pe Stackoverflow.",
+ "Oops": "Oops!",
+ "CreateArticleSuccessMessage": "Articolul a fost trimis cu succes. Va fi publicat după ce va fi revizuit de un administrator al site-ului.",
+ "ChooseCoverImage": "Alegeţi o poză de copertă...",
+ "CoverImage": "Poză de copertă",
+ "ShareYourExperiencesWithTheABPFramework": "Împărtăşiţi-vă experienţele cu ABP Framework!",
+ "Optional": "Opţional",
+ "UpdateUserWebSiteInfo": "Exemplu: https://johndoe.com",
+ "UpdateUserTwitterInfo": "Exemplu: johndoe",
+ "UpdateUserGithubInfo": "Exemplu: johndoe",
+ "UpdateUserLinkedinInfo": "Exemplu: https://www.linkedin.com/...",
+ "UpdateUserCompanyInfo": "Exemplu: Volosoft",
+ "UpdateUserJobTitleInfo": "Exemplu: Software Developer",
+ "UserName": "Nume de utilizator",
+ "Company": "Companie",
+ "PersonalWebsite": "Site web personal",
+ "RegistrationDate": "Data înregistrării",
+ "Social": "Social",
+ "Biography": "Biografie",
+ "HasNoPublishedArticlesYet": "nu a publicat niciun articol încă",
+ "Author": "Autor",
+ "LatestGithubAnnouncements": "Ultimele anunţuri de pe Github",
+ "SeeAllAnnouncements": "Vezi toate anunţurile",
+ "LatestBlogPost": "Ultima postare de pe blog",
+ "Edit": "Modifică",
+ "ProfileImageChange": "Schimbă poza de profil",
+ "BlogItemErrorMessage": "Nu s-au putut obţine detaliile ultimei postări de pe from ABP.",
+ "PlannedReleaseDate": "Data planificată de lansare",
+ "CommunityArticleRequestErrorMessage": "Nu s-a putut obţine ultima cerere de articol de pe Github.",
+ "ArticleRequestFromGithubIssue": "Momentan nu există cereri de articole.",
+ "LatestArticles": "Ultimele postări",
+ "ArticleRequests": "Cereri de articole",
+ "AllArticleRequests": "Vedeţi toate cererile de articole",
+ "SubscribeToTheNewsletter": "Abonaţi-vă la newsletter-ul nostru",
+ "NewsletterEmailDefinition": "Obţineţi informaţii despre evenimentele din ABP, cum ar fi lansări noi, surse gratuite, articole şi multe altele.",
+ "NoThanks": "Nu, mulţumesc",
+ "MaybeLater": "Poate mai târziu",
+ "JoinOurArticleNewsletter": "Abonaţi-vă la newsletter-ul nostru de articole",
+ "Community": "Comunitate",
+ "Marketing": "Marketing",
+ "CommunityPrivacyPolicyConfirmation": "Sunt de acord cu termenii şi condiţiile şi politica de confidenţialitate.",
+ "ArticleRequestMessageTitle": "Deschideţi o problemă pe GitHub pentru a solicita un articol/tutorial pe care doriţi să îl vedeţi pe acest site web.",
+ "ArticleRequestMessageBody": "Aici, lista articolelor solicitate de către comunitate. Doriţi să scrieţi un articol solicitat? Vă rugăm să daţi click pe cerere şi să vă alăturaţi discuţiei.",
+ "Language": "Limba",
+ "CreateArticleLanguageInfo": "Limba pentru conţinutul postării.",
+ "VideoPost": "Post video",
+ "Article": "Articol",
+ "Read": "Citeşte",
+ "CreateGithubArticleUrlInfo": "Adresa URL originală GitHub a articolului.",
+ "CreateVideoContentUrlInfo": "Adresa URL originală YouTube a articolului",
+ "CreateExternalArticleUrlInfo": "Adresa URL originală externă a articolului.",
+ "VideoContentForm": "Trimite videoclip pe YouTube",
+ "GithubPostForm": "Trimite articol pe GitHub",
+ "ExternalPostForm": "Trimite un conţinut extern",
+ "HowToPost": "Cum postez?",
+ "Posts": "Postări",
+ "VideoUrl": "Url Video",
+ "GithubArticleUrl": "Adresa Url articol Github",
+ "ExternalArticleUrl": "Adresa Url externă Article",
+ "CreatePostCoverInfo": "Pentru crearea unei postări eficace, adăugaţi o poză de copertă. Încărcaţi imagini cu raport de aspect 16:9 pentru cea mai bună vizualizare. Dimensiunea maximă a fişierului: 1MB.",
+ "ThankYouForContribution": "Vă mulţumim pentru că aţi contribuit la comunitatea ABP.",
+ "GithubArticle": "Articol GitHub",
+ "GithubArticleSubmitStepOne": "1. Scrieţi un articol pe orice repository GitHub folosind formatul Markup. exemplu",
+ "GithubArticleSubmitStepTwo": "2. Trimiteţi Url-ul articolului folosind formularul.",
+ "GithubArticleSubmitStepThree": "3. Articolul dumneavoastră va fi redat în acest site web.",
+ "YoutubeVideo": "Videoclip YouTube",
+ "YoutubeVideoSubmitStepOne": "1. Publicaţi-vă videoclipul pe YouTube.",
+ "YoutubeVideoSubmitStepTwo": "2. Trimieţi Url-ul videoclipului folosind formularul.",
+ "YoutubeVideoSubmitStepThree": "3. Vizitatorii vor putea să vă vizioneze conţinutul video direct de pe acest site web.",
+ "ExternalContent": "Conţinut extern",
+ "ExternalContentSubmitStepOne": "1. Creaţi conţinut pe orice platformă publică (mediu, blogul dumneavoastră sau oriunde doriţi).",
+ "ExternalContentSubmitStepTwo": "2. Trimiteţi-vă conţinutul URL folosind formularul.",
+ "ExternalContentSubmitStepThree": "3. Vizitatorii sunt redirecţionaţi către conţinutul de pe site-ul web original.",
+ "ChooseYourContentType": "Vă rugăm să alegeţi modalitatea pri ncare vreţi să vă adăugaţi conţinutul.",
+ "PostContentViaGithub": "Vreau să adaug articolul meu de pe GitHub conform cu regulile de reducere.",
+ "PostContentViaYoutube": "Vreau să distribui videoclipurile mele disponibile de pe YouTube aici.",
+ "PostContentViaExternalSource": "Vreau să adaug conţinutul pe care l-am publicat pe altă platformă aici.",
+ "GitHubUserNameValidationMessage": "Numele de utilizator al contului dumneavoastră de GitHub nu poate conţine spaţii goale, vă rugăm să verificaţi că numele de utilizator al contului dumneavoastră de GitHub este corect.",
+ "PersonalSiteUrlValidationMessage": "Url-ul site-ului dumneavoastră personal nu poate conţine spaţii goale, vă rugăm să verificaţi ca Url-ul site-ului dumneavoastră personal este corect.",
+ "TwitterUserNameValidationMessage": "Url-ul dumneavoastră de Twitter nu poate conţine spaţii goale, vă rugăm să verificaţi ca Url-ul de Twitter este corect.",
+ "LinkedinUrlValidationMessage": "Url-ul dumneavoastră de LinkedIn nu poate conţine spaţii goale, vă rugăm să verificaţi ca Url-ul de LinkedIn este corect.",
+ "NoPostsFound": "Nu s-au găsit postări!",
+ "SearchInPosts": "Caută în postări...",
+ "MinimumSearchContent": "Trebuie să introduceţi cel putin 3 caractere!",
+ "Volo.AbpIo.Domain:060001": "Sursa URL(\"{ArticleUrl}\") nu este URL GitHub",
+ "Volo.AbpIo.Domain:060002": "Conţinutul articolului nu este disponibil din resursa de pe GitHub(\"{ArticleUrl}\").",
+ "Volo.AbpIo.Domain:060003": "Nu a fost găsit conţinutul articolului!"
+ }
+}
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Docs/Localization/Resources/ro-RO.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Docs/Localization/Resources/ro-RO.json
new file mode 100644
index 0000000000..c5a76c1617
--- /dev/null
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Docs/Localization/Resources/ro-RO.json
@@ -0,0 +1,5 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ }
+}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Support/Localization/Resources/ro-RO.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Support/Localization/Resources/ro-RO.json
new file mode 100644
index 0000000000..c5a76c1617
--- /dev/null
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Support/Localization/Resources/ro-RO.json
@@ -0,0 +1,5 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ }
+}
\ No newline at end of file
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ro-RO.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ro-RO.json
new file mode 100644
index 0000000000..8115eed091
--- /dev/null
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/ro-RO.json
@@ -0,0 +1,278 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "GetStarted": "Începeţi - Şabloane de pornire",
+ "Create": "Creează",
+ "NewProject": "Proiect nou",
+ "DirectDownload": "Descărcare directă",
+ "ProjectName": "Nume proiect",
+ "ProjectType": "Tip proiect",
+ "DatabaseProvider": "Provider bază de date",
+ "DatabaseManagementSystem": "Sistem de administrare bază de date",
+ "NTier": "N-Tier",
+ "IncludeUserInterface": "Include interfaţa userului",
+ "CreateNow": "Creează acum",
+ "TheStartupProject": "Proiectul de pornire",
+ "Tutorial": "Tutorial",
+ "UsingCLI": "Folosind CLI",
+ "SeeDetails": "Vedeţi detalii",
+ "AbpShortDescription": "ABP Framework este o infrastructură completă pentru crearea aplicaţiilor moderne web prin folosirea celor mai bune practici şi convenţii de dezvoltare software.",
+ "SourceCodeUpper": "COD SURSĂ",
+ "LatestReleaseLogs": "Cele mai recente jurnale de lansare",
+ "Infrastructure": "Infrastructura",
+ "Architecture": "Arhitectura",
+ "Modular": "Modular",
+ "DontRepeatYourself": "Nu vă repetaţi",
+ "DeveloperFocused": "Axat pe dezvoltator",
+ "FullStackApplicationInfrastructure": "Infrastructură de aplicaţii full stack.",
+ "DomainDrivenDesign": "Domain Driven Design",
+ "DomainDrivenDesignExplanation": "Proiectat şi dezvoltat pe baza modelelor şi principiilor DDD. Oferă un model stratificat pentru aplicaţia dumneavoastră.",
+ "Authorization": "Autorizare",
+ "AuthorizationExplanation": "Autorizare avansată pe bază de utilizator, rol şi sistem de permisiuni. Construit pe biblioteca Microsoft Identity.",
+ "MultiTenancy": "Multi-Tenancz",
+ "MultiTenancyExplanationShort": "Aplicaţii SaaS simplificate! Multi-Tenancy integrată de la baza de date până la UI.",
+ "CrossCuttingConcerns": "Cross Cutting Concerns",
+ "CrossCuttingConcernsExplanationShort": "Infrastructură completă pentru autorizare, validare, gestionarea excepţiilor, stocarea în cache, înregistrarea auditului, gestionarea tranzacţiilor şi multe altele.",
+ "BuiltInBundlingMinification": "Grupare şi minificare incorporate",
+ "BuiltInBundlingMinificationExplanation": "Nu este nevoie să utilizaţi instrumente externe pentru grupare şi minificare. ABP oferă un mod mai simplu, dinamic, puternic, modular şi incorporat!",
+ "VirtualFileSystem": "Sistem de fişiere virtuale",
+ "VirtualFileSystemExplanation": "Încorporaţi view-uri, scripturi, stiluri, imagini... in pachete/librării şi refolosiţi-le în diferite aplicaţii.",
+ "Theming": "Tematică",
+ "ThemingExplanationShort": "Utilizaţi şi personalizaţi tema UI standard, bazată pe UI, sau creaţi-o pe a dumneavoastră.",
+ "BootstrapTagHelpersDynamicForms": "Bootstrap Tag Helpers & Dynamic Forms",
+ "BootstrapTagHelpersDynamicFormsExplanation": "În loc să scrieţi manual detaliile repetate ale componentelor bootstrap, utilizaţi tag helperele ABP pentru a simplifica şi profita de inteligenţă. Construiţi rapid formulare de interfaţă bazate pe un model C# utilizând ajutorul pentru formulare dinamice.",
+ "HTTPAPIsDynamicProxies": "HTTP APIs & Dynamic Proxies",
+ "HTTPAPIsDynamicProxiesExplanation": "Expuneţi automat serviciile aplicaţiilor sub formă de API-uri HTTP şi folosiţi-le cu JavaScript dinamic si proxy C#.",
+ "CompleteArchitectureInfo": "Arhitectură modernă pentru a crea soluţii software care pot fi întreţinute.",
+ "DomainDrivenDesignBasedLayeringModelExplanation": "Vă ajută să implementaţi o arhitectură stratificată DDD şi să construiţi o bază de cod uşor de întreţinut.",
+ "DomainDrivenDesignBasedLayeringModelExplanationCont": "Oferă şabloane de pornire, abstractizări, clase de bază, servicii, documentaţie şi ghiduri pentru a vă ajuta să vă dezvoltaţi aplicaţia bazându-vă pe principiile şi tiparele DDD.",
+ "MicroserviceCompatibleModelExplanation": "Framework-ul de bază şi modulele pre-construite sunt proiectate având în vedere arhitectura microservice.",
+ "MicroserviceCompatibleModelExplanationCont": "Oferă infrastructură, integrări, exemple şi documentaţie pentru a implementa mai uşor soluţiile de microservicii, în timp ce nu aduce complexitate suplimentară dacă doriţi o aplicaţie monolitică.",
+ "ModularInfo": "ABP oferă un sistem de module care vă permite să dezvoltaţi module de aplicaţie reutilizabile, să vă conectaţi la evenimentele din ciclul de viaţă ale aplicaţiei şi să exprimaţi dependenţe între părţile centrale ale sistemului dumneavoastră.",
+ "PreBuiltModulesThemes": "Module şi teme pro-construite.",
+ "PreBuiltModulesThemesExplanation": "Modulele şi temele open source sunt gata de utilizare în aplicaţia dumneavoastră.",
+ "NuGetNPMPackages": "Pachete NuGet & NPM",
+ "NuGetNPMPackagesExplanation": "Distribuite sub formă de pachete NuGet & NPM. Uşor de instalat şi actualizat.",
+ "ExtensibleReplaceable": "Extensibil/Înlocuibil",
+ "ExtensibleReplaceableExplanation": "Toate serviciile şi modulele sunt dezvoltate pentru extensibilitate. Puteţi înlocui servicii, pagini, stiluri şi componente.",
+ "CrossCuttingConcernsExplanation2": "Menţineţi baza codului redusă, astfel încât să vă puteţi concentra asupra codului care e specific afacerii dumneavoastră.",
+ "CrossCuttingConcernsExplanation3": "Nu pierdeţi timp implementând cerinţe comune de aplicaţie pentru mai multe proiecte.",
+ "AuthenticationAuthorization": "Autentificare & Autorizare",
+ "ExceptionHandling": "Tratarea excepţiilor",
+ "Validation": "Validare",
+ "DatabaseConnection": "Conectare la baza de date",
+ "TransactionManagement": "Administrarea tranzacţiilor",
+ "AuditLogging": "Audit Logging",
+ "Caching": "Caching",
+ "Multitenancy": "Multitenancy",
+ "DataFiltering": "Filtrarea datelor",
+ "ConventionOverConfiguration": "Convention Over Configuration",
+ "ConventionOverConfigurationExplanation": "ABP implementează convenţii de aplicaţii comune în mod implicit, cu o configuraţie minimă sau zero.",
+ "ConventionOverConfigurationExplanationList1": "Auto înregistrează serviciile cunoscute pentru injectarea dependinţei..",
+ "ConventionOverConfigurationExplanationList2": "Expune serviciile aplicaţiei ca API-uri HTTP prin convenţii de denumire.",
+ "ConventionOverConfigurationExplanationList3": "Creează proxy-uri dinamice HTTP client pentru C# şi JavaScript.",
+ "ConventionOverConfigurationExplanationList4": "Oferă repository-uri implicite pentru entităţile dumneavoastră.",
+ "ConventionOverConfigurationExplanationList5": "Gestionează unitatea de lucru pe request web sau metodă de serviciu a aplicaţiei.",
+ "ConventionOverConfigurationExplanationList6": "Publică crearea, actualizarea şi ştergerea evenimentelor pentru entităţile dumneavoastră.",
+ "BaseClasses": "Clase de bază",
+ "BaseClassesExplanation": "Clase de bază pre-construite pentru tipare comune de aplicaţie.",
+ "DeveloperFocusedExplanation": "ABP este pentru dezvoltatori.",
+ "DeveloperFocusedExplanationCont": "Aceasta îşi propune să vă simplifice dezvoltarea zilnică de software, fără a vă restricţiona să scrieţi cod de nivel scăzut.",
+ "SeeAllFeatures": "Vedeţi toate funcţionalităţile",
+ "CLI_CommandLineInterface": "CLI (Command Line Interface)",
+ "CLI_CommandLineInterfaceExplanation": "Include un CLI pentru a vă ajuta să automatizaţi crearea de noi proiecte şi adăugarea de noi module.",
+ "StartupTemplates": "Proiecte de lansare",
+ "StartupTemplatesExplanation": "Diverse proiecte de lansare furnizează o soluţie complet configurată pentru a vă începe dezvoltarea.",
+ "BasedOnFamiliarTools": "Bazat pe instrumente familiare",
+ "BasedOnFamiliarToolsExplanation": "Construit şi integrat cu instrumente populare pe care le ştiţi deja. Curbă de învăţare joasă, adaptare uşoară, dezvoltare confortabilă.",
+ "ORMIndependent": "ORM Independent",
+ "ORMIndependentExplanation": "Framework-ul de bază este independent de ORM/bază de date şi poate funcţiona cu orice sursă de date. Furnizorii Entity Framework Core şi MongoDB sunt deja disponibili.",
+ "Features": "Exploraţi caracteristicile framework-ului ABP Framework",
+ "ABPCLI": "ABP CLI",
+ "Modularity": "Modularitate",
+ "BootstrapTagHelpers": "Bootstrap Tag Helpers",
+ "DynamicForms": "Formulare dinamice",
+ "BundlingMinification": "Grupare & Minificare",
+ "BackgroundJobs": "Background Jobs",
+ "BackgroundJobsExplanation": "Definiţi clase simple pentru a executa task-uri în fundal, aşezate în coadă. Folosiţi managerul de taskuri încorporat sau integraţi-l pe al dumneavoastră. Integrările Hangfire & RabbitMQ sunt deja disponibile.",
+ "DDDInfrastructure": "Infrastructură DDD",
+ "DomainDrivenDesignInfrastructure": "Infrastructură Domain Driven Design",
+ "AutoRESTAPIs": "Auto REST APIs",
+ "DynamicClientProxies": "Dynamic Client Proxies",
+ "DistributedEventBus": "Distributed Event Bus",
+ "DistributedEventBusWithRabbitMQIntegration": "Distributed Event Bus with RabbitMQ Integration",
+ "TestInfrastructure": "Infrastructură de test",
+ "AuditLoggingEntityHistories": "Jurnalul de audit şi istoricul entităţilor",
+ "ObjectToObjectMapping": "Mapare obiect la obiect",
+ "ObjectToObjectMappingExplanation": "Abstractizarea mapării obiect la obiect cu integrare AutoMapper.",
+ "EmailSMSAbstractions": "Abstractizări Email & SMS",
+ "EmailSMSAbstractionsWithTemplatingSupport": "Abstractizări de Email & SMS cu asistenţă pentru modelare",
+ "Localization": "Localizare",
+ "SettingManagement": "Administrarea setărilor",
+ "ExtensionMethods": "Metode de extindere",
+ "ExtensionMethodsHelpers": "Metode de extindere & Ajutoare",
+ "AspectOrientedProgramming": "Programare orientată spre aspect",
+ "DependencyInjection": "Injectarea de dependinţe",
+ "DependencyInjectionByConventions": "Injectarea dependinţei prin convenţii",
+ "ABPCLIExplanation": "ABP CLI (Command Line Interface) este un instrument de linie de comandă pentru efectuarea câtorva operaţii comune pentru soluţiile bazate pe ABP.",
+ "ModularityExplanation": "ABP asigură o infrastructură completă pentru construirea modulelor aplicaţiei dumneavoastră, care pot avea entităţi, servicii, integrări cu baze de date, API-uri, componente UI şi aşa mai departe..",
+ "MultiTenancyExplanation": "ABP nu numai că acceptă dezvoltarea de aplicaţii multi-tenant, dar, de asemenea, face ca şi codul dumneavoastră să nu fie în mare parte conştient de multi-tenancy.",
+ "MultiTenancyExplanation2": "Poate detecta automat tenantul curent, izola datele unor tenanţi diferiţi unul de celălalt.",
+ "MultiTenancyExplanation3": "Acceptă o singură bază de date, bază de date per tenant şi abordări hibride.",
+ "MultiTenancyExplanation4": "Vă focusaţi pe codul dumneavoastră şi lăsaţi framework-ul să se ocupe de multi-tenancy pentru dumneavoastră.",
+ "BootstrapTagHelpersExplanation": "În loc să scrieţi manual detaliile repetate ale componentelor bootstrap, folosiţi tag helperele ABP pentru a simplifica şi profita de inteligenţă. Puteţi folosi cu siguranţă Bootstrap ori de câte ori aveţi nevoie de el.",
+ "DynamicFormsExplanation": "Formulare dinamice & tag helpere de intrare pot crea formularul complet dintr-o clasă C# ca model.",
+ "AuthenticationAuthorizationExplanation": "Opţiuni variate de autentificare şi autorizare integrate cu ASP.NET Core Identity & IdentityServer4. Furnizează un sistem de permisiuni extensibil şi detaliat.",
+ "CrossCuttingConcernsExplanation": "Nu vă repetaţi pentru a implementa din nou şi din nou toate aceste lucruri obişniuite. Concentraţi-vă pe codul dumneavoastră de business şi lăsaţi ABP să le automatizeze prin convenţii.",
+ "DatabaseConnectionTransactionManagement": "Conectare la baza de date & Gestionarea tranzacţiilor",
+ "CorrelationIdTracking": "Correlation-Id Tracking",
+ "BundlingMinificationExplanation": "ABP oferă un sistem simplu, dinamic, puternic, modular şi încorporat de grupare şi minimizare.",
+ "VirtualFileSystemnExplanation": "Sistemul fişierelor virtuale face posibilă administrare fişierelor care nu există fizic pe sistemul de fişiere (disk). Este folosit în principal pentru a încorpora fişiere (js, css, images, cshtml...) în ansambluri şi să le folosească sub formă de fişiere fizice în timpul rulării.",
+ "ThemingExplanation": "Sistemul de teme permite dezvoltarea aplicaţiei & modulelor independente de tema prin definirea unui set comun de librării şi aspecte de bază, bazate pe ultimul framework Bootstrap.",
+ "DomainDrivenDesignInfrastructureExplanation": "O infrastructură completă pentru construirea aplicaţiilor stratificate, bazată pe tipare & principii Domain Driven Design;",
+ "Specification": "Specificaţie",
+ "Repository": "Repository",
+ "DomainService": "Domain Service",
+ "ValueObject": "Value Object",
+ "ApplicationService": "Application Service",
+ "DataTransferObject": "Obiect de transfer de date",
+ "AggregateRootEntity": "Aggregate Root, Entity",
+ "AutoRESTAPIsExplanation": "ABP poate configura automat serviciile aplicaţiei sub formă de controllere API prin convenţie.",
+ "DynamicClientProxiesExplanation": "Folosiţi-vă cu uşurinţă API-urile din JavaScript şi clienţi C#.",
+ "DistributedEventBusWithRabbitMQIntegrationExplanation": "Publicaţi şi utilizaţi cu uşurinţă evenimentele distribuite utilizând Distributed Event Bus încorporat cu integrarea RabbitMQ disponibilă.",
+ "TestInfrastructureExplanation": "Framework-ul a fost dezvoltat cu testarea unităţii şi integrării în minte. Vă oferă clase de bază pentru a o uşura. Şabloanele de pornire sunt pre-configurate pentru testare.",
+ "AuditLoggingEntityHistoriesExplanation": "Jurnal de audit încorporat pentru aplicaţii critice pentru afaceri. Solicitare, serviciu, jurnal de audit la nivel de metodă şi istoric de entităţi cu detalii la nivel de proprietate.",
+ "EmailSMSAbstractionsWithTemplatingSupportExplanation": "Abstractizările IEmailSender şi ISmsSender decuplează logica aplicaţiei de infrastructură. Sistemul avansat de şabloane de email permite crearea şi localizarea şabloanelor de email şi utilizarea lor cu uşurinţă ori de câte ori este necesar.",
+ "LocalizationExplanation": "Sistemul de localizare vă permite să creaţi resurse în JSON simplu şi să le folosiţi pentru a vă localiza UI-ul dumneavoastră. Suportă sisteme avansate precum moştenirea, extinderea, şi integrarea cu JavaScript în timp ce e pe deplin compatibilă cu sistemul de localizare al AspNet Core.",
+ "SettingManagementExplanation": "Definiţi setări pentru aplicaţia dumneavoastră şi Define settings for your application and get values on runtime based on the current configuration, tenant and user.",
+ "ExtensionMethodsHelpersExplanation": "Don't repeat yourself even for trivial code parts. Extensions & helpers for standard types makes your code much cleaner and easy to write.",
+ "AspectOrientedProgrammingExplanation": "Furnizează o infrastructură confortabilă pentru crearea proxy-urilor dinamice şi implementarea programării orientată aspect. Interceptează orice clasă şi execută codul dumneavoastră înainte & după orice executare de metodă.",
+ "DependencyInjectionByConventionsExplanation": "Nu este nevoie să vă înregistraţi clasele pentru injectarea manuală a dependinţelor. Înregistrează în mod automat tipurile de servicii comune prin convenţie. Pentru alte tipuri de servicii, puteţi folosi interfeţe şi atribute pentru a o face mai uşor si pe loc.",
+ "DataFilteringExplanation": "Definiţi şi utilizaţi filtre de date care sunt aplicate automat atunci când interogaţi entităţi din baza de date. Filtre Soft Delete & MultiTenant sunt prevăzute în mod implicit atunci când implementaţi interfeţe simple.",
+ "PublishEvents": "Publicaţi evenimente",
+ "HandleEvents": "Gestionaţi evenimente",
+ "AndMore": "şi multe altele...",
+ "Code": "Cod",
+ "Result": "Rezultat",
+ "SeeTheDocumentForMoreInformation": "Consultaţi {0} documentul pentru mai multe informaţii",
+ "IndexPageHeroSection": "open sourceWeb Application Framework pentru asp.net core",
+ "UiFramework": "Framework UI",
+ "EmailAddress": "Adresă de email",
+ "Mobile": "Mobil",
+ "ReactNative": "React nativ",
+ "Strong": "Puternic",
+ "Complete": "Complet",
+ "BasedLayeringModel": "Based Layering Model",
+ "Microservice": "Microserviciu",
+ "Compatible": "Compatibil",
+ "MeeTTheABPCommunityInfo": "Misiunea noastră este de a crea un mediu în care dezvoltatorii să se ajute reciproc cu articole, tutoriale, studii de caz etc. şi să cunoască oameni cu aceleaşi idei.",
+ "JoinTheABPCommunityInfo": "Implicaţi-vă într-o comunitate vibrantă şi deveniţi un contribuitor la ABP Framework!",
+ "AllArticles": "Toate articolele",
+ "SubmitYourArticle": "Trimiteţi-vă articolul",
+ "DynamicClientProxyDocument": "Consultaţi documentaţia pentru client proxy dinamic pentru JavaScript & C#.",
+ "EmailSMSAbstractionsDocument": "Consultaţi documentele de emailing and trimiterea de SMS pentru mai multe informaţii.",
+ "CreateProjectWizard": "Acest formular crează un proiect nou începând cu şablonul de pornire, care este configurat corespunzător pentru a începe direct cu proiectul.",
+ "TieredOption": "Crează o soluţie pe mai multe niveluri în care straturile Web API şi HTTP sunt separate fizic. Dacă nu este bifată, creează o soluţie stratificată mai puţin complexă şi potrivită pentru majoritatea scenariilor.",
+ "SeparateIdentityServerOption": "Separă partea serverului în două aplicaţii: prima este pentru serverul de identitate, iar a doua pentru serverul dumneavoastră de HTTP API.",
+ "UseslatestPreVersion": "Foloseşte ultima versiune pre-lansare",
+ "ReadTheDocumentation": "Citiţi Documentaţia",
+ "Documentation": "Documentaţie",
+ "GettingStartedTutorial": "Tutorial de pornire",
+ "ApplicationDevelopmentTutorial": "Tutorial de dezvoltare a aplicaţiei",
+ "TheStartupTemplate": "Şablonul de pornire",
+ "InstallABPCLIInfo": "ABP CLI este cea mai rapidă metodă de a porni o soluţie nouă cu framework-ul ABP. Instalaţi ABP CLI folosind o fereastră de linii de comandă:",
+ "DifferentLevelOfNamespaces": "Puteţi folosi nivele diferite de spaţii de nume; e.g. BookStore, Acme.BookStore or Acme.Retail.BookStore.",
+ "ABPCLIExamplesInfo": "comanda new creează o aplicaţie stratificată MVC cu Entity Framework Core ca şi furnizor de baze de date. Totuşi, are şi alte opţiuni. Exemple:",
+ "SeeCliDocumentForMoreInformation": "Consultaţi documentul ABP CLI pentru mai multe opţiuni sau selectaţi tab-ul de \"Descărcare directă\" de deasupra.",
+ "Optional": "Opţional",
+ "LocalFrameworkRef": "Pastraţi referinţa proiectului local pentru pachetele framework-ului.",
+ "BlobStoring": "Depozitare BLOB",
+ "BlobStoringExplanation": "Sistemul de depozitare BLOB oferă o abstractizare pentru lucrul cu BLOB-uri. ABP oferă câteva integrări prestabilite pentru furnizorii de stocare (Azure, AWS, File System, Database, etc.) pe care le puteţi folosi cu uşurinţă în aplicaţiile dumneavoastră.",
+ "TextTemplating": "Modelare text",
+ "TextTemplatingExplanation": "Modelarea textului este folosită pentru a reda dinamic conţinuturile bazate pe un şablon şi un model (un obiect de date). De exemplu, o puteţi folosi pentru a crea conţinuturi dinamice de email cu un şablon predefinit.",
+ "MultipleUIOptions": "Opţiuni UI multiple",
+ "MultipleDBOptions": "Furnizori de baze de date multipli",
+ "MultipleUIOptionsExplanation": "Framework-ul de bază este conceput ca independent de UI şi poate funcţiona cu orice tip de sistem UI, în timp ce mai multe opţiuni pre-construite şi integrate sunt oferite din start.",
+ "MultipleDBOptionsExplanation": "Framework-ul poate lucra cu orice sursă de date, în timp ce furnizorii următori sunt dezvoltaţi şi acceptaţi oficial;",
+ "SelectLanguage": "Selectaţi limba",
+ "LatestArticleOnCommunity": "Ultimul articol de pe comunitatea ABP",
+ "Register": "Întregistrare",
+ "IsDownloadable": "Poate fi descărcat",
+ "DatabaseOptions": "Opţiunile bazei de date",
+ "BackToPackagesPage": "Înapoi la pagina pachetelor",
+ "HowToInstall": "Cum instalez",
+ "SeeOnNpm": "Vedeţi pe NPM",
+ "SeeOnNuget": "Vedeţi pe Nuget",
+ "MVCGulpCommandExplanation": "Dacă folosiţi MVC (Razor Pages) UI, atunci rulaţi comanda the \"gulp\" după instalarea pachetelor.",
+ "UsingABPCLI": "Folosind Abp CLI",
+ "WithoutABPCLI": "Fară ABP CLI",
+ "ABPCLIModuleDependency": "Abp Cli adaugă automat dependenţa modulelor.",
+ "AddModuleDependency": "Apoi adăugaţi dependenţa modulului",
+ "Packages": "Pachete",
+ "NugetPackages": "Pachete Nuget",
+ "NPMPackages": "Pachete NPM",
+ "SeeDocs": "Consultaţi documentele",
+ "None": "Niciuna",
+ "Application": "Aplicaţie",
+ "Module": "Module",
+ "PackageName": "Nume pachet",
+ "LicenseURL": "URL licenţă",
+ "License": "Licenţă",
+ "ProjectCreationSuccessMessage": "Proiectul dumneavoastră a fost creat cu succes",
+ "HowToRunSolution": "Cum vă rulaţi soluţia?",
+ "GettingStartedMessage": "Consultaţi documentul de pornire pentru a învăţa cum să vă configuraţi şi să rulaţi soluţia dumneavoastră.",
+ "WebAppDevTutorial": "Tutorial Web App Dev",
+ "WebAppDevTutorialMessage": "Consultaţi documentul de dezvoltare a aplicaţiilor web pentru un exemplu de dezvoltare pas cu pas.",
+ "CommunityArticles": "Articolele comunităţii",
+ "CommunityArticleMessage": "Verificaţi platforma comunităţii ABP pentru a citi articole utile pentru framework-ul ABP.",
+ "InvestigateSolutionDetails": "Investigaţi detaliile soluţiei",
+ "StartupTemplateDocumentationMessage": "Consultaţi documentul şablonului de pornire a aplicaţiei pentru a învăţa arhitectura şi strucutra soluţiei dumneavoastră.",
+ "ClientSideDevelopment": "Dezvoltarea clientului",
+ "ClientSideDevelopmentDocumentationMessage": "Consultaţi documentul {0} pentru a învăţa punctele cheie pentru dezvoltarea interfeţei de utilizator.",
+ "DatabaseProviderDocumentationMessage": "Consultaţi documentul {0} pentru a învăţa punctele cheie pentru dezvoltarea straturilor bazei de date.",
+ "ABPCommercialExplanationMessage": "ABP Commercial oferă module premium, teme, isntrumente şi asistenţă pentru framework-ul ABP.",
+ "ImplementingDDD": "Implementarea Domain Driven Design",
+ "DDDBookExplanation": "Un ghid practic pentru implementarea Domain Driven Design în framework-ul ABP.",
+ "Overview": "Prezentare generală",
+ "DDDBookPracticalGuide": "Acesta este un ghid practic pentru implementarea Domain Driven Design (DDD). În timp ce detaliile implementării se bazează pe infrastructura framework-ului ABP, conceptele de bază, principiile şi modelele pot fi aplicate oricărei soluţii, chiar dacă nu este una .NET.",
+ "TableOfContents": "Cuprins",
+ "IntroductionToImplementingDDD": "Introducere în Implementarea Domain Driven Design",
+ "WhatIsDDD": "Ce este Domain Driven Design?",
+ "Implementation": "Implementare",
+ "TheBigPicture": "Privire de ansamblu",
+ "TheBuildingBlock": "The Building Block",
+ "ExampleUseCase": "Exemplu de Use Case",
+ "DomainAndApplicationLogic": "Domain Logic & Application Logic",
+ "Author": "Autor",
+ "Pages": "Pagini",
+ "PublishedOn": "Publicat pe",
+ "FreeEBook": "E-Book gratuit",
+ "Download": "Descărcaţi",
+ "EBookSignInForDownload": "Pentru a descărca e-book-ul trebuie să vă autentificaţi",
+ "SignIn": "Autentificaţi-vă",
+ "Or": "Sau",
+ "TellUsAboutYourself": "Spuneţi-ne un pic despre dumneavoastră",
+ "Name": "Nume",
+ "Surname": "Nume",
+ "CompanyName": "Nume companie",
+ "DoYouAgreePrivacyPolicy": "Sunt de acord cu Termenii & condiţiile şi Politica de confidenţialitate.",
+ "Free": "Gratuit",
+ "DDDEBook": "E-book DDD",
+ "PracticalGuideForImplementingDDD": "Această carte este un ghid practic pentru implementarea Domain Driven Design în framework-ul ABP.",
+ "IntroducingDDD": "Introducere în Domain Driven Design",
+ "DDDLayersAndCleanArchitecture": "Straturile DDD & Arhitectură curată",
+ "LayeringOfADotnetSolution": "Stratificarea unei soluţii .NET",
+ "ImplementingDDDBuildingBlocks": "Implementând DDD Building Blocks",
+ "DomainVsApplicationLogic": "Domain Logic vs Application Logic",
+ "SamplesAndDiscussions": "Exemple & Discuţii",
+ "EmailNotValid": "Vă rugăm să introduceţi o adresa de email validă.",
+ "WeWillSendYouADownloadLink": "Un link care conţine e-book-ul a fost trimis către {0}. Verificaţi-vă folderele de inbox, junk sau spam!",
+ "GoHome": "Pagina principală",
+ "InvalidFormInputs": "Vă rugăm, introduceţi informaţia validă specificată în formular.",
+ "DDDBookEmailBody": "Vă mulţumim. Pentru a descărca cartea, click aici.",
+ "SubscribeToNewsletter": "Abonaţi-vă la newsletter pentru a primi informaţii despre evnimentele din platforma ABP.IO, precum noi lansări, articole, oferte şi multe altele.",
+ "FirstEdition": "Prima ediţie",
+ "ThankYou": "Vă mulţumim!",
+ "CheckboxMandatory": "Trebuie să bifaţi asta pentru a continua!"
+ }
+}
diff --git a/common.props b/common.props
index 6bad8e8068..6ce5cae828 100644
--- a/common.props
+++ b/common.props
@@ -19,4 +19,13 @@
runtime; build; native; contentfiles; analyzers
+
+
+
+
+ true
+ Never
+
+
+
diff --git a/docs/en/API/Swagger-Integration.md b/docs/en/API/Swagger-Integration.md
new file mode 100644
index 0000000000..48ce252940
--- /dev/null
+++ b/docs/en/API/Swagger-Integration.md
@@ -0,0 +1,140 @@
+# Swagger Integration
+
+[Swagger (OpenAPI)](https://swagger.io/) is a language-agnostic specification for describing REST APIs. It allows both computers and humans to understand the capabilities of a REST API without direct access to the source code. Its main goals are to:
+
+- Minimize the amount of work needed to connect decoupled services.
+- Reduce the amount of time needed to accurately document a service.
+
+ABP Framework offers a prebuilt module for full Swagger integration with small configurations.
+
+## Installation
+
+> This package is already installed by default with the startup template. So, most of the time, you don't need to install it manually.
+
+If installation is needed, it is suggested to use the [ABP CLI](CLI.md) to install this package.
+
+### Using the ABP CLI
+
+Open a command line window in the folder of the `Web` or `HttpApi.Host` project (.csproj file) and type the following command:
+
+```bash
+abp add-package Volo.Abp.Swashbuckle
+```
+
+### Manual Installation
+
+If you want to manually install;
+
+1. Add the [Volo.Abp.Swashbuckle](https://www.nuget.org/packages/Volo.Abp.Swashbuckle) NuGet package to your `Web` or `HttpApi.Host` project:
+
+ `Install-Package Volo.Abp.Swashbuckle`
+
+2. Add the `AbpSwashbuckleModule` to the dependency list of your module:
+
+ ```csharp
+ [DependsOn(
+ //...other dependencies
+ typeof(AbpSwashbuckleModule) // <-- Add module dependency like that
+ )]
+ public class YourModule : AbpModule
+ {
+ }
+ ```
+
+## Configuration
+
+First, we need to use `AddAbpSwaggerGen` extension to configure Swagger in `ConfigureServices` method of our module.
+
+```csharp
+public override void ConfigureServices(ServiceConfigurationContext context)
+{
+ var services = contex.Services;
+
+ //... other configarations.
+
+ services.AddAbpSwaggerGen(
+ options =>
+ {
+ options.SwaggerDoc("v1", new OpenApiInfo { Title = "Test API", Version = "v1" });
+ options.DocInclusionPredicate((docName, description) => true);
+ options.CustomSchemaIds(type => type.FullName);
+ }
+ );
+}
+```
+
+Then we can use Swagger UI by calling `UseAbpSwaggerUI` method in the `OnApplicationInitialization` method of our module.
+
+```csharp
+public override void OnApplicationInitialization(ApplicationInitializationContext context)
+{
+ var app = context.GetApplicationBuilder();
+
+ //... other configarations.
+
+ app.UseAbpSwaggerUI(options =>
+ {
+ options.SwaggerEndpoint("/swagger/v1/swagger.json", "Test API");
+ });
+
+ //... other configarations.
+}
+```
+
+## Using Swagger with OAUTH
+
+For non MVC/Tiered applications, we need to configure Swagger with OAUTH to handle authorization.
+
+> ABP Framework uses IdentityServer by default. To get more information about IDS, check this [documentation](Modules/IdentityServer.md).
+
+
+
+To do that, we need to use `AddAbpSwaggerGenWithOAuth` extension to configure Swagger with OAuth issuer and scopes in `ConfigureServices` method of our module.
+
+```csharp
+public override void ConfigureServices(ServiceConfigurationContext context)
+{
+ var services = contex.Services;
+
+ //... other configarations.
+
+ services.AddAbpSwaggerGenWithOAuth(
+ "https://localhost:44341", // authority issuer
+ new Dictionary //
+ { // scopes
+ {"Test", "Test API"} //
+ }, //
+ options =>
+ {
+ options.SwaggerDoc("v1", new OpenApiInfo { Title = "Test API", Version = "v1" });
+ options.DocInclusionPredicate((docName, description) => true);
+ options.CustomSchemaIds(type => type.FullName);
+ }
+ );
+}
+```
+
+Then we can use Swagger UI by calling `UseAbpSwaggerUI` method in the `OnApplicationInitialization` method of our module.
+
+> Do not forget to set `OAuthClientId` and `OAuthClientSecret`.
+
+
+```csharp
+public override void OnApplicationInitialization(ApplicationInitializationContext context)
+{
+ var app = context.GetApplicationBuilder();
+
+ //... other configarations.
+
+ app.UseAbpSwaggerUI(options =>
+ {
+ options.SwaggerEndpoint("/swagger/v1/swagger.json", "Test API");
+
+ var configuration = context.ServiceProvider.GetRequiredService();
+ options.OAuthClientId("Test_Swagger"); // clientId
+ options.OAuthClientSecret("1q2w3e*"); // clientSecret
+ });
+
+ //... other configarations.
+}
+```
\ No newline at end of file
diff --git a/docs/en/Background-Jobs-Hangfire.md b/docs/en/Background-Jobs-Hangfire.md
index cfa2e12a6b..a690d9d17b 100644
--- a/docs/en/Background-Jobs-Hangfire.md
+++ b/docs/en/Background-Jobs-Hangfire.md
@@ -79,3 +79,26 @@ After you have installed these NuGet packages, you need to configure your projec
}
````
+
+### Dashboard Authorization
+
+Hangfire Dashboard provides information about your background jobs, including method names and serialized arguments as well as gives you an opportunity to manage them by performing different actions – retry, delete, trigger, etc. So it is important to restrict access to the Dashboard.
+To make it secure by default, only local requests are allowed, however you can change this by following the [official documentation](http://docs.hangfire.io/en/latest/configuration/using-dashboard.html) of Hangfire.
+
+You can integrate the Hangfire dashboard to [ABP authorization system](Authorization.md) using the **AbpHangfireAuthorizationFilter**
+class. This class is defined in the `Volo.Abp.Hangfire` package. The following example, checks if the current user is logged in to the application:
+
+ app.UseHangfireDashboard("/hangfire", new DashboardOptions
+ {
+ AsyncAuthorization = new[] { new AbpHangfireAuthorizationFilter() }
+ });
+
+If you want to require an additional permission, you can pass it into the constructor as below:
+
+ app.UseHangfireDashboard("/hangfire", new DashboardOptions
+ {
+ AsyncAuthorization = new[] { new AbpHangfireAuthorizationFilter("MyHangFireDashboardPermissionName") }
+ });
+
+**Important**: `UseHangfireDashboard` should be called after the authentication middleware in your `Startup` class (probably at the last line). Otherwise,
+authorization will always fail!
diff --git a/docs/en/Blog-Posts/2020-10-15 v3_3_Preview/POST.md b/docs/en/Blog-Posts/2020-10-15 v3_3_Preview/POST.md
index 4e19a294c1..886e8a145d 100644
--- a/docs/en/Blog-Posts/2020-10-15 v3_3_Preview/POST.md
+++ b/docs/en/Blog-Posts/2020-10-15 v3_3_Preview/POST.md
@@ -213,7 +213,7 @@ There are some breaking changes with the Blazor UI. If you've built an applicati
When you create a new project, profile management doesn't work, you get an exception because it can't find the `/libs/cropperjs/css/cropper.min.css` file. To fix the issue;
* Add `"@volo/account": "^3.3.0-rc.1"` to the `package.json` in the `.Host` project.
-* Run `yarn` (or `npm install`), then `gulp` on a command line terminal in the root folder of the `.Host` project.
+* Run `yarn` (or `npm install`), then `abp install-libs` on a command line terminal in the root folder of the `.Host` project.
### Multi-Tenant Social Logins
diff --git a/docs/en/Blog-Posts/2021-08-02 v4_4_Release_Stable/POST.md b/docs/en/Blog-Posts/2021-08-02 v4_4_Release_Stable/POST.md
new file mode 100644
index 0000000000..a2c812bb74
--- /dev/null
+++ b/docs/en/Blog-Posts/2021-08-02 v4_4_Release_Stable/POST.md
@@ -0,0 +1,42 @@
+# ABP.IO Platform 4.4 Final Has Been Released!
+
+[ABP Framework](https://abp.io/) and [ABP Commercial](https://commercial.abp.io/) 4.4 versions have been released today.
+
+## What's New With 4.4?
+
+Since all the new features are already explained in details with the 4.4 RC announcement posts, I will not repeat all the details again. See [the related blog post](https://blog.abp.io/abp/ABP-Platform-4-4-RC-Has-Been-Released) for all the features and enhancements.
+
+## How to Upgrade an Existing Solution
+
+### Install/Update the ABP CLI
+
+First of all, install the ABP CLI or upgrade to the latest version.
+
+If you haven't installed yet:
+
+```bash
+dotnet tool install -g Volo.Abp.Cli
+```
+
+To update an existing installation:
+
+```bash
+dotnet tool update -g Volo.Abp.Cli
+```
+
+### ABP UPDATE Command
+
+[ABP CLI](https://docs.abp.io/en/abp/latest/CLI) provides a handy command to update all the ABP related NuGet and NPM packages in your solution with a single command:
+
+```bash
+abp update
+```
+
+Run this command in the root folder of your solution.
+
+## The Road Map
+
+The next feature version will be 5.0. It is planned to release the 5.0 RC (Release Candidate) in November 2021. See the updated road maps;
+
+* [ABP Framework Road Map](https://docs.abp.io/en/abp/latest/Road-Map)
+* [ABP Commercial Road Map](https://docs.abp.io/en/commercial/latest/road-map)
\ No newline at end of file
diff --git a/docs/en/Modules/Cms-Kit/Index.md b/docs/en/Modules/Cms-Kit/Index.md
index fbdc37ec18..eb08a0c53c 100644
--- a/docs/en/Modules/Cms-Kit/Index.md
+++ b/docs/en/Modules/Cms-Kit/Index.md
@@ -12,6 +12,7 @@ The following features are currently available:
* Provides a [**comment**](Comments.md) system to add comments feature to any kind of resource, like blog post or a product review page.
* Provides a [**reaction**](Reactions.md) system to add reactions (smileys) feature to any kind of resource, like a blog post or a comment.
* Provides a [**rating**](Ratings.md) system to add rating feature to any kind of resource.
+* Provides a [**menu**](Menus.md) system to manage public menus dynamically.
Click to a feature to understand and learn how to use it.
diff --git a/docs/en/Modules/Cms-Kit/Menus.md b/docs/en/Modules/Cms-Kit/Menus.md
new file mode 100644
index 0000000000..87486326da
--- /dev/null
+++ b/docs/en/Modules/Cms-Kit/Menus.md
@@ -0,0 +1,88 @@
+# CMS Kit: Pages
+
+CMS Kit Menu system allows to manage public menus dynamically.
+
+## The User Interface
+
+### Menu items
+
+CMS Kit module admin side adds the following items to the main menu, under the *CMS* menu item:
+
+* **Menus**: Menu management page.
+
+`CmsKitAdminMenus` class has the constants for the menu item names.
+
+### Menus
+
+#### Menu Management
+
+Menus page is used to manage dynamic public menus in the system.
+
+
+
+
+
+Created menus will be visible on public site.
+
+
+
+# Internals
+
+## Domain Layer
+
+#### Aggregates
+
+This module follows the [Entity Best Practices & Conventions](https://docs.abp.io/en/abp/latest/Best-Practices/Entities) guide.
+
+##### Menus
+
+- `MenuItem` (aggregate root): A Menu Item presents a single node at menu tree.
+
+#### Repositories
+
+This module follows the [Repository Best Practices & Conventions](https://docs.abp.io/en/abp/latest/Best-Practices/Repositories) guide.
+
+Following custom repositories are defined for this feature:
+
+- `IMenuItemRepository`
+
+#### Domain services
+
+This module follows the [Domain Services Best Practices & Conventions](https://docs.abp.io/en/abp/latest/Best-Practices/Domain-Services) guide.
+
+##### Menu Item Manager
+
+`MenuItemManager` is used to perform some operations for the `MenuItemManager` aggregate root.
+
+### Application layer
+
+#### Application services
+
+- `MenuItemAdminAppService` (implements `IMenuItemAdminAppService`): Implements the management operations of menu system.
+- `MenuItemPublicAppService` (implements `IMenuItemPublicAppService`): Implements the public use cases of menu system.
+
+### Database providers
+
+#### Common
+
+##### Table / collection prefix & schema
+
+All tables/collections use the `Cms` prefix by default. Set static properties on the `CmsKitDbProperties` class if you need to change the table prefix or set a schema name (if supported by your database provider).
+
+##### Connection string
+
+This module uses `CmsKit` for the connection string name. If you don't define a connection string with this name, it fallbacks to the `Default` connection string.
+
+See the [connection strings](https://docs.abp.io/en/abp/latest/Connection-Strings) documentation for details.
+
+#### Entity Framework Core
+
+##### Tables
+
+- CmsMenuItems
+
+#### MongoDB
+
+##### Collections
+
+- CmsMenuItems
\ No newline at end of file
diff --git a/docs/en/Modules/Docs.md b/docs/en/Modules/Docs.md
index 4c764ee2c6..3894e29d20 100644
--- a/docs/en/Modules/Docs.md
+++ b/docs/en/Modules/Docs.md
@@ -188,7 +188,7 @@ Open `package.json` and add `@abp/docs": "^2.9.0` as shown below:
Then open the command line terminal in the `Acme.MyProject.Web` project folder and run the following command:
1. `yarn`
- 2. `gulp`
+ 2. `abp install-libs`
### 4- Database Integration
diff --git a/docs/en/Modules/Virtual-File-Explorer.md b/docs/en/Modules/Virtual-File-Explorer.md
index bae87ba95a..b0e25a2d65 100644
--- a/docs/en/Modules/Virtual-File-Explorer.md
+++ b/docs/en/Modules/Virtual-File-Explorer.md
@@ -61,7 +61,7 @@ Or you can also manually install nuget package to `Acme.MyProject.Web` project:
Then open the command line terminal in the `Acme.MyProject.Web` project folder and run the following command:
1. `yarn`
- 2. `gulp`
+ 2. `abp install-libs`
That's all,Now run the application and Navigate to `/VirtualFileExplorer`. You will see virtual file explorer page:
diff --git a/docs/en/SignalR-Integration.md b/docs/en/SignalR-Integration.md
index 29c37e30b2..c8a25215de 100644
--- a/docs/en/SignalR-Integration.md
+++ b/docs/en/SignalR-Integration.md
@@ -70,10 +70,10 @@ This will add the `@abp/signalr` to the dependencies in the `package.json` of yo
}
````
-Run the `gulp` in the root folder of your web project:
+Run `abp install-libs` command in the root folder of your web project:
````bash
-gulp
+abp install-libs
````
This will copy the SignalR JavaScript files into your project:
diff --git a/docs/en/Swagger.md b/docs/en/Swagger.md
deleted file mode 100644
index 1fda8a0cd7..0000000000
--- a/docs/en/Swagger.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Swagger UI Integration
-
-TODO
\ No newline at end of file
diff --git a/docs/en/UI/Angular/Basic-Theme.md b/docs/en/UI/Angular/Basic-Theme.md
new file mode 100644
index 0000000000..7b6c98fdcc
--- /dev/null
+++ b/docs/en/UI/Angular/Basic-Theme.md
@@ -0,0 +1,107 @@
+# Angular UI: Basic Theme
+
+The Basic Theme is a theme implementation for the Angular UI. It is a minimalist theme that doesn't add any styling on top of the plain [Bootstrap](https://getbootstrap.com/). You can take the Basic Theme as the **base theme** and build your own theme or styling on top of it. See the *Customization* section.
+
+> If you are looking for a professional, enterprise ready theme, you can check the [Lepton Theme](https://commercial.abp.io/themes), which is a part of the [ABP Commercial](https://commercial.abp.io/).
+
+> See the [Theming document](Theming.md) to learn about themes.
+
+## Installation
+
+**This theme is already installed** when you create a new solution using the [startup templates](../../Startup-Templates/Index.md). If you need to manually install it, follow the steps below:
+
+* Install the [@abp/ng.theme.basic](https://www.npmjs.com/package/@abp/ng.theme.basic) NPM package to your Angular project.
+* Open the `src/app/app.module.ts` file, import `ThemeBasicModule` (it can be imported from `@abp/ng.theme.basic` package), and add `ThemeBasicModule.forRoot()` to the `imports` array.
+* Open the `src/app/shared/shared.module` file, import `ThemeBasicModule` (it can be imported from `@abp/ng.theme.basic` package), and add `ThemeBasicModule` to the `imports` and `exports` array.
+
+The `ThemeBasicModule` is registered own layouts (`ApplicationLayoutComponent`, `AccountLayoutComponent`, `EmptyLayoutComponent`) to a service which is exposed by `@abp/ng.core` package on application initialization.
+
+## Application Layout
+
+
+
+Application Layout implements the following parts, in addition to the common parts mentioned above;
+
+* Logo area
+* Routes area
+* Language selection & user menu
+* [Page Alerts](Page-Alerts.md)
+
+See Application Layout components:
+
+
+
+### How to Use a Layout
+
+Routes should be added to the menu by calling `add` method `RoutesService`. A layout can be set in the object of your route. See the [modifying the menu](Modifying-the-Menu#how-to-add-a-navigation-element) for more information.
+
+## Customization
+
+You have two options two customize this theme:
+
+### Overriding Styles / Components
+
+In this approach, you continue to use the theme as an NPM package and customize the parts you need to. There are several ways to customize it;
+
+#### Override the Styles
+
+You can simply override the styles in the global styles (`src/styles.scss`) file of your application.
+
+#### Override the Components
+
+See the [Component Replacement](Component-Replacement.md) to learn how you can replace components, customize and extend the user interface.
+
+### Copy & Customize
+
+You can run the following [ABP CLI](../../CLI.md) command in **Angular** project directory to copy the source code to your solution:
+
+`abp add-package @abp/ng.theme.basic --with-source-code`
+
+----
+
+Or, you can download the [source code](https://github.com/abpframework/abp/blob/dev/npm/ng-packs/packages/theme-basic) of the Basic Theme, manually copy the project content into your project (`projects/theme-basic` folder), open `angular.json` file and add configuration below to the `projects` object:
+
+```json
+{
+ "projects": {
+ ...
+ "theme-basic": {
+ "projectType": "library",
+ "root": "projects/theme-basic",
+ "sourceRoot": "projects/theme-basic/src",
+ "prefix": "abp",
+ "architect": {
+ "build": {
+ "builder": "@angular-devkit/build-ng-packagr:build",
+ "options": {
+ "tsConfig": "projects/theme-basic/tsconfig.lib.json",
+ "project": "projects/theme-basic/ng-package.json"
+ },
+ "configurations": {
+ "production": {
+ "tsConfig": "projects/theme-basic/tsconfig.lib.prod.json"
+ }
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+Then, open the `tsconfig.json` file and add new paths as follows:
+
+```json
+"paths": {
+ ...
+ "@abp/ng.theme.basic": ["projects/theme-basic/src/public-api.ts"],
+ "@abp/ng.theme.basic/testing": ["projects/theme-basic/testing/src/public-api.ts"]
+}
+```
+
+
+You can now freely customize the theme based on your application requirements.
+
+## See Also
+
+* [Theming](Theming.md)
diff --git a/docs/en/UI/Angular/Theming.md b/docs/en/UI/Angular/Theming.md
new file mode 100644
index 0000000000..21e28953f8
--- /dev/null
+++ b/docs/en/UI/Angular/Theming.md
@@ -0,0 +1,228 @@
+# Angular UI: Theming
+
+## Introduction
+
+ABP Framework provides a complete **UI Theming** system with the following goals:
+
+* Reusable [application modules](../../Modules/Index.md) are developed **theme-independent**, so they can work with any UI theme.
+* UI theme is **decided by the final application**.
+* The theme is distributed via an NPM package, so it is **easily upgradable**.
+* The final application can **customize** the selected theme.
+
+In order to accomplish these goals, ABP Framework;
+
+* Determines a set of **base libraries** used and adapted by all the themes. So, module and application developers can depend on and use these libraries without depending on a particular theme.
+* Provides a system that consists of layout parts (like navigation menus and toolbars) that is implemented by all the themes. So, the modules and the application contribute to the layout to compose a consistent application UI.
+
+### Current Themes
+
+Currently, two themes are **officially provided**:
+
+* The [Basic Theme](Basic-Theme.md) is the minimalist theme with the plain Bootstrap style. It is **open source and free**.
+* The [Lepton Theme](https://commercial.abp.io/themes) is a **commercial** theme developed by the core ABP team and is a part of the [ABP Commercial](https://commercial.abp.io/) license.
+
+## Overall
+
+### The Base Libraries
+
+All the themes must depend on the [@abp/ng.theme.shared](https://www.npmjs.com/package/@abp/ng.theme.shared) NuGet package, so they are indirectly depending on the following libraries:
+
+* [Twitter Bootstrap](https://getbootstrap.com/) as the fundamental HTML/CSS framework.
+* [FontAwesome](https://fontawesome.com/) as the fundamental CSS font library.
+* [NG Bootstrap](https://ng-bootstrap.github.io/#/home) as a component library that supports the Bootstrap and adds extra components like modal and datepicker.
+* [Ngx-Datatable](https://swimlane.gitbook.io/ngx-datatable/) as a datatable library.
+* [ngx-validate](https://github.com/ng-turkey/ngx-validate) a dynamic validation of reactive forms library.
+* [Chart.js](https://www.chartjs.org/) as a widget library.
+
+These libraries are selected as the base libraries and available to the applications and modules.
+
+> Bootstrap's JavaScript part is not used since the NG Bootstrap library already provides the necessary functionalities to the Bootstrap components in a native way.
+
+### The Layout
+
+All themes must define a layout for the application. The following image shows the user management page in the [Basic Theme](Basic-Theme.md) application layout:
+
+
+
+And the same page is shown below with the [Lepton Theme](https://commercial.abp.io/themes) application layout:
+
+
+
+As you can see, the page is the same, but the look is completely different in the themes above.
+
+The application layout typically includes the following parts;
+
+* Main menu
+* Nav items area with the following components;
+ * User menu
+ * Language switch dropdown
+* [Page alerts](Page-Alerts.md)
+* The page content (aka ``)
+
+## Implementing a Theme
+
+A theme is simply an NPM package and comes with startup templates.
+
+### The Easy Way
+
+The easiest way to create a new theme is to add Basic Theme Source Code to your project via [ABP CLI](../../CLI.md) command and customize it.
+
+You can run the following command in **Angular** project directory to copy the source code to your solution:
+
+`abp add-package @abp/ng.theme.basic --with-source-code`
+
+### Global/Component Styles
+
+Angular can bundle global style files and component styles with components.
+See the [component styles](https://angular.io/guide/component-styles) guide on Angular documentation for more information.
+
+### Layout Parts
+
+A typical layout consists of several parts. The theme should include the necessary parts in each layout.
+
+**Example: The Basic Theme has the following parts for the Application Layout**
+
+
+
+The application code and the modules can only show contents in the Page Content part. If they need to change the other parts (to add a menu item, to add a nav item, to change the application name in the logo area...) they should use the ABP Framework APIs.
+
+The following sections explain the fundamental parts pre-defined by the ABP Framework and can be implemented by the themes.
+
+> It is a good practice to split the layout into components/partials, so the final application can override them partially for customization purpose.
+
+#### Logo
+
+The `application` object of an environment file should be configured to get the name and the logo URL of the application to render in the logo part. Additionally, `LogoComponent` can be replaced. See [Component Replacement](Component-Replacement.md) document for more.
+
+The [Application Startup Template](../../Startup-Templates/Application.md) has an implementation of this interface to set the values by the application developer.
+
+#### Main Menu / Routes
+
+`RoutesService` service is used to manage the main menu items and render them on the layout.
+
+**Example: Adding a route to the main menu**
+
+```ts
+import { RoutesService, eLayoutType } from '@abp/ng.core';
+import { Component } from '@angular/core';
+
+@Component(/* component metadata */)
+export class AppComponent {
+ constructor(routes: RoutesService) {
+ routes.add([
+ {
+ path: '/your-path',
+ name: 'Your navigation',
+ order: 101,
+ iconClass: 'fas fa-question-circle',
+ requiredPolicy: 'permission key here',
+ layout: eLayoutType.application,
+ },
+ {
+ path: '/your-path/child',
+ name: 'Your child navigation',
+ parentName: 'Your navigation',
+ order: 1,
+ requiredPolicy: 'permission key here',
+ },
+ ]);
+ }
+}
+```
+
+See the [Modifying the Menu](Modifying-the-Menu.md) document to learn more about the navigation system.
+
+#### Toolbar / Nav Items
+
+`NavItemsService` service is used to get the menu's right part items and render on the layout. You can add an HTML content or Angular component as an element to render.
+
+**Example: Adding an element to right part of the menu**
+
+````ts
+import { NavItemsService } from '@abp/ng.theme.shared';
+import { Component } from '@angular/core';
+
+@Component({
+ template: `
+
+ `,
+})
+export class MySearchInputComponent {}
+
+
+@Component(/* component metadata */)
+export class AppComponent {
+ constructor(private navItems: NavItemsService) {
+ navItems.addItems([
+ {
+ id: 'MySearchInput',
+ order: 1,
+ component: MySearchInputComponent,
+ },
+ {
+ id: 'SignOutIcon',
+ html: '',
+ action: () => console.log('Clicked the sign out icon'),
+ order: 101, // puts as last element
+ },
+ ]);
+ }
+}
+````
+
+> See the [How to Add an Element to Right Part of the Menu](Modifying-the-Menu#how-to-add-an-element-to-right-part-of-the-menu) document to learn more on the nav items system.
+
+The theme has a responsibility to add two pre-defined items to the toolbar: Language Selection and User Menu.
+
+##### Language Selection
+
+Language Selection toolbar item is generally a dropdown that is used to switch between languages. `ConfigStateService` is used to get the list of available languages and `SessionStateService` is used to learn the current language.
+
+`SessionStateService` is used to get and set the current language.
+
+**Example: Get the currently selected language**
+
+````ts
+import {SessionStateService} from '@abp/ng.core';
+
+//...
+
+constructor(private sessionState: SessionStateService) {
+ const lang = this.sessionState.getLanguage()
+}
+````
+
+**Example: Set the selected language**
+
+````ts
+import {SessionStateService} from '@abp/ng.core';
+
+//...
+
+constructor(private sessionState: SessionStateService) {
+ const lang = this.sessionState.setLanguage('en')
+}
+````
+
+##### User Menu
+
+User menu is a component that can be replaceable. See an example to learn how can you replace it:
+
+````ts
+import { eThemeBasicComponents } from '@abp/ng.theme.basic';
+import { NavItemsService } from '@abp/ng.theme.shared';
+import { Component } from '@angular/core';
+
+@Component({/* component metadata */})
+export class AppComponent {
+ constructor(private navItems: NavItemsService) {
+ this.navItems.patchItem(eThemeBasicComponents.CurrentUser, { component: MyUserMenuComponent });
+ }
+}
+````
+
+[`ConfigStateService`](Config-State-Service.md) service can be used to obtain the `application-configuration` API response (e.g. getting current user or tenant).
+
+#### Page Alerts
+
+`PageAlertService` service is used to get the current page alerts to render on the layout. See the [Page Alerts](Page-Alerts.md) document to learn more.
\ No newline at end of file
diff --git a/docs/en/UI/Angular/images/basic-theme-application-layout-parts.png b/docs/en/UI/Angular/images/basic-theme-application-layout-parts.png
new file mode 100644
index 0000000000..934b0e0528
Binary files /dev/null and b/docs/en/UI/Angular/images/basic-theme-application-layout-parts.png differ
diff --git a/docs/en/UI/AspNetCore/Basic-Theme.md b/docs/en/UI/AspNetCore/Basic-Theme.md
index 50a82142ef..e74799a423 100644
--- a/docs/en/UI/AspNetCore/Basic-Theme.md
+++ b/docs/en/UI/AspNetCore/Basic-Theme.md
@@ -15,7 +15,7 @@ The Basic Theme has RTL (Right-to-Left language) support.
* Install the [Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic](https://www.nuget.org/packages/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic) NuGet package to your web project.
* Add `AbpAspNetCoreMvcUiBasicThemeModule` into the `[DependsOn(...)]` attribute for your [module class](../../Module-Development-Basics.md) in the web project.
* Install the [@abp/aspnetcore.mvc.ui.theme.basic](https://www.npmjs.com/package/@abp/aspnetcore.mvc.ui.theme.basic) NPM package to your web project (e.g. `npm install @abp/aspnetcore.mvc.ui.theme.basic` or `yarn add @abp/aspnetcore.mvc.ui.theme.basic`).
-* Run `gulp` command in a command line terminal in the web project's folder.
+* Run `abp install-libs` command in a command line terminal in the web project's folder.
## Layouts
@@ -85,7 +85,7 @@ See the [User Interface Customization Guide](Customization-User-Interface.md) to
You can run the following [ABP CLI](../../CLI.md) command in **Web** project directory to copy the source code to your solution:
-`abp add-package Volo.Abp.AspNetCore.Components.Server.BasicTheme --with-source-code --add-to-solution-file`
+`abp add-module Volo.BasicTheme --with-source-code --add-to-solution-file`
----
diff --git a/docs/en/UI/AspNetCore/Client-Side-Package-Management.md b/docs/en/UI/AspNetCore/Client-Side-Package-Management.md
index 645200a363..259461adf3 100644
--- a/docs/en/UI/AspNetCore/Client-Side-Package-Management.md
+++ b/docs/en/UI/AspNetCore/Client-Side-Package-Management.md
@@ -18,7 +18,7 @@ To solve the versioning problem, we created a **standard set of packages** those
The benefit of a **standard package** is:
* It depends on a **standard version** of a package. Depending on this package is **safe** because all modules depend on the same version.
-* It contains the gulp task to copy library resources (js, css, img... files) from the **node_modules** folder to **wwwroot/libs** folder. See the *Mapping The Library Resources* section for more.
+* It contains the necessary mapping configuration to copy library resources (js, css, img... files) from the **node_modules** folder to **wwwroot/libs** folder. See the *Mapping The Library Resources* section for more.
Depending on a standard package is easy. Just add it to your **package.json** file like you normally do. Example:
@@ -61,7 +61,13 @@ Using NPM packages and NPM/Yarn tool is the de facto standard for client side li
Next challenge is copying needed resources (js, css, img... files) from the `node_modules` into a folder inside the **wwwroot** folder to make it accessible to the clients/browsers.
-ABP defines a [Gulp](https://gulpjs.com/) based task to **copy resources** from **node_modules** to **wwwroot/libs** folder. Each **standard package** (see the *@ABP NPM Packages* section) defines the mapping for its own files. So, most of the time, you only configure dependencies.
+[ABP CLI](../../CLI.md) offers the command below to **copy resources** from **node_modules** to **wwwroot/libs** folder. You have to run it in the root folder of your web project:
+
+````bash
+abp install-libs
+````
+
+Each **standard package** (see the *@ABP NPM Packages* section) defines the mapping for its own files. So, most of the time, you only configure dependencies.
The **startup templates** are already configured to work all these out of the box. This section will explain the configuration options.
@@ -100,17 +106,17 @@ mappings: {
}
````
-#### Using The Gulp
+#### Using ABP CLI To Copy Resources
-Once you properly configure the `abp.resourcemapping.js` file, you can run the gulp command from the command line:
+Once you properly configure the `abp.resourcemapping.js` file, you can run the [ABP CLI](../../CLI.md) command from the command line:
-````
-gulp
+````bash
+abp install-libs
````
-When you run the `gulp`, all packages will copy their own resources into the **wwwroot/libs** folder. Running `yarn & gulp` is only necessary if you make a change in your dependencies in the **package.json** file.
+When you run this command, all packages will copy their own resources into the **wwwroot/libs** folder. Running `yarn` & `abp install-libs` are only necessary if you make a change in your dependencies in the **package.json** file.
-> When you run the Gulp command, dependencies of the application are resolved using the package.json file. The Gulp task automatically discovers and maps all resources from all dependencies (recursively).
+> When you run the `abp install-libs` command, dependencies of the application are resolved using the package.json file. [ABP CLI](../../CLI.md) automatically discovers and maps all resources from all dependencies (recursively).
#### See Also
diff --git a/docs/en/UI/Blazor/Basic-Theme.md b/docs/en/UI/Blazor/Basic-Theme.md
index 6a71e50c84..2c034f258a 100644
--- a/docs/en/UI/Blazor/Basic-Theme.md
+++ b/docs/en/UI/Blazor/Basic-Theme.md
@@ -38,7 +38,7 @@ You have two options two customize this theme:
### Overriding Styles / Components
-In this approach, you continue to use the the theme as NuGet and NPM packages and customize the parts you need to. There are several ways to customize it;
+In this approach, you continue to use the theme as NuGet and NPM packages and customize the parts you need to. There are several ways to customize it;
#### Override the Styles
diff --git a/docs/en/Validation.md b/docs/en/Validation.md
index c4821adf65..1d24c5e2a6 100644
--- a/docs/en/Validation.md
+++ b/docs/en/Validation.md
@@ -149,8 +149,8 @@ Once ABP determines a validation error, it throws an exception of type `AbpValid
In addition to the automatic validation, you may want to manually validate an object. In this case, [inject](Dependency-Injection.md) and use the `IObjectValidator` service:
-* `Validate` method validates the given object based on the validation rules and throws an `AbpValidationException` if it is not in a valid state.
-* `GetErrors` doesn't throw an exception, but only returns the validation errors.
+* `ValidateAsync` method validates the given object based on the validation rules and throws an `AbpValidationException` if it is not in a valid state.
+* `GetErrorsAsync` doesn't throw an exception, but only returns the validation errors.
`IObjectValidator` is implemented by the `ObjectValidator` by default. `ObjectValidator` is extensible; you can implement `IObjectValidationContributor` interface to contribute a custom logic. Example:
@@ -158,13 +158,14 @@ In addition to the automatic validation, you may want to manually validate an ob
public class MyObjectValidationContributor
: IObjectValidationContributor, ITransientDependency
{
- public void AddErrors(ObjectValidationContext context)
+ public Task AddErrorsAsync(ObjectValidationContext context)
{
//Get the validating object
var obj = context.ValidatingObject;
//Add the validation errors if available
context.Errors.Add(...);
+ return Task.CompletedTask;
}
}
````
diff --git a/docs/en/Virtual-File-System.md b/docs/en/Virtual-File-System.md
index 307c6e92bc..6cdf9a7649 100644
--- a/docs/en/Virtual-File-System.md
+++ b/docs/en/Virtual-File-System.md
@@ -38,7 +38,7 @@ This configuration recursively adds all files under the **MyResources** folder o
Embedding a file in the project/assembly may cause problems if a file name contains some special chars. To overcome this limitation;
1. Add [Microsoft.Extensions.FileProviders.Embedded](https://www.nuget.org/packages/Microsoft.Extensions.FileProviders.Embedded) NuGet package to the project that contains the embedded resource(s).
-2. Add `true` into the `...` section of your `.csproj` file.
+2. Add `true` into the `...` section of your `.csproj` file.
> While these two steps are optional and ABP can work without these configuration, it is strongly suggested to make it.
@@ -193,4 +193,4 @@ So, if you need to replace a file of a module, just create the file in the exact
### Physical Files
-Physical files always override the virtual files. That means if you put a file under the `/wwwroot/my-folder/my-file.css`, it will override the file in the same location of the virtual file system. So, you need to know the file paths defined in the modules to override them.
\ No newline at end of file
+Physical files always override the virtual files. That means if you put a file under the `/wwwroot/my-folder/my-file.css`, it will override the file in the same location of the virtual file system. So, you need to know the file paths defined in the modules to override them.
diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json
index c946b8401c..398da988e4 100644
--- a/docs/en/docs-nav.json
+++ b/docs/en/docs-nav.json
@@ -365,8 +365,8 @@
"path": "Object-To-Object-Mapping.md"
},
{
- "text":"String Encryption",
- "path":"String-Encryption.md"
+ "text": "String Encryption",
+ "path": "String-Encryption.md"
},
{
"text": "Text Templating",
@@ -578,6 +578,10 @@
"path": "API/Application-Configuration.md"
}
]
+ },
+ {
+ "text": "Swagger Integration",
+ "path": "API/Swagger-Integration.md"
}
]
},
@@ -1025,6 +1029,19 @@
"text": "Customization Guide",
"path": "UI/Angular/Customization-User-Interface.md"
},
+ {
+ "text": "Theming",
+ "items": [
+ {
+ "text": "Overall",
+ "path": "UI/Angular/Theming.md"
+ },
+ {
+ "text": "The Basic Theme",
+ "path": "UI/Angular/Basic-Theme.md"
+ }
+ ]
+ },
{
"text": "Modifying the Menu",
"path": "UI/Angular/Modifying-the-Menu.md"
diff --git a/docs/en/images/cmskit-module-menus-page.png b/docs/en/images/cmskit-module-menus-page.png
new file mode 100644
index 0000000000..c265763788
Binary files /dev/null and b/docs/en/images/cmskit-module-menus-page.png differ
diff --git a/docs/en/images/cmskit-module-menus-public.png b/docs/en/images/cmskit-module-menus-public.png
new file mode 100644
index 0000000000..0b67064334
Binary files /dev/null and b/docs/en/images/cmskit-module-menus-public.png differ
diff --git a/docs/zh-Hans/Entities.md b/docs/zh-Hans/Entities.md
index 23ca3e73f0..85e1132d2b 100644
--- a/docs/zh-Hans/Entities.md
+++ b/docs/zh-Hans/Entities.md
@@ -211,7 +211,7 @@ public class OrderLine : Entity
> 如果你不想你的聚合根继承`AggregateRoot`类,你可以直接实现`IAggregateRoot`接口
-`Order`是一个具有`Guid`类型`Id`属性的 **聚合根**.它有一个`OrderLine`实体集合.`OrderLine`是一个具有组合键(`OrderLine`和 ` ProductId`)的实体.
+`Order`是一个具有`Guid`类型`Id`属性的 **聚合根**.它有一个`OrderLine`实体集合.`OrderLine`是一个具有组合键(`OrderId`和 ` ProductId`)的实体.
虽然这个示例可能无法实现聚合根的所有最佳实践,但它仍然遵循良好的实践:
diff --git a/docs/zh-Hans/Validation.md b/docs/zh-Hans/Validation.md
index f6b2daf31f..6e46b07aed 100644
--- a/docs/zh-Hans/Validation.md
+++ b/docs/zh-Hans/Validation.md
@@ -130,8 +130,8 @@ namespace Acme.BookStore
除了自动验证你可能需要手动验证对象,这种情况下[注入](Dependency-Injection.md)并使用 `IObjectValidator` 服务:
-* `Validate` 方法根据验证规则验证给定对象,如果对象没有被验证通过会抛出 `AbpValidationException` 异常.
-* `GetErrors` 不会抛出异常,只返回验证错误.
+* `ValidateAsync` 方法根据验证规则验证给定对象,如果对象没有被验证通过会抛出 `AbpValidationException` 异常.
+* `GetErrorsAsync` 不会抛出异常,只返回验证错误.
`IObjectValidator` 默认由 `ObjectValidator` 实现. `ObjectValidator`是可扩展的; 可以实现`IObjectValidationContributor`接口提供自定义逻辑.
示例 :
@@ -140,13 +140,14 @@ namespace Acme.BookStore
public class MyObjectValidationContributor
: IObjectValidationContributor, ITransientDependency
{
- public void AddErrors(ObjectValidationContext context)
+ public Task AddErrorsAsync(ObjectValidationContext context)
{
//Get the validating object
var obj = context.ValidatingObject;
//Add the validation errors if available
context.Errors.Add(...);
+ return Task.CompletedTask;
}
}
````
diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln
index 0605f5c103..8d5432f4c6 100644
--- a/framework/Volo.Abp.sln
+++ b/framework/Volo.Abp.sln
@@ -383,6 +383,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.TextTemplating.Scr
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.MongoDB.Tests.SecondContext", "test\Volo.Abp.MongoDB.Tests.SecondContext\Volo.Abp.MongoDB.Tests.SecondContext.csproj", "{90B1866A-EF99-40B9-970E-B898E5AA523F}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Threading.Tests", "test\Volo.Abp.Threading.Tests\Volo.Abp.Threading.Tests.csproj", "{7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -1141,6 +1143,10 @@ Global
{90B1866A-EF99-40B9-970E-B898E5AA523F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{90B1866A-EF99-40B9-970E-B898E5AA523F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{90B1866A-EF99-40B9-970E-B898E5AA523F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1334,6 +1340,7 @@ Global
{C996F458-98FB-483D-9306-4701290E2FC1} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{75D8DADB-3FA9-4C1D-B23A-DBFD08133B7C} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{90B1866A-EF99-40B9-970E-B898E5AA523F} = {447C8A77-E5F0-4538-8687-7383196D04EA}
+ {7B2FCAD6-86E6-49C8-ADBE-A61B4F4B101B} = {447C8A77-E5F0-4538-8687-7383196D04EA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}
diff --git a/framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/AbpAspNetCoreComponentsServerModule.cs b/framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/AbpAspNetCoreComponentsServerModule.cs
index 58398b651a..91b672b073 100644
--- a/framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/AbpAspNetCoreComponentsServerModule.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/AbpAspNetCoreComponentsServerModule.cs
@@ -25,18 +25,19 @@ namespace Volo.Abp.AspNetCore.Components.Server
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
- context.Services.AddServerSideBlazor();
-
+ var serverSideBlazorBuilder = context.Services.AddServerSideBlazor();
+ context.Services.ExecutePreConfiguredActions(serverSideBlazorBuilder);
+
Configure(options =>
{
options.IgnoredUrls.AddIfNotContains("/_blazor");
});
-
+
Configure(options =>
{
options.IgnoredUrls.AddIfNotContains("/_blazor");
});
-
+
Configure(options =>
{
options.EndpointConfigureActions.Add(endpointContext =>
@@ -56,4 +57,4 @@ namespace Volo.Abp.AspNetCore.Components.Server
);
}
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs
index f5541e3b40..f3d21a804b 100644
--- a/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs
+++ b/framework/src/Volo.Abp.AspNetCore.MultiTenancy/Volo/Abp/AspNetCore/MultiTenancy/MultiTenancyMiddleware.cs
@@ -64,6 +64,7 @@ namespace Volo.Abp.AspNetCore.MultiTenancy
context,
requestCulture
);
+ context.Items[AbpRequestLocalizationMiddleware.HttpContextItemName] = true;
}
await next(context);
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/ro-RO.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/ro-RO.json
new file mode 100644
index 0000000000..e431f56838
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/ro-RO.json
@@ -0,0 +1,13 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "GivenTenantIsNotExist": "Tenantul {0} nu există",
+ "GivenTenantIsNotAvailable": "Tenantul {0} nu este disponibil",
+ "Tenant": "Tenant",
+ "Switch": "schimbă",
+ "Name": "Nume",
+ "SwitchTenantHint": "Lăsaţi câmpul de nume gol pentru a schimba pe host.",
+ "SwitchTenant": "Schimbă tenant",
+ "NotSelected": "Neselectat"
+ }
+}
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpLanguagesController.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpLanguagesController.cs
index b0fa63e4f5..f5324656b9 100644
--- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpLanguagesController.cs
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Localization/AbpLanguagesController.cs
@@ -33,6 +33,8 @@ namespace Volo.Abp.AspNetCore.Mvc.Localization
new RequestCulture(culture, uiCulture)
);
+ HttpContext.Items[AbpRequestLocalizationMiddleware.HttpContextItemName] = true;
+
var context = new QueryStringCultureReplacementContext(HttpContext, new RequestCulture(culture, uiCulture), returnUrl);
await QueryStringCultureReplacement.ReplaceAsync(context);
diff --git a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs
index 06f3922b22..dad2b240d8 100644
--- a/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs
+++ b/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/RequestLocalization/AbpRequestLocalizationMiddleware.cs
@@ -10,6 +10,8 @@ namespace Microsoft.AspNetCore.RequestLocalization
{
public class AbpRequestLocalizationMiddleware : IMiddleware, ITransientDependency
{
+ public const string HttpContextItemName = "__AbpSetCultureCookie";
+
private readonly IAbpRequestLocalizationOptionsProvider _requestLocalizationOptionsProvider;
private readonly ILoggerFactory _loggerFactory;
@@ -29,6 +31,23 @@ namespace Microsoft.AspNetCore.RequestLocalization
_loggerFactory
);
+ context.Response.OnStarting(() =>
+ {
+ if (context.Items[HttpContextItemName] == null)
+ {
+ var requestCultureFeature = context.Features.Get();
+ if (requestCultureFeature?.Provider is QueryStringRequestCultureProvider)
+ {
+ AbpRequestCultureCookieHelper.SetCultureCookie(
+ context,
+ requestCultureFeature.RequestCulture
+ );
+ }
+ }
+
+ return Task.CompletedTask;
+ });
+
await middleware.Invoke(context);
}
}
diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Threading/HttpContextCancellationTokenProvider.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Threading/HttpContextCancellationTokenProvider.cs
index c7c961176c..ce722b1176 100644
--- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Threading/HttpContextCancellationTokenProvider.cs
+++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Threading/HttpContextCancellationTokenProvider.cs
@@ -6,13 +6,26 @@ using Volo.Abp.Threading;
namespace Volo.Abp.AspNetCore.Threading
{
[Dependency(ReplaceServices = true)]
- public class HttpContextCancellationTokenProvider : ICancellationTokenProvider, ITransientDependency
+ public class HttpContextCancellationTokenProvider : CancellationTokenProviderBase, ITransientDependency
{
- public CancellationToken Token => _httpContextAccessor.HttpContext?.RequestAborted ?? CancellationToken.None;
-
private readonly IHttpContextAccessor _httpContextAccessor;
- public HttpContextCancellationTokenProvider(IHttpContextAccessor httpContextAccessor)
+ public override CancellationToken Token
+ {
+ get
+ {
+ if (OverrideValue != null)
+ {
+ return OverrideValue.CancellationToken;
+ }
+ return _httpContextAccessor.HttpContext?.RequestAborted ?? CancellationToken.None;
+ }
+ }
+
+ public HttpContextCancellationTokenProvider(
+ IAmbientScopeProvider cancellationTokenOverrideScopeProvider,
+ IHttpContextAccessor httpContextAccessor)
+ : base(cancellationTokenOverrideScopeProvider)
{
_httpContextAccessor = httpContextAccessor;
}
diff --git a/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/ro-RO.json b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/ro-RO.json
new file mode 100644
index 0000000000..e330581c69
--- /dev/null
+++ b/framework/src/Volo.Abp.Authorization/Volo/Abp/Authorization/Localization/ro-RO.json
@@ -0,0 +1,10 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "Volo.Authorization:010001": "Autorizare eşuată! Politica dată nu a fost acordată.",
+ "Volo.Authorization:010002": "Autorizare eşuată! Politica dată nu a acordat: {PolicyName}",
+ "Volo.Authorization:010003": "Autorizare eşuată! Politica dată nu a fost acordată pentru resursa dată: {ResourceName}",
+ "Volo.Authorization:010004": "Autorizare eşuată! Cerinţa dată nu a fost acordată pentru resursa dată: {ResourceName}",
+ "Volo.Authorization:010005": "Autorizare eşuată! Cerinţele date nu au fost acordate pentru resursa dată: {ResourceName}"
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj b/framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj
index f8c8658e5f..dcfe16cce3 100644
--- a/framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj
+++ b/framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj
@@ -14,10 +14,10 @@
-
-
-
-
+
+
+
+
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliUrls.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliUrls.cs
index 1ecc5b1631..8d2b10d3ca 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliUrls.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/CliUrls.cs
@@ -10,9 +10,9 @@
public const string NuGetRootPath = NuGetRootPathDevelopment;
#else
public const string WwwAbpIo = WwwAbpIoProduction;
-
+
public const string AccountAbpIo = AccountAbpIoProduction;
-
+
public const string NuGetRootPath = NuGetRootPathProduction;
#endif
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CreateMigrationAndRunMigratorCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CreateMigrationAndRunMigratorCommand.cs
index 2a3c4652af..7b9fbd35fe 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CreateMigrationAndRunMigratorCommand.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/CreateMigrationAndRunMigratorCommand.cs
@@ -70,9 +70,10 @@ namespace Volo.Abp.Cli.Commands
private string FindTenantDbContextName(string dbMigrationsFolder)
{
- var tenantDbContext = Directory
- .GetFiles(dbMigrationsFolder, "*TenantMigrationsDbContext.cs", SearchOption.AllDirectories)
- .FirstOrDefault();
+ var tenantDbContext = Directory.GetFiles(dbMigrationsFolder, "*TenantMigrationsDbContext.cs", SearchOption.AllDirectories)
+ .FirstOrDefault() ??
+ Directory.GetFiles(dbMigrationsFolder, "*TenantDbContext.cs", SearchOption.AllDirectories)
+ .FirstOrDefault();
if (tenantDbContext == null)
{
@@ -84,9 +85,10 @@ namespace Volo.Abp.Cli.Commands
private string FindDbContextName(string dbMigrationsFolder)
{
- var dbContext = Directory
- .GetFiles(dbMigrationsFolder, "*MigrationsDbContext.cs", SearchOption.AllDirectories)
- .FirstOrDefault(fp => !fp.EndsWith("TenantMigrationsDbContext.cs"));
+ var dbContext = Directory.GetFiles(dbMigrationsFolder, "*MigrationsDbContext.cs", SearchOption.AllDirectories)
+ .FirstOrDefault(fp => !fp.EndsWith("TenantMigrationsDbContext.cs")) ??
+ Directory.GetFiles(dbMigrationsFolder, "*DbContext.cs", SearchOption.AllDirectories)
+ .FirstOrDefault(fp => !fp.EndsWith("TenantDbContext.cs"));
if (dbContext == null)
{
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs
index c8757e1252..c8bc508983 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/NewCommand.cs
@@ -26,24 +26,20 @@ using Volo.Abp.Threading;
namespace Volo.Abp.Cli.Commands
{
- public class NewCommand : IConsoleCommand, ITransientDependency
+ public class NewCommand : ProjectCreationCommandBase, IConsoleCommand, ITransientDependency
{
- private readonly EfCoreMigrationManager _efCoreMigrationManager;
public ILogger Logger { get; set; }
protected TemplateProjectBuilder TemplateProjectBuilder { get; }
public ITemplateInfoProvider TemplateInfoProvider { get; }
- public ConnectionStringProvider ConnectionStringProvider { get; }
public NewCommand(TemplateProjectBuilder templateProjectBuilder
, ITemplateInfoProvider templateInfoProvider,
- EfCoreMigrationManager efCoreMigrationManager,
ConnectionStringProvider connectionStringProvider)
+ : base(connectionStringProvider)
{
- _efCoreMigrationManager = efCoreMigrationManager;
TemplateProjectBuilder = templateProjectBuilder;
TemplateInfoProvider = templateInfoProvider;
- ConnectionStringProvider = connectionStringProvider;
Logger = NullLogger.Instance;
}
@@ -79,257 +75,23 @@ namespace Volo.Abp.Cli.Commands
template = (await TemplateInfoProvider.GetDefaultAsync()).Name;
}
- var version = commandLineArgs.Options.GetOrNull(Options.Version.Short, Options.Version.Long);
- if (version != null)
- {
- Logger.LogInformation("Version: " + version);
- }
-
var isTiered = commandLineArgs.Options.ContainsKey(Options.Tiered.Long);
if (isTiered)
{
Logger.LogInformation("Tiered: yes");
}
- var preview = commandLineArgs.Options.ContainsKey(Options.Preview.Long);
- if (preview)
- {
- Logger.LogInformation("Preview: yes");
- }
-
- var databaseProvider = GetDatabaseProvider(commandLineArgs);
- if (databaseProvider != DatabaseProvider.NotSpecified)
- {
- Logger.LogInformation("Database provider: " + databaseProvider);
- }
-
- var connectionString = GetConnectionString(commandLineArgs);
- if (connectionString != null)
- {
- Logger.LogInformation("Connection string: " + connectionString);
- }
-
- var databaseManagementSystem = GetDatabaseManagementSystem(commandLineArgs);
- if (databaseManagementSystem != DatabaseManagementSystem.NotSpecified)
- {
- Logger.LogInformation("DBMS: " + databaseManagementSystem);
- }
-
- var uiFramework = GetUiFramework(commandLineArgs);
- if (uiFramework != UiFramework.NotSpecified)
- {
- Logger.LogInformation("UI Framework: " + uiFramework);
- }
-
- var publicWebSite = uiFramework != UiFramework.None && commandLineArgs.Options.ContainsKey(Options.PublicWebSite.Long);
- if (publicWebSite)
- {
- Logger.LogInformation("Public Web Site: yes");
- }
-
- var mobileApp = GetMobilePreference(commandLineArgs);
- if (mobileApp != MobileApp.None)
- {
- Logger.LogInformation("Mobile App: " + mobileApp);
- }
-
- var gitHubAbpLocalRepositoryPath = commandLineArgs.Options.GetOrNull(Options.GitHubAbpLocalRepositoryPath.Long);
- if (gitHubAbpLocalRepositoryPath != null)
- {
- Logger.LogInformation("GitHub Abp Local Repository Path: " + gitHubAbpLocalRepositoryPath);
- }
-
- var gitHubVoloLocalRepositoryPath = commandLineArgs.Options.GetOrNull(Options.GitHubVoloLocalRepositoryPath.Long);
- if (gitHubVoloLocalRepositoryPath != null)
- {
- Logger.LogInformation("GitHub Volo Local Repository Path: " + gitHubVoloLocalRepositoryPath);
- }
-
- var templateSource = commandLineArgs.Options.GetOrNull(Options.TemplateSource.Short, Options.TemplateSource.Long);
- if (templateSource != null)
- {
- Logger.LogInformation("Template Source: " + templateSource);
- }
-
- var createSolutionFolder = GetCreateSolutionFolderPreference(commandLineArgs);
-
- var outputFolder = commandLineArgs.Options.GetOrNull(Options.OutputFolder.Short, Options.OutputFolder.Long);
-
- var outputFolderRoot =
- outputFolder != null ? Path.GetFullPath(outputFolder) : Directory.GetCurrentDirectory();
-
- SolutionName solutionName;
- if (MicroserviceServiceTemplateBase.IsMicroserviceServiceTemplate(template))
- {
- var microserviceSolutionName = FindMicroserviceSolutionName(outputFolderRoot);
-
- if (microserviceSolutionName == null)
- {
- throw new CliUsageException("This command should be run inside a folder that contains a microservice solution!");
- }
-
- solutionName = SolutionName.Parse(microserviceSolutionName, projectName);
- outputFolder = MicroserviceServiceTemplateBase.CalculateTargetFolder(outputFolderRoot, projectName);
- uiFramework = uiFramework == UiFramework.NotSpecified ? FindMicroserviceSolutionUiFramework(outputFolderRoot) : uiFramework;
- }
- else
- {
- solutionName = SolutionName.Parse(projectName);
-
- outputFolder = createSolutionFolder ?
- Path.Combine(outputFolderRoot, SolutionName.Parse(projectName).FullName) :
- outputFolderRoot;
- }
-
- Volo.Abp.IO.DirectoryHelper.CreateIfNotExists(outputFolder);
-
- Logger.LogInformation("Output folder: " + outputFolder);
-
- if (connectionString == null &&
- databaseManagementSystem != DatabaseManagementSystem.NotSpecified &&
- databaseManagementSystem != DatabaseManagementSystem.SQLServer)
- {
- connectionString = ConnectionStringProvider.GetByDbms(databaseManagementSystem, outputFolder);
- }
-
- commandLineArgs.Options.Add(CliConsts.Command, commandLineArgs.Command);
+ var projectArgs = GetProjectBuildArgs(commandLineArgs, template, projectName);
var result = await TemplateProjectBuilder.BuildAsync(
- new ProjectBuildArgs(
- solutionName,
- template,
- version,
- databaseProvider,
- databaseManagementSystem,
- uiFramework,
- mobileApp,
- publicWebSite,
- gitHubAbpLocalRepositoryPath,
- gitHubVoloLocalRepositoryPath,
- templateSource,
- commandLineArgs.Options,
- connectionString
- )
+ projectArgs
);
- using (var templateFileStream = new MemoryStream(result.ZipContent))
- {
- using (var zipInputStream = new ZipInputStream(templateFileStream))
- {
- var zipEntry = zipInputStream.GetNextEntry();
- while (zipEntry != null)
- {
- if (string.IsNullOrWhiteSpace(zipEntry.Name))
- {
- zipEntry = zipInputStream.GetNextEntry();
- continue;
- }
-
- var fullZipToPath = Path.Combine(outputFolder, zipEntry.Name);
- var directoryName = Path.GetDirectoryName(fullZipToPath);
-
- if (!string.IsNullOrEmpty(directoryName))
- {
- Directory.CreateDirectory(directoryName);
- }
-
- var fileName = Path.GetFileName(fullZipToPath);
- if (fileName.Length == 0)
- {
- zipEntry = zipInputStream.GetNextEntry();
- continue;
- }
-
- var buffer = new byte[4096]; // 4K is optimum
- using (var streamWriter = File.Create(fullZipToPath))
- {
- StreamUtils.Copy(zipInputStream, streamWriter, buffer);
- }
-
- zipEntry = zipInputStream.GetNextEntry();
- }
- }
- }
-
- Logger.LogInformation($"'{projectName}' has been successfully created to '{outputFolder}'");
-
-
- if (AppTemplateBase.IsAppTemplate(template))
- {
- var isCommercial = template == AppProTemplate.TemplateName;
- OpenThanksPage(uiFramework, databaseProvider, isTiered || commandLineArgs.Options.ContainsKey("separate-identity-server"), isCommercial);
- }
- else if (MicroserviceTemplateBase.IsMicroserviceTemplate(template))
- {
- OpenMicroserviceDocumentPage();
- }
- }
-
- private string FindMicroserviceSolutionName(string outputFolderRoot)
- {
- var slnFile = Directory.GetFiles(outputFolderRoot, "*.sln").FirstOrDefault();
-
- if (slnFile == null)
- {
- return null;
- }
-
- return Path.GetFileName(slnFile).RemovePostFix(".sln");
- }
-
- private UiFramework FindMicroserviceSolutionUiFramework(string outputFolderRoot)
- {
- if (Directory.Exists(Path.Combine(outputFolderRoot, "apps", "blazor")))
- {
- return UiFramework.Blazor;
- }
- if (Directory.Exists(Path.Combine(outputFolderRoot, "apps", "web")))
- {
- return UiFramework.Mvc;
- }
- if (Directory.Exists(Path.Combine(outputFolderRoot, "apps", "angular")))
- {
- return UiFramework.Angular;
- }
-
- return UiFramework.None;
- }
-
- private void OpenThanksPage(UiFramework uiFramework, DatabaseProvider databaseProvider, bool tiered, bool commercial)
- {
- uiFramework = uiFramework == UiFramework.NotSpecified || uiFramework == UiFramework.None ? UiFramework.Mvc : uiFramework;
- databaseProvider = databaseProvider == DatabaseProvider.NotSpecified ? DatabaseProvider.EntityFrameworkCore : databaseProvider;
-
- var urlPrefix = commercial ? "commercial" : "www";
- var tieredYesNo = tiered ? "yes" : "no";
- var url = $"https://{urlPrefix}.abp.io/project-created-success?ui={uiFramework:g}&db={databaseProvider:g}&tiered={tieredYesNo}";
-
- CmdHelper.OpenWebPage(url);
- }
-
- private void OpenMicroserviceDocumentPage()
- {
- var url = "https://docs.abp.io/en/commercial/latest/startup-templates/microservice/index";
+ ExtractProjectZip(result, projectArgs.OutputFolder);
- CmdHelper.OpenWebPage(url);
- }
-
- private bool GetCreateSolutionFolderPreference(CommandLineArgs commandLineArgs)
- {
- var longKey = commandLineArgs.Options.ContainsKey(Options.CreateSolutionFolder.Long);
-
- if (longKey == false)
- {
- return commandLineArgs.Options.ContainsKey(Options.CreateSolutionFolder.Short);
- }
-
- return longKey;
- }
+ Logger.LogInformation($"'{projectName}' has been successfully created to '{projectArgs.OutputFolder}'");
- private static string GetConnectionString(CommandLineArgs commandLineArgs)
- {
- var connectionString = commandLineArgs.Options.GetOrNull(Options.ConnectionString.Short, Options.ConnectionString.Long);
- return string.IsNullOrWhiteSpace(connectionString) ? null : connectionString;
+ OpenRelatedWebPage(projectArgs, template, isTiered, commandLineArgs);
}
public string GetUsageInfo()
@@ -389,174 +151,5 @@ namespace Volo.Abp.Cli.Commands
return "Generate a new solution based on the ABP startup templates.";
}
- protected virtual DatabaseProvider GetDatabaseProvider(CommandLineArgs commandLineArgs)
- {
- var optionValue = commandLineArgs.Options.GetOrNull(Options.DatabaseProvider.Short, Options.DatabaseProvider.Long);
- switch (optionValue)
- {
- case "ef":
- return DatabaseProvider.EntityFrameworkCore;
- case "mongodb":
- return DatabaseProvider.MongoDb;
- default:
- return DatabaseProvider.NotSpecified;
- }
- }
-
- protected virtual DatabaseManagementSystem GetDatabaseManagementSystem(CommandLineArgs commandLineArgs)
- {
- var optionValue = commandLineArgs.Options.GetOrNull(Options.DatabaseManagementSystem.Short, Options.DatabaseManagementSystem.Long);
-
- if (optionValue == null)
- {
- return DatabaseManagementSystem.NotSpecified;
- }
-
- switch (optionValue.ToLowerInvariant())
- {
- case "sqlserver":
- return DatabaseManagementSystem.SQLServer;
- case "mysql":
- return DatabaseManagementSystem.MySQL;
- case "postgresql":
- return DatabaseManagementSystem.PostgreSQL;
- case "oracle-devart":
- return DatabaseManagementSystem.OracleDevart;
- case "sqlite":
- return DatabaseManagementSystem.SQLite;
- case "oracle":
- return DatabaseManagementSystem.Oracle;
- default:
- return DatabaseManagementSystem.NotSpecified;
- }
- }
-
- protected virtual UiFramework GetUiFramework(CommandLineArgs commandLineArgs)
- {
- if (commandLineArgs.Options.ContainsKey("no-ui"))
- {
- return UiFramework.None;
- }
-
- var optionValue = commandLineArgs.Options.GetOrNull(Options.UiFramework.Short, Options.UiFramework.Long);
- switch (optionValue)
- {
- case "none":
- return UiFramework.None;
- case "mvc":
- return UiFramework.Mvc;
- case "angular":
- return UiFramework.Angular;
- case "blazor":
- return UiFramework.Blazor;
- case "blazor-server":
- return UiFramework.BlazorServer;
- default:
- return UiFramework.NotSpecified;
- }
- }
-
- protected virtual MobileApp GetMobilePreference(CommandLineArgs commandLineArgs)
- {
- var optionValue = commandLineArgs.Options.GetOrNull(Options.Mobile.Short, Options.Mobile.Long);
-
- switch (optionValue)
- {
- case "none":
- return MobileApp.None;
- case "react-native":
- return MobileApp.ReactNative;
- default:
- return MobileApp.None;
- }
- }
-
- public static class Options
- {
- public static class Template
- {
- public const string Short = "t";
- public const string Long = "template";
- }
-
- public static class DatabaseProvider
- {
- public const string Short = "d";
- public const string Long = "database-provider";
- }
-
- public static class DatabaseManagementSystem
- {
- public const string Short = "dbms";
- public const string Long = "database-management-system";
- }
-
- public static class OutputFolder
- {
- public const string Short = "o";
- public const string Long = "output-folder";
- }
-
- public static class GitHubAbpLocalRepositoryPath
- {
- public const string Long = "abp-path";
- }
-
- public static class GitHubVoloLocalRepositoryPath
- {
- public const string Long = "volo-path";
- }
-
- public static class Version
- {
- public const string Short = "v";
- public const string Long = "version";
- }
-
- public static class UiFramework
- {
- public const string Short = "u";
- public const string Long = "ui";
- }
-
- public static class Mobile
- {
- public const string Short = "m";
- public const string Long = "mobile";
- }
-
- public static class PublicWebSite
- {
- public const string Long = "with-public-website";
- }
-
- public static class TemplateSource
- {
- public const string Short = "ts";
- public const string Long = "template-source";
- }
-
- public static class ConnectionString
- {
- public const string Short = "cs";
- public const string Long = "connection-string";
- }
-
- public static class CreateSolutionFolder
- {
- public const string Short = "csf";
- public const string Long = "create-solution-folder";
- }
-
- public static class Tiered
- {
- public const string Long = "tiered";
- }
-
- public static class Preview
- {
- public const string Long = "preview";
- }
- }
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs
new file mode 100644
index 0000000000..927019f566
--- /dev/null
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ProjectCreationCommandBase.cs
@@ -0,0 +1,449 @@
+using System;
+using System.IO;
+using System.Linq;
+using ICSharpCode.SharpZipLib.Core;
+using ICSharpCode.SharpZipLib.Zip;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+using Volo.Abp.Cli.Args;
+using Volo.Abp.Cli.Commands.Services;
+using Volo.Abp.Cli.ProjectBuilding;
+using Volo.Abp.Cli.ProjectBuilding.Building;
+using Volo.Abp.Cli.ProjectBuilding.Templates.App;
+using Volo.Abp.Cli.ProjectBuilding.Templates.Microservice;
+using Volo.Abp.Cli.Utils;
+
+namespace Volo.Abp.Cli.Commands
+{
+ public abstract class ProjectCreationCommandBase
+ {
+ public ConnectionStringProvider ConnectionStringProvider { get; }
+ public ILogger Logger { get; set; }
+
+ public ProjectCreationCommandBase(ConnectionStringProvider connectionStringProvider)
+ {
+ ConnectionStringProvider = connectionStringProvider;
+
+ Logger = NullLogger.Instance;
+ }
+
+ protected ProjectBuildArgs GetProjectBuildArgs(CommandLineArgs commandLineArgs, string template, string projectName)
+ {
+ var version = commandLineArgs.Options.GetOrNull(Options.Version.Short, Options.Version.Long);
+
+ if (version != null)
+ {
+ Logger.LogInformation("Version: " + version);
+ }
+
+ var preview = commandLineArgs.Options.ContainsKey(Options.Preview.Long);
+ if (preview)
+ {
+ Logger.LogInformation("Preview: yes");
+ }
+
+ var databaseProvider = GetDatabaseProvider(commandLineArgs);
+ if (databaseProvider != DatabaseProvider.NotSpecified)
+ {
+ Logger.LogInformation("Database provider: " + databaseProvider);
+ }
+
+ var connectionString = GetConnectionString(commandLineArgs);
+ if (connectionString != null)
+ {
+ Logger.LogInformation("Connection string: " + connectionString);
+ }
+
+ var databaseManagementSystem = GetDatabaseManagementSystem(commandLineArgs);
+ if (databaseManagementSystem != DatabaseManagementSystem.NotSpecified)
+ {
+ Logger.LogInformation("DBMS: " + databaseManagementSystem);
+ }
+
+ var uiFramework = GetUiFramework(commandLineArgs);
+ if (uiFramework != UiFramework.NotSpecified)
+ {
+ Logger.LogInformation("UI Framework: " + uiFramework);
+ }
+
+ var publicWebSite = uiFramework != UiFramework.None && commandLineArgs.Options.ContainsKey(Options.PublicWebSite.Long);
+ if (publicWebSite)
+ {
+ Logger.LogInformation("Public Web Site: yes");
+ }
+
+ var mobileApp = GetMobilePreference(commandLineArgs);
+ if (mobileApp != MobileApp.None)
+ {
+ Logger.LogInformation("Mobile App: " + mobileApp);
+ }
+
+ var gitHubAbpLocalRepositoryPath = commandLineArgs.Options.GetOrNull(Options.GitHubAbpLocalRepositoryPath.Long);
+ if (gitHubAbpLocalRepositoryPath != null)
+ {
+ Logger.LogInformation("GitHub Abp Local Repository Path: " + gitHubAbpLocalRepositoryPath);
+ }
+
+ var gitHubVoloLocalRepositoryPath = commandLineArgs.Options.GetOrNull(Options.GitHubVoloLocalRepositoryPath.Long);
+ if (gitHubVoloLocalRepositoryPath != null)
+ {
+ Logger.LogInformation("GitHub Volo Local Repository Path: " + gitHubVoloLocalRepositoryPath);
+ }
+
+ var templateSource = commandLineArgs.Options.GetOrNull(Options.TemplateSource.Short, Options.TemplateSource.Long);
+ if (templateSource != null)
+ {
+ Logger.LogInformation("Template Source: " + templateSource);
+ }
+
+ var createSolutionFolder = GetCreateSolutionFolderPreference(commandLineArgs);
+
+ var outputFolder = commandLineArgs.Options.GetOrNull(Options.OutputFolder.Short, Options.OutputFolder.Long);
+
+ var outputFolderRoot =
+ outputFolder != null ? Path.GetFullPath(outputFolder) : Directory.GetCurrentDirectory();
+
+ SolutionName solutionName;
+ if (MicroserviceServiceTemplateBase.IsMicroserviceServiceTemplate(template))
+ {
+ var microserviceSolutionName = FindMicroserviceSolutionName(outputFolderRoot);
+
+ if (microserviceSolutionName == null)
+ {
+ throw new CliUsageException("This command should be run inside a folder that contains a microservice solution!");
+ }
+
+ solutionName = SolutionName.Parse(microserviceSolutionName, projectName);
+ outputFolder = MicroserviceServiceTemplateBase.CalculateTargetFolder(outputFolderRoot, projectName);
+ uiFramework = uiFramework == UiFramework.NotSpecified ? FindMicroserviceSolutionUiFramework(outputFolderRoot) : uiFramework;
+ }
+ else
+ {
+ solutionName = SolutionName.Parse(projectName);
+
+ outputFolder = createSolutionFolder ?
+ Path.Combine(outputFolderRoot, SolutionName.Parse(projectName).FullName) :
+ outputFolderRoot;
+ }
+
+ IO.DirectoryHelper.CreateIfNotExists(outputFolder);
+
+ Logger.LogInformation("Output folder: " + outputFolder);
+
+ if (connectionString == null &&
+ databaseManagementSystem != DatabaseManagementSystem.NotSpecified &&
+ databaseManagementSystem != DatabaseManagementSystem.SQLServer)
+ {
+ connectionString = ConnectionStringProvider.GetByDbms(databaseManagementSystem, outputFolder);
+ }
+
+ commandLineArgs.Options.Add(CliConsts.Command, commandLineArgs.Command);
+
+ return new ProjectBuildArgs(
+ solutionName,
+ template,
+ version,
+ outputFolder,
+ databaseProvider,
+ databaseManagementSystem,
+ uiFramework,
+ mobileApp,
+ publicWebSite,
+ gitHubAbpLocalRepositoryPath,
+ gitHubVoloLocalRepositoryPath,
+ templateSource,
+ commandLineArgs.Options,
+ connectionString
+ );
+ }
+
+ protected void ExtractProjectZip(ProjectBuildResult project, string outputFolder)
+ {
+ using (var templateFileStream = new MemoryStream(project.ZipContent))
+ {
+ using (var zipInputStream = new ZipInputStream(templateFileStream))
+ {
+ var zipEntry = zipInputStream.GetNextEntry();
+ while (zipEntry != null)
+ {
+ if (string.IsNullOrWhiteSpace(zipEntry.Name))
+ {
+ zipEntry = zipInputStream.GetNextEntry();
+ continue;
+ }
+
+ var fullZipToPath = Path.Combine(outputFolder, zipEntry.Name);
+ var directoryName = Path.GetDirectoryName(fullZipToPath);
+
+ if (!string.IsNullOrEmpty(directoryName))
+ {
+ Directory.CreateDirectory(directoryName);
+ }
+
+ var fileName = Path.GetFileName(fullZipToPath);
+ if (fileName.Length == 0)
+ {
+ zipEntry = zipInputStream.GetNextEntry();
+ continue;
+ }
+
+ var buffer = new byte[4096]; // 4K is optimum
+ using (var streamWriter = File.Create(fullZipToPath))
+ {
+ StreamUtils.Copy(zipInputStream, streamWriter, buffer);
+ }
+
+ zipEntry = zipInputStream.GetNextEntry();
+ }
+ }
+ }
+ }
+
+ protected void OpenRelatedWebPage(ProjectBuildArgs projectArgs,
+ string template,
+ bool isTiered,
+ CommandLineArgs commandLineArgs)
+ {
+ if (AppTemplateBase.IsAppTemplate(template))
+ {
+ var isCommercial = template == AppProTemplate.TemplateName;
+ OpenThanksPage(projectArgs.UiFramework, projectArgs.DatabaseProvider, isTiered || commandLineArgs.Options.ContainsKey("separate-identity-server"), isCommercial);
+ }
+ else if (MicroserviceTemplateBase.IsMicroserviceTemplate(template))
+ {
+ OpenMicroserviceDocumentPage();
+ }
+ }
+
+ protected string FindMicroserviceSolutionName(string outputFolderRoot)
+ {
+ var slnFile = Directory.GetFiles(outputFolderRoot, "*.sln").FirstOrDefault();
+
+ if (slnFile == null)
+ {
+ return null;
+ }
+
+ return Path.GetFileName(slnFile).RemovePostFix(".sln");
+ }
+
+ protected UiFramework FindMicroserviceSolutionUiFramework(string outputFolderRoot)
+ {
+ if (Directory.Exists(Path.Combine(outputFolderRoot, "apps", "blazor")))
+ {
+ return UiFramework.Blazor;
+ }
+ if (Directory.Exists(Path.Combine(outputFolderRoot, "apps", "web")))
+ {
+ return UiFramework.Mvc;
+ }
+ if (Directory.Exists(Path.Combine(outputFolderRoot, "apps", "angular")))
+ {
+ return UiFramework.Angular;
+ }
+
+ return UiFramework.None;
+ }
+
+ protected void OpenThanksPage(UiFramework uiFramework, DatabaseProvider databaseProvider, bool tiered, bool commercial)
+ {
+ uiFramework = uiFramework == UiFramework.NotSpecified || uiFramework == UiFramework.None ? UiFramework.Mvc : uiFramework;
+ databaseProvider = databaseProvider == DatabaseProvider.NotSpecified ? DatabaseProvider.EntityFrameworkCore : databaseProvider;
+
+ var urlPrefix = commercial ? "commercial" : "www";
+ var tieredYesNo = tiered ? "yes" : "no";
+ var url = $"https://{urlPrefix}.abp.io/project-created-success?ui={uiFramework:g}&db={databaseProvider:g}&tiered={tieredYesNo}";
+
+ CmdHelper.OpenWebPage(url);
+ }
+
+ protected void OpenMicroserviceDocumentPage()
+ {
+ var url = "https://docs.abp.io/en/commercial/latest/startup-templates/microservice/index";
+
+ CmdHelper.OpenWebPage(url);
+ }
+
+ protected bool GetCreateSolutionFolderPreference(CommandLineArgs commandLineArgs)
+ {
+ return commandLineArgs.Options.ContainsKey(Options.CreateSolutionFolder.Long)
+ || commandLineArgs.Options.ContainsKey(Options.CreateSolutionFolder.Short);
+ }
+
+ protected static string GetConnectionString(CommandLineArgs commandLineArgs)
+ {
+ var connectionString = commandLineArgs.Options.GetOrNull(Options.ConnectionString.Short, Options.ConnectionString.Long);
+ return string.IsNullOrWhiteSpace(connectionString) ? null : connectionString;
+ }
+
+ protected virtual DatabaseProvider GetDatabaseProvider(CommandLineArgs commandLineArgs)
+ {
+ var optionValue = commandLineArgs.Options.GetOrNull(Options.DatabaseProvider.Short, Options.DatabaseProvider.Long);
+ switch (optionValue)
+ {
+ case "ef":
+ return DatabaseProvider.EntityFrameworkCore;
+ case "mongodb":
+ return DatabaseProvider.MongoDb;
+ default:
+ return DatabaseProvider.NotSpecified;
+ }
+ }
+
+ protected virtual DatabaseManagementSystem GetDatabaseManagementSystem(CommandLineArgs commandLineArgs)
+ {
+ var optionValue = commandLineArgs.Options.GetOrNull(Options.DatabaseManagementSystem.Short, Options.DatabaseManagementSystem.Long);
+
+ if (optionValue == null)
+ {
+ return DatabaseManagementSystem.NotSpecified;
+ }
+
+ switch (optionValue.ToLowerInvariant())
+ {
+ case "sqlserver":
+ return DatabaseManagementSystem.SQLServer;
+ case "mysql":
+ return DatabaseManagementSystem.MySQL;
+ case "postgresql":
+ return DatabaseManagementSystem.PostgreSQL;
+ case "oracle-devart":
+ return DatabaseManagementSystem.OracleDevart;
+ case "sqlite":
+ return DatabaseManagementSystem.SQLite;
+ case "oracle":
+ return DatabaseManagementSystem.Oracle;
+ default:
+ return DatabaseManagementSystem.NotSpecified;
+ }
+ }
+
+ protected virtual MobileApp GetMobilePreference(CommandLineArgs commandLineArgs)
+ {
+ var optionValue = commandLineArgs.Options.GetOrNull(Options.Mobile.Short, Options.Mobile.Long);
+
+ switch (optionValue)
+ {
+ case "none":
+ return MobileApp.None;
+ case "react-native":
+ return MobileApp.ReactNative;
+ default:
+ return MobileApp.None;
+ }
+ }
+
+ protected virtual UiFramework GetUiFramework(CommandLineArgs commandLineArgs)
+ {
+ if (commandLineArgs.Options.ContainsKey("no-ui"))
+ {
+ return UiFramework.None;
+ }
+
+ var optionValue = commandLineArgs.Options.GetOrNull(Options.UiFramework.Short, Options.UiFramework.Long);
+ switch (optionValue)
+ {
+ case "none":
+ return UiFramework.None;
+ case "mvc":
+ return UiFramework.Mvc;
+ case "angular":
+ return UiFramework.Angular;
+ case "blazor":
+ return UiFramework.Blazor;
+ case "blazor-server":
+ return UiFramework.BlazorServer;
+ default:
+ return UiFramework.NotSpecified;
+ }
+ }
+
+ public static class Options
+ {
+ public static class Template
+ {
+ public const string Short = "t";
+ public const string Long = "template";
+ }
+
+ public static class DatabaseProvider
+ {
+ public const string Short = "d";
+ public const string Long = "database-provider";
+ }
+
+ public static class DatabaseManagementSystem
+ {
+ public const string Short = "dbms";
+ public const string Long = "database-management-system";
+ }
+
+ public static class OutputFolder
+ {
+ public const string Short = "o";
+ public const string Long = "output-folder";
+ }
+
+ public static class GitHubAbpLocalRepositoryPath
+ {
+ public const string Long = "abp-path";
+ }
+
+ public static class GitHubVoloLocalRepositoryPath
+ {
+ public const string Long = "volo-path";
+ }
+
+ public static class Version
+ {
+ public const string Short = "v";
+ public const string Long = "version";
+ }
+
+ public static class UiFramework
+ {
+ public const string Short = "u";
+ public const string Long = "ui";
+ }
+
+ public static class Mobile
+ {
+ public const string Short = "m";
+ public const string Long = "mobile";
+ }
+
+ public static class PublicWebSite
+ {
+ public const string Long = "with-public-website";
+ }
+
+ public static class TemplateSource
+ {
+ public const string Short = "ts";
+ public const string Long = "template-source";
+ }
+
+ public static class ConnectionString
+ {
+ public const string Short = "cs";
+ public const string Long = "connection-string";
+ }
+
+ public static class CreateSolutionFolder
+ {
+ public const string Short = "csf";
+ public const string Long = "create-solution-folder";
+ }
+
+ public static class Tiered
+ {
+ public const string Long = "tiered";
+ }
+
+ public static class Preview
+ {
+ public const string Long = "preview";
+ }
+ }
+ }
+}
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SourceCodeDownloadService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SourceCodeDownloadService.cs
index 56e5c0a03b..a228068b45 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SourceCodeDownloadService.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Services/SourceCodeDownloadService.cs
@@ -42,6 +42,7 @@ namespace Volo.Abp.Cli.Commands.Services
SolutionName.Parse(moduleName),
moduleName,
version,
+ outputFolder,
DatabaseProvider.NotSpecified,
DatabaseManagementSystem.NotSpecified,
UiFramework.NotSpecified,
@@ -106,7 +107,8 @@ namespace Volo.Abp.Cli.Commands.Services
new ProjectBuildArgs(
SolutionName.Parse(packageName),
packageName,
- version
+ version,
+ outputFolder
)
);
@@ -156,7 +158,8 @@ namespace Volo.Abp.Cli.Commands.Services
new ProjectBuildArgs(
SolutionName.Parse(packageName),
packageName,
- version
+ version,
+ outputFolder
)
);
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/TranslateCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/TranslateCommand.cs
index c3eeddc443..a9f7a15a9a 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/TranslateCommand.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/TranslateCommand.cs
@@ -59,7 +59,7 @@ namespace Volo.Abp.Cli.Commands
Logger.LogInformation("Target culture: " + targetCulture);
Logger.LogInformation("Reference culture: " + referenceCulture);
Logger.LogInformation("Output file: " + outputFile);
-
+
if (allValues)
{
Logger.LogInformation("Include all keys");
@@ -195,8 +195,11 @@ namespace Volo.Abp.Cli.Commands
var targetText = targetLocalizationInfo.Texts.FirstOrDefault(x => x.Name == text.LocalizationKey);
if (targetText != null)
{
- Logger.LogInformation($"Update translation: {targetText.Name} => " + text.Target);
- targetText.Value = text.Target;
+ if (!text.Target.IsNullOrEmpty())
+ {
+ Logger.LogInformation($"Update translation: {targetText.Name} => " + text.Target);
+ targetText.Value = text.Target;
+ }
}
else
{
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ReplaceCommonPropsStep.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ReplaceCommonPropsStep.cs
index 862ac39b09..c615bcdfce 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ReplaceCommonPropsStep.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/ReplaceCommonPropsStep.cs
@@ -60,7 +60,9 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps
foreach (XmlNode node in importNodes)
{
- if (!(node.Attributes?["Project"]?.Value?.EndsWith("\\common.props") ?? false))
+ var value = node.Attributes?["Project"]?.Value;
+
+ if (value == null || (!value.EndsWith("\\common.props") && !value.EndsWith("\\common.test.props")))
{
continue;
}
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs
index 712de9e327..e2d4d5faa1 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/TemplateProjectBuildPipelineBuilder.cs
@@ -1,4 +1,5 @@
using System;
+using NuGet.Versioning;
using Volo.Abp.Cli.ProjectBuilding.Building.Steps;
using Volo.Abp.Cli.ProjectBuilding.Templates.App;
using Volo.Abp.Cli.ProjectBuilding.Templates.Microservice;
@@ -13,7 +14,11 @@ namespace Volo.Abp.Cli.ProjectBuilding.Building
var pipeline = new ProjectBuildPipeline(context);
pipeline.Steps.Add(new FileEntryListReadStep());
- pipeline.Steps.Add(new CreateAppSettingsSecretsStep());
+
+ if (SemanticVersion.Parse(context.TemplateFile.Version) > new SemanticVersion(4, 3, 99))
+ {
+ pipeline.Steps.Add(new CreateAppSettingsSecretsStep());
+ }
pipeline.Steps.AddRange(context.Template.GetCustomSteps(context));
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuildArgs.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuildArgs.cs
index 71ccf96f7a..01b21bf858 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuildArgs.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/ProjectBuildArgs.cs
@@ -37,6 +37,9 @@ namespace Volo.Abp.Cli.ProjectBuilding
[CanBeNull]
public string ConnectionString { get; set; }
+ [NotNull]
+ public string OutputFolder { get; set; }
+
[NotNull]
public Dictionary ExtraProperties { get; set; }
@@ -44,6 +47,7 @@ namespace Volo.Abp.Cli.ProjectBuilding
[NotNull] SolutionName solutionName,
[CanBeNull] string templateName = null,
[CanBeNull] string version = null,
+ string outputFolder = null,
DatabaseProvider databaseProvider = DatabaseProvider.NotSpecified,
DatabaseManagementSystem databaseManagementSystem = DatabaseManagementSystem.NotSpecified,
UiFramework uiFramework = UiFramework.NotSpecified,
@@ -58,6 +62,7 @@ namespace Volo.Abp.Cli.ProjectBuilding
SolutionName = Check.NotNull(solutionName, nameof(solutionName));
TemplateName = templateName;
Version = version;
+ OutputFolder = outputFolder;
DatabaseProvider = databaseProvider;
DatabaseManagementSystem = databaseManagementSystem;
UiFramework = uiFramework;
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs
index 663d4e9bad..0d6a30719d 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/Module/ModuleTemplateBase.cs
@@ -53,6 +53,11 @@ namespace Volo.Abp.Cli.ProjectBuilding.Templates.Module
projectFolderPath: "/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host"
));
+ steps.Add(new RemoveProjectFromSolutionStep(
+ "MyCompanyName.MyProjectName.Blazor.Server.Host",
+ projectFolderPath: "/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host"
+ ));
+
steps.Add(new RemoveProjectFromSolutionStep(
"MyCompanyName.MyProjectName.Web.Host",
projectFolderPath: "/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host"
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationManager.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationManager.cs
index 8143acf7b8..05996b90d7 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationManager.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/EfCoreMigrationManager.cs
@@ -69,9 +69,10 @@ namespace Volo.Abp.Cli.ProjectModification
protected virtual string FindDbContextName(string dbMigrationsFolder)
{
- var dbContext = Directory
- .GetFiles(dbMigrationsFolder, "*MigrationsDbContext.cs", SearchOption.AllDirectories)
- .FirstOrDefault(fp => !fp.EndsWith("TenantMigrationsDbContext.cs"));
+ var dbContext = Directory.GetFiles(dbMigrationsFolder, "*MigrationsDbContext.cs", SearchOption.AllDirectories)
+ .FirstOrDefault(fp => !fp.EndsWith("TenantMigrationsDbContext.cs")) ??
+ Directory.GetFiles(dbMigrationsFolder, "*DbContext.cs", SearchOption.AllDirectories)
+ .FirstOrDefault(fp => !fp.EndsWith("TenantDbContext.cs"));
if (dbContext == null)
{
@@ -83,9 +84,10 @@ namespace Volo.Abp.Cli.ProjectModification
protected virtual string FindTenantDbContextName(string dbMigrationsFolder)
{
- var tenantDbContext = Directory
- .GetFiles(dbMigrationsFolder, "*TenantMigrationsDbContext.cs", SearchOption.AllDirectories)
- .FirstOrDefault();
+ var tenantDbContext = Directory.GetFiles(dbMigrationsFolder, "*TenantMigrationsDbContext.cs", SearchOption.AllDirectories)
+ .FirstOrDefault() ??
+ Directory.GetFiles(dbMigrationsFolder, "*TenantDbContext.cs", SearchOption.AllDirectories)
+ .FirstOrDefault();
if (tenantDbContext == null)
{
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NugetPackageToLocalReferenceConverter.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NugetPackageToLocalReferenceConverter.cs
index 8e45378f72..efecee8d79 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NugetPackageToLocalReferenceConverter.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/NugetPackageToLocalReferenceConverter.cs
@@ -67,7 +67,8 @@ namespace Volo.Abp.Cli.ProjectModification
if (oldNodeIncludeValue.EndsWith(".test", StringComparison.InvariantCultureIgnoreCase) ||
oldNodeIncludeValue.EndsWith(".tests", StringComparison.InvariantCultureIgnoreCase) ||
- oldNodeIncludeValue.EndsWith(".testbase", StringComparison.InvariantCultureIgnoreCase))
+ oldNodeIncludeValue.EndsWith(".testbase", StringComparison.InvariantCultureIgnoreCase)||
+ oldNodeIncludeValue.EndsWith(".Demo", StringComparison.InvariantCultureIgnoreCase))
{
tempSourceFile = "test";
}
diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs
index 273f011f41..62d490d64d 100644
--- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs
+++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs
@@ -576,11 +576,12 @@ namespace Volo.Abp.Cli.ProjectModification
return;
}
- var dbMigrationsProject = projectFiles.FirstOrDefault(p => p.EndsWith(".DbMigrations.csproj"));
+ var dbMigrationsProject = projectFiles.FirstOrDefault(p => p.EndsWith(".DbMigrations.csproj"))
+ ?? projectFiles.FirstOrDefault(p => p.EndsWith(".EntityFrameworkCore.csproj")) ;
if (dbMigrationsProject == null)
{
- Logger.LogDebug("Solution doesn't have a \".DbMigrations\" project.");
+ Logger.LogDebug("Solution doesn't have a Migrations project.");
if (!skipDbMigrations)
{
diff --git a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj
index 15b967b9e4..5909bb632f 100644
--- a/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj
+++ b/framework/src/Volo.Abp.Core/Volo.Abp.Core.csproj
@@ -25,6 +25,7 @@
+
diff --git a/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/ro-RO.json b/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/ro-RO.json
new file mode 100644
index 0000000000..1daa63ea0e
--- /dev/null
+++ b/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Localization/Resources/AbpDdd/ro-RO.json
@@ -0,0 +1,6 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "MaxResultCountExceededExceptionMessage": "{0} nu poate fi mai mare decât {1}! Măriţi {2}.{3} pe partea de server pentru a permite mai multe rezultate."
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IReadOnlyBasicRepository.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IReadOnlyBasicRepository.cs
index ed97d87ffa..a6988e5c10 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IReadOnlyBasicRepository.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IReadOnlyBasicRepository.cs
@@ -1,6 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq.Expressions;
+using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
@@ -18,19 +16,7 @@ namespace Volo.Abp.Domain.Repositories
/// A to observe while waiting for the task to complete.
/// Entity
Task> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default);
-
- ///
- /// Gets a list entities by the given .
- ///
- /// A condition to find the entity
- /// Set true to include all children of this entity
- /// A to observe while waiting for the task to complete.
- /// Entity
- Task> GetListAsync(
- [NotNull] Expression> predicate,
- bool includeDetails = false,
- CancellationToken cancellationToken = default);
-
+
///
/// Gets total count of all entities.
///
diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IReadOnlyRepository.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IReadOnlyRepository.cs
index 80d1425044..7aeffdad12 100644
--- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IReadOnlyRepository.cs
+++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IReadOnlyRepository.cs
@@ -1,7 +1,10 @@
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
+using System.Threading;
using System.Threading.Tasks;
+using JetBrains.Annotations;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Linq;
@@ -23,6 +26,17 @@ namespace Volo.Abp.Domain.Repositories
Task> WithDetailsAsync(params Expression>[] propertySelectors); //TODO: CancellationToken
Task> GetQueryableAsync(); //TODO: CancellationToken
+
+ ///
+ /// Gets a list of entities by the given .
+ ///
+ /// A condition to filter the entities
+ /// Set true to include details (sub-collections) of this entity
+ /// A to observe while waiting for the task to complete.
+ Task> GetListAsync(
+ [NotNull] Expression> predicate,
+ bool includeDetails = false,
+ CancellationToken cancellationToken = default);
}
public interface IReadOnlyRepository : IReadOnlyRepository, IReadOnlyBasicRepository
diff --git a/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Localization/ro-RO.json b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Localization/ro-RO.json
new file mode 100644
index 0000000000..46cd358125
--- /dev/null
+++ b/framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Localization/ro-RO.json
@@ -0,0 +1,25 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "DisplayName:Abp.Mailing.DefaultFromAddress": "Implicit de la adresa",
+ "DisplayName:Abp.Mailing.DefaultFromDisplayName": "Implicit de la numele afişat",
+ "DisplayName:Abp.Mailing.Smtp.Host": "Host",
+ "DisplayName:Abp.Mailing.Smtp.Port": "Port",
+ "DisplayName:Abp.Mailing.Smtp.UserName": "Nume de utilizator",
+ "DisplayName:Abp.Mailing.Smtp.Password": "Parola",
+ "DisplayName:Abp.Mailing.Smtp.Domain": "Domeniu",
+ "DisplayName:Abp.Mailing.Smtp.EnableSsl": "Activează SSL",
+ "DisplayName:Abp.Mailing.Smtp.UseDefaultCredentials": "Folosiţi credenţialele implicite",
+ "Description:Abp.Mailing.DefaultFromAddress": "Implicit de la adresa",
+ "Description:Abp.Mailing.DefaultFromDisplayName": "Implicit de la numele afişat",
+ "Description:Abp.Mailing.Smtp.Host": "Numele sau adresa IP al hostului folosit pentru tranzacţiile SMTP.",
+ "Description:Abp.Mailing.Smtp.Port": "Portul folosit pentru tranzacţiile SMTP.",
+ "Description:Abp.Mailing.Smtp.UserName": "Numele de utilizator asociat credenţialelor.",
+ "Description:Abp.Mailing.Smtp.Password": "Parola folosită pentru numele de utilizator asociat credenţialelor.",
+ "Description:Abp.Mailing.Smtp.Domain": "Domeniul sau numele calculatorului care verifică credenţialele.",
+ "Description:Abp.Mailing.Smtp.EnableSsl": "Dacă SmtpClient foloseste Secure Sockets Layer (SSL) pentru a cripta conexiunea.",
+ "Description:Abp.Mailing.Smtp.UseDefaultCredentials": "Dacă DefaultCredentials sunt trimise odată cu solicitările.",
+ "TextTemplate:StandardEmailTemplates.Layout": "Şablon aspect implicit pentru email",
+ "TextTemplate:StandardEmailTemplates.Message": "Şablon de mesaj simplu pentru emailuri"
+ }
+}
diff --git a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Local/LocalEventBus.cs b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Local/LocalEventBus.cs
index 16246a892f..3dc6045250 100644
--- a/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Local/LocalEventBus.cs
+++ b/framework/src/Volo.Abp.EventBus/Volo/Abp/EventBus/Local/LocalEventBus.cs
@@ -30,17 +30,13 @@ namespace Volo.Abp.EventBus.Local
protected ConcurrentDictionary> HandlerFactories { get; }
- protected IJsonSerializer Serializer { get; }
-
public LocalEventBus(
IOptions options,
IServiceScopeFactory serviceScopeFactory,
ICurrentTenant currentTenant,
- IEventErrorHandler errorHandler,
- IJsonSerializer serializer)
+ IEventErrorHandler errorHandler)
: base(serviceScopeFactory, currentTenant, errorHandler)
{
- Serializer = serializer;
Options = options.Value;
Logger = NullLogger.Instance;
@@ -131,10 +127,9 @@ namespace Volo.Abp.EventBus.Local
public virtual async Task PublishAsync(LocalEventMessage localEventMessage)
{
- var rawEventData = Serializer.Serialize(localEventMessage.EventData);
await TriggerHandlersAsync(localEventMessage.EventType, localEventMessage.EventData, errorContext =>
{
- errorContext.EventData = Serializer.Deserialize(localEventMessage.EventType, rawEventData);
+ errorContext.EventData = localEventMessage.EventData;
errorContext.SetProperty(nameof(LocalEventMessage.MessageId), localEventMessage.MessageId);
});
}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/ro-RO.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/ro-RO.json
new file mode 100644
index 0000000000..e04cf971e8
--- /dev/null
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/ro-RO.json
@@ -0,0 +1,26 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "InternalServerErrorMessage": "A intervenit o eroare internă în timpul solicitării dumneavoastră!",
+ "ValidationErrorMessage": "Solicitarea dumneavoastră este invalidă!",
+ "ValidationNarrativeErrorMessageTitle": "Următoarele erori au fost detectate în timpul validării",
+ "DefaultErrorMessage": "A intervenit o eroare!",
+ "DefaultErrorMessageDetail": "Detaliile erorii nu au fost trimise de către server.",
+ "DefaultErrorMessage401": "Nu sunteţi autentificat!",
+ "DefaultErrorMessage401Detail": "Ar trebui să vă autentificaţi pentru a efectua această operaţie.",
+ "DefaultErrorMessage403": "Nu sunteţi autorizat!",
+ "DefaultErrorMessage403Detail": "Nu sunteţi autorizat să efectuaţi această operaţie!",
+ "DefaultErrorMessage404": "Resursa nu a fost găsită!",
+ "DefaultErrorMessage404Detail": "Resursa solicitată nu a fost găsită pe server!",
+ "EntityNotFoundErrorMessage": "Nu există entitatea {0} cu id-ul {1}!",
+ "AbpDbConcurrencyErrorMessage": "Datele pe care le-aţi trimis au fost modificate deja de către alt utilizator/client. Vă rugăm să renunţaţi la modificările pe care le-aţi făcut şi să încercaţi de la început.",
+ "Error": "Eroare",
+ "UnhandledException": "Excepţie netratată!",
+ "401Message": "Neautorizat",
+ "403Message": "Interzis",
+ "404Message": "Pagina nu a fost găsită",
+ "500Message": "Eroare internă a serverului",
+ "403MessageDetail": "Nu sunteţi autorizat să efectuaţi această operaţie!",
+ "404MessageDetail": "Ne cerem scuze, nu este nimic la această adresă."
+ }
+}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/zh-Hans.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/zh-Hans.json
index c5c7783381..08213a79a7 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/zh-Hans.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/zh-Hans.json
@@ -13,6 +13,7 @@
"DefaultErrorMessage404": "未找到资源!",
"DefaultErrorMessage404Detail": "未在服务中找到请求的资源!",
"EntityNotFoundErrorMessage": "实体 {0} 不存在,id = {1}!",
+ "AbpDbConcurrencyErrorMessage": "你提交的数据已经被其他用户/客户端修改.请放弃你所做的修改并再次尝试.",
"Error": "错误",
"UnhandledException": "未处理的异常!",
"401Message": "未授权",
@@ -22,4 +23,4 @@
"403MessageDetail": "您没有权限执行此操作",
"404MessageDetail": "抱歉, 这个地址是空的"
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/zh-Hant.json b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/zh-Hant.json
index f934d77187..65d4f657dd 100644
--- a/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/zh-Hant.json
+++ b/framework/src/Volo.Abp.ExceptionHandling/Volo/Abp/ExceptionHandling/Localization/zh-Hant.json
@@ -13,6 +13,7 @@
"DefaultErrorMessage404": "未找到資源!",
"DefaultErrorMessage404Detail": "未在服務中找到請求的資源!",
"EntityNotFoundErrorMessage": "實體 {0} 不存在,id = {1}!",
+ "AbpDbConcurrencyErrorMessage": "你提交的數據已經被其他用戶/客戶端修改.請放棄你所做的修改並再次嘗試.",
"Error": "錯誤",
"UnhandledException": "未處理的異常!",
"401Message": "未授權",
@@ -22,4 +23,4 @@
"403MessageDetail": "你不被授權執行此操作",
"404MessageDetail": "對不起,地址是空的"
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/ro-RO.json b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/ro-RO.json
new file mode 100644
index 0000000000..07748edfd5
--- /dev/null
+++ b/framework/src/Volo.Abp.Features/Volo/Abp/Features/Localization/ro-RO.json
@@ -0,0 +1,8 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "Volo.Feature:010001": "Caracteristica nu este activată: {FeatureName}",
+ "Volo.Feature:010002": "Caracteristicile necesare nu sunt activate. Toate aceste caracteristici trebuie activate: {FeatureNames}",
+ "Volo.Feature:010003": "Caracteristicile necesare nu sunt activate. Cel puţin una din aceste caracteristici trebuie activată: {FeatureNames}"
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/FluentObjectValidationContributor.cs b/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/FluentObjectValidationContributor.cs
index ccc290f354..e2d0f39372 100644
--- a/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/FluentObjectValidationContributor.cs
+++ b/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/FluentObjectValidationContributor.cs
@@ -2,6 +2,7 @@ using FluentValidation;
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
+using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Validation;
@@ -17,7 +18,7 @@ namespace Volo.Abp.FluentValidation
_serviceProvider = serviceProvider;
}
- public void AddErrors(ObjectValidationContext context)
+ public virtual async Task AddErrorsAsync(ObjectValidationContext context)
{
var serviceType = typeof(IValidator<>).MakeGenericType(context.ValidatingObject.GetType());
var validator = _serviceProvider.GetService(serviceType) as IValidator;
@@ -26,7 +27,7 @@ namespace Volo.Abp.FluentValidation
return;
}
- var result = validator.Validate((IValidationContext) Activator.CreateInstance(
+ var result = await validator.ValidateAsync((IValidationContext) Activator.CreateInstance(
typeof(ValidationContext<>).MakeGenericType(context.ValidatingObject.GetType()),
context.ValidatingObject));
diff --git a/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/ro-RO.json b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/ro-RO.json
new file mode 100644
index 0000000000..f2b0fa0d7b
--- /dev/null
+++ b/framework/src/Volo.Abp.GlobalFeatures/Volo/Abp/GlobalFeatures/Localization/ro-RO.json
@@ -0,0 +1,6 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "Volo.GlobalFeature:010001": "Serviciul '{ServiceName}' trebuie să activeze caracteristica '{GlobalFeatureName}'."
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj b/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj
index 4ec9d0a3b5..6b598d0edd 100644
--- a/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj
+++ b/framework/src/Volo.Abp.HangFire/Volo.Abp.HangFire.csproj
@@ -19,6 +19,7 @@
+
diff --git a/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireAuthorizationFilter.cs b/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireAuthorizationFilter.cs
new file mode 100644
index 0000000000..15fbb4f60c
--- /dev/null
+++ b/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireAuthorizationFilter.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Threading.Tasks;
+using Hangfire.Dashboard;
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Authorization.Permissions;
+using Volo.Abp.Users;
+
+namespace Volo.Abp.Hangfire
+{
+ public class AbpHangfireAuthorizationFilter : IDashboardAsyncAuthorizationFilter
+ {
+ private readonly string _requiredPermissionName;
+
+ public AbpHangfireAuthorizationFilter(string requiredPermissionName = null)
+ {
+ _requiredPermissionName = requiredPermissionName;
+ }
+
+ public async Task AuthorizeAsync(DashboardContext context)
+ {
+ if (!IsLoggedIn(context))
+ {
+ return false;
+ }
+
+ if (_requiredPermissionName.IsNullOrEmpty())
+ {
+ return true;
+ }
+
+ return await IsPermissionGrantedAsync(context, _requiredPermissionName);
+ }
+
+ private static bool IsLoggedIn(DashboardContext context)
+ {
+ var currentUser = context.GetHttpContext().RequestServices.GetRequiredService();
+ return currentUser.IsAuthenticated;
+ }
+
+ private static async Task IsPermissionGrantedAsync(DashboardContext context, string requiredPermissionName)
+ {
+ var permissionChecker = context.GetHttpContext().RequestServices.GetRequiredService();
+ return await permissionChecker.IsGrantedAsync(requiredPermissionName);
+ }
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireModule.cs b/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireModule.cs
index d69edb0b5d..1628d2f37f 100644
--- a/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireModule.cs
+++ b/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireModule.cs
@@ -1,10 +1,12 @@
using Hangfire;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
+using Volo.Abp.Authorization;
using Volo.Abp.Modularity;
namespace Volo.Abp.Hangfire
{
+ [DependsOn(typeof(AbpAuthorizationAbstractionsModule))]
public class AbpHangfireModule : AbpModule
{
private BackgroundJobServer _backgroundJobServer;
diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs
index a83d25910a..b1763d8825 100644
--- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs
+++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/DynamicHttpProxyInterceptor.cs
@@ -173,7 +173,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying
var response = await client.SendAsync(
requestMessage,
HttpCompletionOption.ResponseHeadersRead /*this will buffer only the headers, the content will be used as a stream*/,
- GetCancellationToken()
+ GetCancellationToken(invocation)
);
if (!response.IsSuccessStatusCode)
@@ -305,8 +305,18 @@ namespace Volo.Abp.Http.Client.DynamicProxying
return input;
}
- protected virtual CancellationToken GetCancellationToken()
+ protected virtual CancellationToken GetCancellationToken(IAbpMethodInvocation invocation)
{
+ var cancellationTokenArg = invocation.Arguments.LastOrDefault(x => x is CancellationToken);
+ if (cancellationTokenArg != null)
+ {
+ var cancellationToken = (CancellationToken) cancellationTokenArg;
+ if (cancellationToken != default)
+ {
+ return cancellationToken;
+ }
+ }
+
return CancellationTokenProvider.Token;
}
}
diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerOptionsSetup.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerOptionsSetup.cs
index 9fd156439b..4de6e96bcc 100644
--- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerOptionsSetup.cs
+++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerOptionsSetup.cs
@@ -1,4 +1,5 @@
using System;
+using System.Text.Encodings.Web;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.Json.SystemTextJson.JsonConverters;
@@ -24,6 +25,9 @@ namespace Volo.Abp.Json.SystemTextJson
options.JsonSerializerOptions.Converters.Add(new ObjectToInferredTypesConverter());
options.JsonSerializerOptions.Converters.Add(new AbpHasExtraPropertiesJsonConverterFactory());
+
+ // If the user hasn't explicitly configured the encoder, use the less strict encoder that does not encode all non-ASCII characters.
+ options.JsonSerializerOptions.Encoder ??= JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
}
}
}
diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpHasExtraPropertiesJsonConverter.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpHasExtraPropertiesJsonConverter.cs
index 47640ec306..ebd561c0ae 100644
--- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpHasExtraPropertiesJsonConverter.cs
+++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpHasExtraPropertiesJsonConverter.cs
@@ -11,9 +11,18 @@ namespace Volo.Abp.Json.SystemTextJson.JsonConverters
{
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
- var newOptions = JsonSerializerOptionsHelper.Create(options, x =>
- x == this ||
- x.GetType() == typeof(AbpHasExtraPropertiesJsonConverterFactory));
+ var newOptions = JsonSerializerOptionsHelper.Create(options, x => x == this);
+
+ var converterFactory = newOptions.Converters.FirstOrDefault(x => x is AbpHasExtraPropertiesJsonConverterFactory).As();
+ var newConverterFactory = new AbpHasExtraPropertiesJsonConverterFactory();
+ if (converterFactory != null)
+ {
+ newOptions.Converters.Remove(converterFactory);
+ newConverterFactory.AddExcludeTypes(converterFactory.GetExcludeTypes().ToArray());
+ }
+
+ newConverterFactory.AddExcludeTypes(typeToConvert);
+ newOptions.Converters.Add(newConverterFactory);
var rootElement = JsonDocument.ParseValue(ref reader).RootElement;
if (rootElement.ValueKind == JsonValueKind.Object)
diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpHasExtraPropertiesJsonConverterFactory.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpHasExtraPropertiesJsonConverterFactory.cs
index f654504e05..dff25e00df 100644
--- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpHasExtraPropertiesJsonConverterFactory.cs
+++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpHasExtraPropertiesJsonConverterFactory.cs
@@ -1,5 +1,7 @@
using System;
using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Collections.Immutable;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
@@ -11,8 +13,26 @@ namespace Volo.Abp.Json.SystemTextJson.JsonConverters
{
private static readonly ConcurrentDictionary CachedTypes = new ConcurrentDictionary();
+ private readonly List _excludeTypes = new List();
+
+ public virtual AbpHasExtraPropertiesJsonConverterFactory AddExcludeTypes(params Type[] excludeTypes)
+ {
+ _excludeTypes.AddIfNotContains(excludeTypes);
+ return this;
+ }
+
+ public virtual IReadOnlyList GetExcludeTypes()
+ {
+ return _excludeTypes.ToImmutableList();
+ }
+
public override bool CanConvert(Type typeToConvert)
{
+ if (_excludeTypes.Contains(typeToConvert))
+ {
+ return false;
+ }
+
//Only for private or protected ExtraProperties.
if (typeof(IHasExtraProperties).IsAssignableFrom(typeToConvert))
{
diff --git a/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Localization/ro-RO.json b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Localization/ro-RO.json
new file mode 100644
index 0000000000..0444f908b3
--- /dev/null
+++ b/framework/src/Volo.Abp.Ldap/Volo/Abp/Ldap/Localization/ro-RO.json
@@ -0,0 +1,19 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "DisplayName:Abp.Ldap.ServerHost": "Server host",
+ "Description:Abp.Ldap.ServerHost": "Server host",
+
+ "DisplayName:Abp.Ldap.ServerPort": "Server port",
+ "Description:Abp.Ldap.ServerPort": "Server port",
+
+ "DisplayName:Abp.Ldap.BaseDc": "Componenta domeniului de bază",
+ "Description:Abp.Ldap.BaseDc": "Componenta domeniului de bază",
+
+ "DisplayName:Abp.Ldap.UserName": "Nume de utilizator",
+ "Description:Abp.Ldap.UserName": "Nume de utilizator",
+
+ "DisplayName:Abp.Ldap.Password": "Parola",
+ "Description:Abp.Ldap.Password": "Parola"
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpLocalization/ro-RO.json b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpLocalization/ro-RO.json
new file mode 100644
index 0000000000..2201b39e0b
--- /dev/null
+++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Resources/AbpLocalization/ro-RO.json
@@ -0,0 +1,7 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "DisplayName:Abp.Localization.DefaultLanguage": "Limba implicită",
+ "Description:Abp.Localization.DefaultLanguage": "Limba implicită a aplicaţiei."
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Sms.Aliyun/Volo.Abp.Sms.Aliyun.csproj b/framework/src/Volo.Abp.Sms.Aliyun/Volo.Abp.Sms.Aliyun.csproj
index cae6301daf..83cea09848 100644
--- a/framework/src/Volo.Abp.Sms.Aliyun/Volo.Abp.Sms.Aliyun.csproj
+++ b/framework/src/Volo.Abp.Sms.Aliyun/Volo.Abp.Sms.Aliyun.csproj
@@ -18,6 +18,7 @@
+
diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/CancellationTokenOverride.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/CancellationTokenOverride.cs
new file mode 100644
index 0000000000..371e3d6652
--- /dev/null
+++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/CancellationTokenOverride.cs
@@ -0,0 +1,14 @@
+using System.Threading;
+
+namespace Volo.Abp.Threading
+{
+ public class CancellationTokenOverride
+ {
+ public CancellationToken CancellationToken { get; }
+
+ public CancellationTokenOverride(CancellationToken cancellationToken)
+ {
+ CancellationToken = cancellationToken;
+ }
+ }
+}
diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/CancellationTokenProviderBase.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/CancellationTokenProviderBase.cs
new file mode 100644
index 0000000000..20101a95da
--- /dev/null
+++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/CancellationTokenProviderBase.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Threading;
+
+namespace Volo.Abp.Threading
+{
+ public abstract class CancellationTokenProviderBase : ICancellationTokenProvider
+ {
+ public const string CancellationTokenOverrideContextKey = "Volo.Abp.Threading.CancellationToken.Override";
+
+ public abstract CancellationToken Token { get; }
+
+ protected IAmbientScopeProvider CancellationTokenOverrideScopeProvider { get; }
+
+ protected CancellationTokenOverride OverrideValue => CancellationTokenOverrideScopeProvider.GetValue(CancellationTokenOverrideContextKey);
+
+ protected CancellationTokenProviderBase(IAmbientScopeProvider cancellationTokenOverrideScopeProvider)
+ {
+ CancellationTokenOverrideScopeProvider = cancellationTokenOverrideScopeProvider;
+ }
+
+ public IDisposable Use(CancellationToken cancellationToken)
+ {
+ return CancellationTokenOverrideScopeProvider.BeginScope(CancellationTokenOverrideContextKey, new CancellationTokenOverride(cancellationToken));
+ }
+ }
+}
diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/ICancellationTokenProvider.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/ICancellationTokenProvider.cs
index 24e303adde..06dc008d52 100644
--- a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/ICancellationTokenProvider.cs
+++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/ICancellationTokenProvider.cs
@@ -1,9 +1,12 @@
-using System.Threading;
+using System;
+using System.Threading;
namespace Volo.Abp.Threading
{
public interface ICancellationTokenProvider
{
CancellationToken Token { get; }
+
+ IDisposable Use(CancellationToken cancellationToken);
}
}
diff --git a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/NullCancellationTokenProvider.cs b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/NullCancellationTokenProvider.cs
index ab6320546c..6c2b4d364c 100644
--- a/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/NullCancellationTokenProvider.cs
+++ b/framework/src/Volo.Abp.Threading/Volo/Abp/Threading/NullCancellationTokenProvider.cs
@@ -2,15 +2,15 @@
namespace Volo.Abp.Threading
{
- public class NullCancellationTokenProvider : ICancellationTokenProvider
+ public class NullCancellationTokenProvider : CancellationTokenProviderBase
{
public static NullCancellationTokenProvider Instance { get; } = new NullCancellationTokenProvider();
- public CancellationToken Token { get; } = CancellationToken.None;
+ public override CancellationToken Token => OverrideValue?.CancellationToken ?? CancellationToken.None;
private NullCancellationTokenProvider()
+ : base(new AmbientDataContextAmbientScopeProvider(new AsyncLocalAmbientDataContext()))
{
-
}
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/ro-RO.json b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/ro-RO.json
new file mode 100644
index 0000000000..08716f8f5f
--- /dev/null
+++ b/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/ro-RO.json
@@ -0,0 +1,7 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "DisplayName:Abp.Timing.Timezone": "Fus orar",
+ "Description:Abp.Timing.Timezone": "Fusul orar al aplicaţiei"
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/ro-RO.json b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/ro-RO.json
new file mode 100644
index 0000000000..fc7069e2f9
--- /dev/null
+++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/ro-RO.json
@@ -0,0 +1,6 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "Menu:Administration": "Administrare"
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ro-RO.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ro-RO.json
new file mode 100644
index 0000000000..b7562858d6
--- /dev/null
+++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ro-RO.json
@@ -0,0 +1,52 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "Languages": "Limbi",
+ "AreYouSure": "Sunteţi sigur(ă)?",
+ "Cancel": "Anulează",
+ "Clear": "Goleşte",
+ "Yes": "Da",
+ "No": "Nu",
+ "Ok": "Ok",
+ "Close": "Închide",
+ "Save": "Salvează",
+ "SavingWithThreeDot": "Se salvează...",
+ "Actions": "Acţiuni",
+ "Delete": "Şterge",
+ "Edit": "Editează",
+ "Refresh": "Reîncarcă",
+ "Language": "Limba",
+ "LoadMore": "Încarcă mai multe",
+ "ProcessingWithThreeDot": "Se procesează...",
+ "LoadingWithThreeDot": "Se încarcă...",
+ "Welcome": "Bun venit",
+ "Login": "Autentificare",
+ "Register": "Înregistrare",
+ "Logout": "Delogare",
+ "Submit": "Trimite",
+ "Back": "Înapoi",
+ "PagerSearch": "Caută",
+ "PagerNext": "Următorul",
+ "PagerPrevious": "Anterior",
+ "PagerFirst": "Primul",
+ "PagerLast": "Ultimul",
+ "PagerInfo": "Afişate _START_ to _END_ of _TOTAL_ înregistrări",
+ "PagerInfo{0}{1}{2}": "Afişate {0} to {1} of {2} înregistrări",
+ "PagerInfoEmpty": "Afişate 0 to 0 of 0 înregistrări",
+ "PagerInfoFiltered": "(filtrate de la _MAX_ înregistrări totale)",
+ "NoDataAvailableInDatatable": "Nicio informaţie disponibilă",
+ "Total": "total",
+ "Selected": "selectate",
+ "PagerShowMenuEntries": "Arată _MENU_ intrări",
+ "DatatableActionDropdownDefaultText": "Acţiuni",
+ "ChangePassword": "Schimbă parola",
+ "PersonalInfo": "Profilul meu",
+ "AreYouSureYouWantToCancelEditingWarningMessage": "Aveţi modificări nesalvate.",
+ "GoHomePage": "Pagina principală",
+ "GoBack": "Înapoi",
+ "Search": "Caută",
+ "ItemWillBeDeletedMessageWithFormat": "{0} va fi şters!",
+ "ItemWillBeDeletedMessage": "Acest articol va fi şters!",
+ "ManageYourAccount": "Administraţi-vă contul"
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationObjectValidationContributor.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationObjectValidationContributor.cs
index 912f68e4af..15e367cefc 100644
--- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationObjectValidationContributor.cs
+++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationObjectValidationContributor.cs
@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
+using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
@@ -26,9 +27,10 @@ namespace Volo.Abp.Validation
Options = options.Value;
}
- public void AddErrors(ObjectValidationContext context)
+ public Task AddErrorsAsync(ObjectValidationContext context)
{
ValidateObjectRecursively(context.Errors, context.ValidatingObject, currentDepth: 1);
+ return Task.CompletedTask;
}
protected virtual void ValidateObjectRecursively(List errors, object validatingObject, int currentDepth)
diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IMethodInvocationValidator.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IMethodInvocationValidator.cs
index fd413bc498..89eec62116 100644
--- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IMethodInvocationValidator.cs
+++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IMethodInvocationValidator.cs
@@ -1,7 +1,9 @@
-namespace Volo.Abp.Validation
+using System.Threading.Tasks;
+
+namespace Volo.Abp.Validation
{
public interface IMethodInvocationValidator
{
- void Validate(MethodInvocationValidationContext context);
+ Task ValidateAsync(MethodInvocationValidationContext context);
}
}
diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidationContributor.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidationContributor.cs
index ca50901bcd..45d0ddcd9b 100644
--- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidationContributor.cs
+++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidationContributor.cs
@@ -1,7 +1,9 @@
-namespace Volo.Abp.Validation
+using System.Threading.Tasks;
+
+namespace Volo.Abp.Validation
{
public interface IObjectValidationContributor
{
- void AddErrors(ObjectValidationContext context);
+ Task AddErrorsAsync(ObjectValidationContext context);
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidator.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidator.cs
index 0ce723bab8..1b7c5881ee 100644
--- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidator.cs
+++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidator.cs
@@ -1,20 +1,21 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
+using System.Threading.Tasks;
namespace Volo.Abp.Validation
{
public interface IObjectValidator
{
- void Validate(
+ Task ValidateAsync(
object validatingObject,
string name = null,
bool allowNull = false
);
- List GetErrors(
+ Task> GetErrorsAsync(
object validatingObject,
string name = null,
bool allowNull = false
);
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/ro-RO.json b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/ro-RO.json
new file mode 100644
index 0000000000..ce03ecb52b
--- /dev/null
+++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/ro-RO.json
@@ -0,0 +1,34 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "'{0}' and '{1}' do not match.": "'{0}' şi '{1}' nu se potrivesc.",
+ "The {0} field is not a valid credit card number.": "Câmpul {0} nu este un număr valid de card de credit.",
+ "{0} is not valid.": "{0} nu este valid.",
+ "The {0} field is not a valid e-mail address.": "Câmpul {0} nu este o adresa de e-mail validă.",
+ "The {0} field only accepts files with the following extensions: {1}": "Câmpul {0} acceptă doar fişiere cu următoarele extensii: {1}",
+ "The field {0} must be a string or array type with a maximum length of '{1}'.": "Câmpul field {0} trebuie să fie de tipul string sau array cu lungimea maximă de '{1}'.",
+ "The field {0} must be a string or array type with a minimum length of '{1}'.": "Câmpul field {0} trebuie să fie de tipul string sau array cu lungimea minimă de '{1}'.",
+ "The {0} field is not a valid phone number.": "Câmpul {0} nu este un număr de telefon valid.",
+ "The field {0} must be between {1} and {2}.": "Câmpul {0} trebuie să fie între {1} şi {2}.",
+ "The field {0} must match the regular expression '{1}'.": "Câmpul {0} nu corespunde formatului solicitat.",
+ "The {0} field is required.": "Câmpul {0} este obligatoriu.",
+ "The field {0} must be a string with a maximum length of {1}.": "Câmpul {0} trebuie să fie un string cu lungimea maximă de {1}.",
+ "The field {0} must be a string with a minimum length of {2} and a maximum length of {1}.": "Câmpul {0} trebuie să fie un string cu lungimea minimă de {2} şi lungimea maximă de {1}.",
+ "The {0} field is not a valid fully-qualified http, https, or ftp URL.": "Câmpul {0} nu este o adresă validă complet http, https sau ftp.",
+ "The field {0} is invalid.": "Câmpul {0} este invalid.",
+ "ThisFieldIsNotAValidCreditCardNumber.": "Acest câmp nu este un număr de card de credit valid.",
+ "ThisFieldIsNotValid.": "Acest câmp nu este valid.",
+ "ThisFieldIsNotAValidEmailAddress.": "Acest câmp nu este o adresă de e-mail validă.",
+ "ThisFieldOnlyAcceptsFilesWithTheFollowingExtensions:{0}": "Acest câmp acceptă doar fişiere cu următoarele extensii: {0}",
+ "ThisFieldMustBeAStringOrArrayTypeWithAMaximumLengthOf{0}": "Acest câmp trebuie să fie de tipul string sau array cu lungimea maximă de '{0}'.",
+ "ThisFieldMustBeAStringOrArrayTypeWithAMinimumLengthOf{0}": "Acest câmp trebuie să fie de tipul string sau arraz cu lungimea minimă de '{0}'.",
+ "ThisFieldIsNotAValidPhoneNumber.": "Acest câmp nu este un număr de telefon valid.",
+ "ThisFieldMustBeBetween{0}And{1}": "Acest câmp trebuie să fie între {0} şi {1}.",
+ "ThisFieldMustMatchTheRegularExpression{0}": "Acest câmp trebuie să se potrivească cu expresia uzuală '{0}'.",
+ "ThisFieldIsRequired.": "Acest câmp este obligatoriu.",
+ "ThisFieldMustBeAStringWithAMaximumLengthOf{0}": "Acest câmp trebuie să fie un string cu lungimea maximă de {0}.",
+ "ThisFieldMustBeAStringWithAMinimumLengthOf{1}AndAMaximumLengthOf{0}": "Acest câmp trebuie să fie un string cu lungimea minimă de {1} şi lungimea maximă de {0}.",
+ "ThisFieldIsNotAValidFullyQualifiedHttpHttpsOrFtpUrl": "Acest câmp nu este o adresă validă http, https sau ftp.",
+ "ThisFieldIsInvalid.": "Acest câmp este invalid."
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/MethodInvocationValidator.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/MethodInvocationValidator.cs
index 584f787a6e..3aeaf57fc7 100644
--- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/MethodInvocationValidator.cs
+++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/MethodInvocationValidator.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
+using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Reflection;
@@ -16,7 +17,7 @@ namespace Volo.Abp.Validation
_objectValidator = objectValidator;
}
- public virtual void Validate(MethodInvocationValidationContext context)
+ public virtual async Task ValidateAsync(MethodInvocationValidationContext context)
{
Check.NotNull(context, nameof(context));
@@ -46,7 +47,7 @@ namespace Volo.Abp.Validation
ThrowValidationError(context);
}
- AddMethodParameterValidationErrors(context);
+ await AddMethodParameterValidationErrorsAsync(context);
if (context.Errors.Any())
{
@@ -60,7 +61,7 @@ namespace Volo.Abp.Validation
{
return false;
}
-
+
if (ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(context.Method) != null)
{
return true;
@@ -82,22 +83,22 @@ namespace Volo.Abp.Validation
);
}
- protected virtual void AddMethodParameterValidationErrors(MethodInvocationValidationContext context)
+ protected virtual async Task AddMethodParameterValidationErrorsAsync(MethodInvocationValidationContext context)
{
for (var i = 0; i < context.Parameters.Length; i++)
{
- AddMethodParameterValidationErrors(context, context.Parameters[i], context.ParameterValues[i]);
+ await AddMethodParameterValidationErrorsAsync(context, context.Parameters[i], context.ParameterValues[i]);
}
}
- protected virtual void AddMethodParameterValidationErrors(IAbpValidationResult context, ParameterInfo parameterInfo, object parameterValue)
+ protected virtual async Task AddMethodParameterValidationErrorsAsync(IAbpValidationResult context, ParameterInfo parameterInfo, object parameterValue)
{
var allowNulls = parameterInfo.IsOptional ||
parameterInfo.IsOut ||
TypeHelper.IsPrimitiveExtended(parameterInfo.ParameterType, includeEnums: true);
context.Errors.AddRange(
- _objectValidator.GetErrors(
+ await _objectValidator.GetErrorsAsync(
parameterValue,
parameterInfo.Name,
allowNulls
@@ -105,4 +106,4 @@ namespace Volo.Abp.Validation
);
}
}
-}
\ No newline at end of file
+}
diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidator.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidator.cs
index d8e0c60b65..8e13d72938 100644
--- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidator.cs
+++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidator.cs
@@ -2,6 +2,7 @@ using Microsoft.Extensions.Options;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
+using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection;
@@ -18,9 +19,9 @@ namespace Volo.Abp.Validation
Options = options.Value;
}
- public virtual void Validate(object validatingObject, string name = null, bool allowNull = false)
+ public virtual async Task ValidateAsync(object validatingObject, string name = null, bool allowNull = false)
{
- var errors = GetErrors(validatingObject, name, allowNull);
+ var errors = await GetErrorsAsync(validatingObject, name, allowNull);
if (errors.Any())
{
@@ -31,7 +32,7 @@ namespace Volo.Abp.Validation
}
}
- public virtual List GetErrors(object validatingObject, string name = null, bool allowNull = false)
+ public virtual async Task> GetErrorsAsync(object validatingObject, string name = null, bool allowNull = false)
{
if (validatingObject == null)
{
@@ -58,7 +59,7 @@ namespace Volo.Abp.Validation
{
var contributor = (IObjectValidationContributor)
scope.ServiceProvider.GetRequiredService(contributorType);
- contributor.AddErrors(context);
+ await contributor.AddErrorsAsync(context);
}
}
diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationInterceptor.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationInterceptor.cs
index b4ce642471..0a0f4fcf5f 100644
--- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationInterceptor.cs
+++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationInterceptor.cs
@@ -15,13 +15,13 @@ namespace Volo.Abp.Validation
public override async Task InterceptAsync(IAbpMethodInvocation invocation)
{
- Validate(invocation);
+ await ValidateAsync(invocation);
await invocation.ProceedAsync();
}
- protected virtual void Validate(IAbpMethodInvocation invocation)
+ protected virtual async Task ValidateAsync(IAbpMethodInvocation invocation)
{
- _methodInvocationValidator.Validate(
+ await _methodInvocationValidator.ValidateAsync(
new MethodInvocationValidationContext(
invocation.TargetObject,
invocation.Method,
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs
index 0fe6fb7cd9..3c186e3fea 100644
--- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcTestModule.cs
@@ -88,6 +88,7 @@ namespace Volo.Abp.AspNetCore.Mvc
options.Languages.Add(new LanguageInfo("en", "en", "English"));
options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar"));
+ options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română"));
options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak"));
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
});
diff --git a/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/EventBus_Exception_Handler_Tests.cs b/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/EventBus_Exception_Handler_Tests.cs
index d6b61ee863..3ed0ff19f9 100644
--- a/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/EventBus_Exception_Handler_Tests.cs
+++ b/framework/test/Volo.Abp.EventBus.Tests/Volo/Abp/EventBus/Local/EventBus_Exception_Handler_Tests.cs
@@ -33,9 +33,7 @@ namespace Volo.Abp.EventBus.Local
LocalEventBus.Subscribe(eventData =>
{
eventData.Value.ShouldBe(0);
-
retryAttempt++;
- eventData.Value++;
if (retryAttempt < 2)
{
throw new Exception("This exception is intentionally thrown!");
@@ -58,7 +56,6 @@ namespace Volo.Abp.EventBus.Local
eventData.Value.ShouldBe(0);
retryAttempt++;
- eventData.Value++;
throw new Exception("This exception is intentionally thrown!");
});
diff --git a/framework/test/Volo.Abp.FluentValidation.Tests/Volo/Abp/FluentValidation/ApplicationService_FluentValidation_Tests.cs b/framework/test/Volo.Abp.FluentValidation.Tests/Volo/Abp/FluentValidation/ApplicationService_FluentValidation_Tests.cs
index a93eabda1d..6263d03ddd 100644
--- a/framework/test/Volo.Abp.FluentValidation.Tests/Volo/Abp/FluentValidation/ApplicationService_FluentValidation_Tests.cs
+++ b/framework/test/Volo.Abp.FluentValidation.Tests/Volo/Abp/FluentValidation/ApplicationService_FluentValidation_Tests.cs
@@ -39,7 +39,8 @@ namespace Volo.Abp.FluentValidation
},
MyMethodInput3 = new MyMethodInput3
{
- MyStringValue3 = "ccc"
+ MyStringValue3 = "ccc",
+ MyBoolValue3 = true
}
});
@@ -62,12 +63,13 @@ namespace Volo.Abp.FluentValidation
},
MyMethodInput3 = new MyMethodInput3
{
- MyStringValue3 = "c"
+ MyStringValue3 = "c",
+ MyBoolValue3 = false
}
}
)
);
-
+
exception.ValidationErrors.ShouldContain(x => x.MemberNames.Contains("MyStringValue"));
exception.ValidationErrors.ShouldContain(x => x.MemberNames.Contains("MyMethodInput2.MyStringValue2"));
exception.ValidationErrors.ShouldContain(x => x.MemberNames.Contains("MyMethodInput3.MyStringValue3"));
@@ -100,7 +102,7 @@ namespace Volo.Abp.FluentValidation
output.ShouldBe("444");
}
-
+
[DependsOn(typeof(AbpAutofacModule))]
[DependsOn(typeof(AbpFluentValidationModule))]
public class TestModule : AbpModule
@@ -162,6 +164,8 @@ namespace Volo.Abp.FluentValidation
{
public string MyStringValue3 { get; set; }
+
+ public bool MyBoolValue3 { get; set; }
}
public class MyMethodInput4
@@ -175,7 +179,8 @@ namespace Volo.Abp.FluentValidation
{
RuleFor(x => x.MyStringValue).Equal("aaa");
RuleFor(x => x.MyMethodInput2.MyStringValue2).Equal("bbb");
- RuleFor(customer => customer.MyMethodInput3).SetValidator(new MyMethodInput3Validator());
+ RuleFor(x => x.MyMethodInput3).SetValidator(new MyMethodInput3Validator());
+ RuleFor(x => x.MyMethodInput3).SetValidator(new MyMethodInput3AsyncValidator());
}
}
@@ -194,5 +199,15 @@ namespace Volo.Abp.FluentValidation
RuleFor(x => x.MyStringValue3).Equal("ccc");
}
}
+
+ public class MyMethodInput3AsyncValidator : MethodInputBaseValidator
+ {
+ public MyMethodInput3AsyncValidator()
+ {
+ RuleFor(x => x.MyStringValue3).Equal("ccc");
+
+ RuleFor(x => x.MyBoolValue3).MustAsync((myBookValue3, cancellation) => Task.FromResult(myBookValue3));
+ }
+ }
}
-}
\ No newline at end of file
+}
diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/IRegularTestController.cs b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/IRegularTestController.cs
index 23694e4e72..d1c1275db7 100644
--- a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/IRegularTestController.cs
+++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/IRegularTestController.cs
@@ -1,4 +1,5 @@
using System;
+using System.Threading;
using System.Threading.Tasks;
namespace Volo.Abp.Http.DynamicProxying
@@ -36,5 +37,7 @@ namespace Volo.Abp.Http.DynamicProxying
Task PatchValueWithHeaderAndQueryStringAsync(string headerValue, string qsValue);
Task DeleteByIdAsync(int id);
+
+ Task AbortRequestAsync(CancellationToken cancellationToken = default);
}
}
diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestController.cs b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestController.cs
index e18c2f8f4a..782b839626 100644
--- a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestController.cs
+++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestController.cs
@@ -1,11 +1,10 @@
using System;
using System.Collections.Generic;
using System.Globalization;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
-using Volo.Abp.Application.Services;
using Volo.Abp.AspNetCore.Mvc;
-using Volo.Abp.UI;
namespace Volo.Abp.Http.DynamicProxying
{
@@ -129,6 +128,14 @@ namespace Volo.Abp.Http.DynamicProxying
{
return Task.FromResult(id + 1);
}
+
+ [HttpGet]
+ [Route("abort-request")]
+ public async Task AbortRequestAsync(CancellationToken cancellationToken = default)
+ {
+ await Task.Delay(100, cancellationToken);
+ return "AbortRequestAsync";
+ }
}
public class Car
diff --git a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs
index bd35016989..8df3e94b3c 100644
--- a/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs
+++ b/framework/test/Volo.Abp.Http.Client.Tests/Volo/Abp/Http/DynamicProxying/RegularTestControllerClientProxy_Tests.cs
@@ -1,10 +1,10 @@
using System;
+using System.Net.Http;
+using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Localization;
using Shouldly;
using Volo.Abp.Http.Client;
-using Volo.Abp.Http.Localization;
using Volo.Abp.Localization;
using Xunit;
@@ -159,5 +159,17 @@ namespace Volo.Abp.Http.DynamicProxying
(await _controller.DeleteByIdAsync(42)).ShouldBe(43);
}
+ [Fact]
+ public async Task AbortRequestAsync()
+ {
+ var cts = new CancellationTokenSource();
+ cts.CancelAfter(10);
+
+ var result = await _controller.AbortRequestAsync(default);
+ result.ShouldBe("AbortRequestAsync");
+
+ var exception = await Assert.ThrowsAsync(async () => await _controller.AbortRequestAsync(cts.Token));
+ exception.InnerException.InnerException.Message.ShouldBe("The client aborted the request.");
+ }
}
}
diff --git a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpHasExtraPropertiesJsonConverter_Tests.cs b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpHasExtraPropertiesJsonConverter_Tests.cs
new file mode 100644
index 0000000000..c11e8f3cec
--- /dev/null
+++ b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpHasExtraPropertiesJsonConverter_Tests.cs
@@ -0,0 +1,76 @@
+using System.Collections.Generic;
+using System.Linq;
+using Shouldly;
+using Volo.Abp.Data;
+using Volo.Abp.ObjectExtending;
+using Xunit;
+
+namespace Volo.Abp.Json
+{
+ public class AbpHasExtraPropertiesJsonConverter_Tests: AbpJsonTestBase
+ {
+ private readonly IJsonSerializer _jsonSerializer;
+
+ public AbpHasExtraPropertiesJsonConverter_Tests()
+ {
+ _jsonSerializer = GetRequiredService();
+ }
+
+ [Fact]
+ public void JsonConverter_Test()
+ {
+ var fooDto = new FooDto
+ {
+ Name = "foo-dto",
+ BarDtos = new List()
+ };
+ fooDto.SetProperty("foo", "foo-value");
+
+ var barDto = new BarDto
+ {
+ Name = "bar-dto"
+ };
+ barDto.SetProperty("bar", "bar-value");
+ fooDto.BarDtos.Add(barDto);
+
+ var json = _jsonSerializer.Serialize(fooDto);
+
+ fooDto = _jsonSerializer.Deserialize(json);
+ fooDto.ShouldNotBeNull();
+ fooDto.Name.ShouldBe("foo-dto");
+ fooDto.GetProperty("foo").ShouldBe("foo-value");
+
+ fooDto.BarDtos.Count.ShouldBe(1);
+ fooDto.BarDtos.First().Name.ShouldBe("bar-dto");
+ fooDto.BarDtos.First().GetProperty("bar").ShouldBe("bar-value");
+
+ fooDto.Name = "new-foo-dto";
+ fooDto.SetProperty("foo", "new-foo-value");
+ fooDto.BarDtos.First().Name = "new-bar-dto";
+ fooDto.BarDtos.First().SetProperty("bar", "new-bar-value");
+
+ json = _jsonSerializer.Serialize(fooDto);
+
+ fooDto = _jsonSerializer.Deserialize(json);
+ fooDto.ShouldNotBeNull();
+ fooDto.Name.ShouldBe("new-foo-dto");
+ fooDto.GetProperty("foo").ShouldBe("new-foo-value");
+
+ fooDto.BarDtos.Count.ShouldBe(1);
+ fooDto.BarDtos.First().Name.ShouldBe("new-bar-dto");
+ fooDto.BarDtos.First().GetProperty("bar").ShouldBe("new-bar-value");
+ }
+ }
+
+ public class FooDto : ExtensibleObject
+ {
+ public string Name { get; set; }
+
+ public List BarDtos { get; set; }
+ }
+
+ public class BarDto : ExtensibleObject
+ {
+ public string Name { get; set; }
+ }
+}
diff --git a/framework/test/Volo.Abp.Threading.Tests/Volo.Abp.Threading.Tests.csproj b/framework/test/Volo.Abp.Threading.Tests/Volo.Abp.Threading.Tests.csproj
new file mode 100644
index 0000000000..cbca0b1329
--- /dev/null
+++ b/framework/test/Volo.Abp.Threading.Tests/Volo.Abp.Threading.Tests.csproj
@@ -0,0 +1,16 @@
+
+
+
+
+
+ net5.0
+
+
+
+
+
+
+
+
+
+
diff --git a/framework/test/Volo.Abp.Threading.Tests/Volo/Abp/Threading/AbpThreadingTestModule.cs b/framework/test/Volo.Abp.Threading.Tests/Volo/Abp/Threading/AbpThreadingTestModule.cs
new file mode 100644
index 0000000000..de530512d3
--- /dev/null
+++ b/framework/test/Volo.Abp.Threading.Tests/Volo/Abp/Threading/AbpThreadingTestModule.cs
@@ -0,0 +1,15 @@
+using Volo.Abp.Modularity;
+
+namespace Volo.Abp.Threading
+{
+ [DependsOn(
+ typeof(AbpThreadingModule),
+ typeof(AbpTestBaseModule)
+ )]
+ public class AbpThreadingTestModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ }
+ }
+}
diff --git a/framework/test/Volo.Abp.Threading.Tests/Volo/Abp/Threading/NullCancellationTokenProvider_Tests.cs b/framework/test/Volo.Abp.Threading.Tests/Volo/Abp/Threading/NullCancellationTokenProvider_Tests.cs
new file mode 100644
index 0000000000..34c5988eb1
--- /dev/null
+++ b/framework/test/Volo.Abp.Threading.Tests/Volo/Abp/Threading/NullCancellationTokenProvider_Tests.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Shouldly;
+using Volo.Abp.Testing;
+using Xunit;
+
+namespace Volo.Abp.Threading
+{
+ public class NullCancellationTokenProvider_Tests : AbpIntegratedTest
+ {
+ private readonly ICancellationTokenProvider _cancellationTokenProvider;
+
+ public NullCancellationTokenProvider_Tests()
+ {
+ _cancellationTokenProvider = NullCancellationTokenProvider.Instance;
+ }
+
+ [Fact]
+ public void Should_Return_None_Token()
+ {
+ _cancellationTokenProvider.Token.ShouldBe(CancellationToken.None);
+ }
+
+ [Fact]
+ public void Should_Return_Specific_Token()
+ {
+ var cts = new CancellationTokenSource();
+
+ using (_cancellationTokenProvider.Use(cts.Token))
+ {
+ var newCancellationTokenProvider = NullCancellationTokenProvider.Instance;
+
+ newCancellationTokenProvider.Token.ShouldBe(cts.Token);
+ }
+
+ _cancellationTokenProvider.Token.ShouldBe(CancellationToken.None);
+ }
+
+ [Fact]
+ public void Should_Cancel_After_100_Milliseconds()
+ {
+ var cts = new CancellationTokenSource();
+ cts.CancelAfter(TimeSpan.FromMilliseconds(100));
+
+ using (_cancellationTokenProvider.Use(cts.Token))
+ {
+ var newCancellationTokenProvider = NullCancellationTokenProvider.Instance;
+ Should.Throw(() => LongTask(1000, newCancellationTokenProvider.Token));
+ }
+ }
+
+ private void LongTask(int loopCounter, CancellationToken cancellationToken = default)
+ {
+ for (var i = 0; i < loopCounter; i++)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ Thread.Sleep(10);
+ }
+ }
+ }
+}
diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ro-RO.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ro-RO.json
new file mode 100644
index 0000000000..909d09f211
--- /dev/null
+++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/ro-RO.json
@@ -0,0 +1,67 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "UserName": "Nume de utilizator",
+ "EmailAddress": "Adresa de email",
+ "UserNameOrEmailAddress": "Nume de utilizator sau adresa de email",
+ "Password": "Parola",
+ "RememberMe": "Ţine-mă minte",
+ "UseAnotherServiceToLogin": "Folisiţi alt serviciu pentru a vă autentifica",
+ "UserLockedOutMessage": "Contul a fost blocat din cauza incercărilor eşuate de autentificare. Vă rugăm să aşteptaţi şi să încercaţi din nou.",
+ "InvalidUserNameOrPassword": "Nume de utilizator sau parolă invalide!",
+ "LoginIsNotAllowed": "Nu vă este permis să vă autentificaţi! Trebuie să vă confirmaţi email-ul/numărul de telefon.",
+ "SelfRegistrationDisabledMessage": "Înregistrarea personală este dezactivată pentru această aplicaţie. Vă rugăm să contactaţi administratorul aplicaţiei pentru a înregistra un nou utilizator.",
+ "LocalLoginDisabledMessage": "Autentificarea locală este dezactivată pentru această aplicaţie.",
+ "Login": "Autentificare",
+ "Cancel": "Anulează",
+ "Register": "Înregistrare",
+ "AreYouANewUser": "Sunteţi un utilizator nou?",
+ "AlreadyRegistered": "Deja înregistrat?",
+ "InvalidLoginRequest": "Cerere de autentificare invalidă",
+ "ThereAreNoLoginSchemesConfiguredForThisClient": "Nu există scheme de autentificare configurate pentru acest client.",
+ "LogInUsingYourProviderAccount": "Autentificaţi-vă folosindu-vă contul {0}",
+ "DisplayName:CurrentPassword": "Parola curentă",
+ "DisplayName:NewPassword": "Parola nouă",
+ "DisplayName:NewPasswordConfirm": "Confirmă noua parolă",
+ "PasswordChangedMessage": "Parola dumneavoastră a fost schimbată cu succes.",
+ "DisplayName:UserName": "Nume de utilizator",
+ "DisplayName:Email": "Email",
+ "DisplayName:Name": "Nume",
+ "DisplayName:Surname": "Surname",
+ "DisplayName:Password": "Parolă",
+ "DisplayName:EmailAddress": "Adresa de email",
+ "DisplayName:PhoneNumber": "Număr de telefon",
+ "PersonalSettings": "Setări personale",
+ "PersonalSettingsSaved": "Setări personale salvate",
+ "PasswordChanged": "Parola schimbată",
+ "NewPasswordConfirmFailed": "Vă rugăm să confirmaţi noua parolă.",
+ "Manage": "Administrează",
+ "MyAccount": "Contul meu",
+ "DisplayName:Abp.Account.IsSelfRegistrationEnabled": "Este înregistrarea personală activată",
+ "Description:Abp.Account.IsSelfRegistrationEnabled": "Dacă un utilizator îşi poate înregistra contul singur(ă).",
+ "DisplayName:Abp.Account.EnableLocalLogin": "Autentificaţi-vă cu un cont local",
+ "Description:Abp.Account.EnableLocalLogin": "Indică dacă serverul va permite utilizatorilor să se autentifice cu un cont local.",
+ "LoggedOutTitle": "Deconectat",
+ "LoggedOutText": "V-aţi deconectat şi veţi fi redirectat(ă) curând.",
+ "ReturnToText": "Click aici pentru a vă întoarce la aplicaţie",
+ "OrLoginWith": "Sau autentificaţi-vă cu:",
+ "ForgotPassword": "Aţi uitat parola?",
+ "SendPasswordResetLink_Information": "Un link pentru resetarea parolei va fi trimis pe emailul dumneavoastră. Dacă nu primiţi un email în decurs de câteva minute, vă rugăm să reîncercaţi.",
+ "PasswordResetMailSentMessage": "Emailul de recuperare al contului a fost trimis la adresa dumneavoastră de email. Dacă nu vedeţi acest email în decurs de 15 minute, cautaţi-l în dosarul de junk/spam. Dacă îl găsiţi acolo, vă rugăm să îl marcaţi ca -Not Junk-/-Not Spam-. ",
+ "ResetPassword": "Resetaţi parola",
+ "ConfirmPassword": "Confirmaţi (repetaţi) parola",
+ "ResetPassword_Information": "Vă rugăm să vă introduceţi noua parola.",
+ "YourPasswordIsSuccessfullyReset": "Parola a fost resetată cu succes.",
+ "GoToTheApplication": "Navigaţi la aplicaţie",
+ "BackToLogin": "Înapoi la autentificare",
+ "ProfileTab:Password": "Schimbă parola",
+ "ProfileTab:PersonalInfo": "Date personale",
+ "ReturnToApplication": "Întoarceţi-vă la aplicaţie",
+ "Volo.Account:InvalidEmailAddress": "Nu a putut fi găsită adresa de email: {0}",
+ "PasswordReset": "Resetarea parolei",
+ "PasswordResetInfoInEmail": "Am primit o cerere de recuperare a contului! Dacă dumneavoastră aţi iniţiat această cerere, daţi click pe următorul link pentru a vă reseta parola.",
+ "ResetMyPassword": "Resetează-mi parola",
+ "AccessDenied": "Acces interzis!",
+ "AccessDeniedMessage": "Nu aveţi acces la această resursă."
+ }
+}
diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/IAuditLogRepository.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/IAuditLogRepository.cs
index 31666504d4..7f24616280 100644
--- a/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/IAuditLogRepository.cs
+++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.Domain/Volo/Abp/AuditLogging/IAuditLogRepository.cs
@@ -21,6 +21,7 @@ namespace Volo.Abp.AuditLogging
Guid? userId = null,
string userName = null,
string applicationName = null,
+ string clientIpAddress = null,
string correlationId = null,
int? maxExecutionDuration = null,
int? minExecutionDuration = null,
@@ -37,6 +38,7 @@ namespace Volo.Abp.AuditLogging
Guid? userId = null,
string userName = null,
string applicationName = null,
+ string clientIpAddress = null,
string correlationId = null,
int? maxExecutionDuration = null,
int? minExecutionDuration = null,
diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs
index 6b2a440f1f..361ae25f91 100644
--- a/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs
+++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.EntityFrameworkCore/Volo/Abp/AuditLogging/EntityFrameworkCore/EfCoreAuditLogRepository.cs
@@ -32,6 +32,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
Guid? userId = null,
string userName = null,
string applicationName = null,
+ string clientIpAddress = null,
string correlationId = null,
int? maxExecutionDuration = null,
int? minExecutionDuration = null,
@@ -48,6 +49,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
userId,
userName,
applicationName,
+ clientIpAddress,
correlationId,
maxExecutionDuration,
minExecutionDuration,
@@ -72,6 +74,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
Guid? userId = null,
string userName = null,
string applicationName = null,
+ string clientIpAddress = null,
string correlationId = null,
int? maxExecutionDuration = null,
int? minExecutionDuration = null,
@@ -87,6 +90,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
userId,
userName,
applicationName,
+ clientIpAddress,
correlationId,
maxExecutionDuration,
minExecutionDuration,
@@ -107,6 +111,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
Guid? userId = null,
string userName = null,
string applicationName = null,
+ string clientIpAddress = null,
string correlationId = null,
int? maxExecutionDuration = null,
int? minExecutionDuration = null,
@@ -126,6 +131,7 @@ namespace Volo.Abp.AuditLogging.EntityFrameworkCore
.WhereIf(userId != null, auditLog => auditLog.UserId == userId)
.WhereIf(userName != null, auditLog => auditLog.UserName == userName)
.WhereIf(applicationName != null, auditLog => auditLog.ApplicationName == applicationName)
+ .WhereIf(clientIpAddress != null, auditLog => auditLog.ClientIpAddress != null && auditLog.ClientIpAddress == clientIpAddress)
.WhereIf(correlationId != null, auditLog => auditLog.CorrelationId == correlationId)
.WhereIf(httpStatusCode != null && httpStatusCode > 0, auditLog => auditLog.HttpStatusCode == nHttpStatusCode)
.WhereIf(maxExecutionDuration != null && maxExecutionDuration.Value > 0, auditLog => auditLog.ExecutionDuration <= maxExecutionDuration)
diff --git a/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs b/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs
index e67f78a2a8..06bf102fed 100644
--- a/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs
+++ b/modules/audit-logging/src/Volo.Abp.AuditLogging.MongoDB/Volo/Abp/AuditLogging/MongoDB/MongoAuditLogRepository.cs
@@ -33,6 +33,7 @@ namespace Volo.Abp.AuditLogging.MongoDB
Guid? userId = null,
string userName = null,
string applicationName = null,
+ string clientIpAddress = null,
string correlationId = null,
int? maxDuration = null,
int? minDuration = null,
@@ -49,6 +50,7 @@ namespace Volo.Abp.AuditLogging.MongoDB
userId,
userName,
applicationName,
+ clientIpAddress,
correlationId,
maxDuration,
minDuration,
@@ -73,6 +75,7 @@ namespace Volo.Abp.AuditLogging.MongoDB
Guid? userId = null,
string userName = null,
string applicationName = null,
+ string clientIpAddress = null,
string correlationId = null,
int? maxDuration = null,
int? minDuration = null,
@@ -88,6 +91,7 @@ namespace Volo.Abp.AuditLogging.MongoDB
userId,
userName,
applicationName,
+ clientIpAddress,
correlationId,
maxDuration,
minDuration,
@@ -110,6 +114,7 @@ namespace Volo.Abp.AuditLogging.MongoDB
Guid? userId = null,
string userName = null,
string applicationName = null,
+ string clientIpAddress = null,
string correlationId = null,
int? maxDuration = null,
int? minDuration = null,
@@ -128,6 +133,7 @@ namespace Volo.Abp.AuditLogging.MongoDB
.WhereIf(userId != null, auditLog => auditLog.UserId == userId)
.WhereIf(userName != null, auditLog => auditLog.UserName == userName)
.WhereIf(applicationName != null, auditLog => auditLog.ApplicationName == applicationName)
+ .WhereIf(clientIpAddress != null, auditLog => auditLog.ClientIpAddress == clientIpAddress)
.WhereIf(correlationId != null, auditLog => auditLog.CorrelationId == correlationId)
.WhereIf(httpStatusCode != null && httpStatusCode > 0, auditLog => auditLog.HttpStatusCode == (int?)httpStatusCode)
.WhereIf(maxDuration != null && maxDuration > 0, auditLog => auditLog.ExecutionDuration <= maxDuration)
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj
index 0ad808cdb2..24205102c8 100644
--- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj
+++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests.csproj
@@ -17,11 +17,19 @@
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo/Abp/AspNetCore/Mvc/UI/Bootstrap/Demo/AbpAspNetCoreMvcUiBootstrapDemoTestBase.cs b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo/Abp/AspNetCore/Mvc/UI/Bootstrap/Demo/AbpAspNetCoreMvcUiBootstrapDemoTestBase.cs
index d7a8a88c2a..ec07aeab4a 100644
--- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo/Abp/AspNetCore/Mvc/UI/Bootstrap/Demo/AbpAspNetCoreMvcUiBootstrapDemoTestBase.cs
+++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Tests/Volo/Abp/AspNetCore/Mvc/UI/Bootstrap/Demo/AbpAspNetCoreMvcUiBootstrapDemoTestBase.cs
@@ -1,12 +1,17 @@
using System;
+using System.Globalization;
using System.IO;
using System.Linq;
-using Microsoft.AspNetCore.Hosting;
+using System.Net;
+using System.Net.Http;
+using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
+using Shouldly;
+using Volo.Abp.AspNetCore.TestBase;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo
{
- public abstract class AbpAspNetCoreMvcUiBootstrapDemoTestBase : AbpAspNetCoreTestBase
+ public abstract class AbpAspNetCoreMvcUiBootstrapDemoTestBase : AbpAspNetCoreIntegratedTestBase
{
protected override IHostBuilder CreateHostBuilder()
{
@@ -46,5 +51,25 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo
.GetFiles(currentDirectory, "*.*", SearchOption.TopDirectoryOnly)
.Any(f => Path.GetFileName(f) == projectFileName);
}
+
+
+ protected virtual async Task GetResponseAsStringAsync(string url, HttpStatusCode expectedStatusCode = HttpStatusCode.OK)
+ {
+ using (var response = await GetResponseAsync(url, expectedStatusCode))
+ {
+ return await response.Content.ReadAsStringAsync();
+ }
+ }
+
+ protected virtual async Task GetResponseAsync(string url, HttpStatusCode expectedStatusCode = HttpStatusCode.OK)
+ {
+ using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, url))
+ {
+ requestMessage.Headers.Add("Accept-Language", CultureInfo.CurrentUICulture.Name);
+ var response = await Client.SendAsync(requestMessage);
+ response.StatusCode.ShouldBe(expectedStatusCode);
+ return response;
+ }
+ }
}
-}
\ No newline at end of file
+}
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj
index 0574bb89c8..372ad8ba75 100644
--- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj
+++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.csproj
@@ -8,7 +8,7 @@
-
+
diff --git a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo.csproj b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo.csproj
index 08c2996075..52024363e0 100644
--- a/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo.csproj
+++ b/modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo/Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic.Demo.csproj
@@ -16,7 +16,7 @@
-
+
diff --git a/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/ro-RO.json b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/ro-RO.json
new file mode 100644
index 0000000000..a1359445cc
--- /dev/null
+++ b/modules/blob-storing-database/src/Volo.Abp.BlobStoring.Database.Domain.Shared/Volo/Abp/BlobStoring/Database/Localization/ro-RO.json
@@ -0,0 +1,6 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "MyAccount": "Contul meu"
+ }
+}
\ No newline at end of file
diff --git a/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/ro-RO.json b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/ro-RO.json
new file mode 100644
index 0000000000..755b2b7ceb
--- /dev/null
+++ b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/ro-RO.json
@@ -0,0 +1,61 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "Menu:Blogs": "Bloguri",
+ "Menu:BlogManagement": "Blogging",
+ "Permission:Management": "Administraţie",
+ "Permission:Edit": "Editare",
+ "Permission:Create": "Creare",
+ "Permission:Delete": "Şterere",
+ "Permission:Blogging": "Blog",
+ "Permission:Blogs": "Bloguri",
+ "Permission:Posts": "Postări",
+ "Permission:Tags": "Etichete",
+ "Permission:Comments": "Comentarii",
+ "Permission:ClearCache": "Goleşte cache",
+ "Title": "Titlu",
+ "Delete": "Şterge",
+ "Reply": "Răspunde",
+ "ReplyTo": "Răspunde la {0}",
+ "ContinueReading": "Continuă citirea",
+ "DaysAgo": "{0} zile în urmă",
+ "YearsAgo": "{0} ani în urmă",
+ "MonthsAgo": "{0} luni în urmă",
+ "WeeksAgo": "{0} săptămâni în urmă",
+ "MinutesAgo": "{0} minute în urmă",
+ "SecondsAgo": "{0} secunde în urmă",
+ "HoursAgo": "{0} ore în urmă",
+ "Now": "acum",
+ "Content": "Conţinut",
+ "SeeAll": "Vezi toate",
+ "PopularTags": "Etichete populare",
+ "WiewsWithCount": "{0} vizualizări",
+ "LastPosts": "Ultimele postări",
+ "LeaveComment": "Lasă un comentariu",
+ "TagsInThisArticle": "Etichete în acest articol",
+ "Posts": "Postări",
+ "Edit": "Editează",
+ "BLOG": "BLOG",
+ "CommentDeletionWarningMessage": "Comentariul va fi şters.",
+ "PostDeletionWarningMessage": "Postarea va fi ştearsă.",
+ "BlogDeletionWarningMessage": "Blogul va fi şters.",
+ "AreYouSure": "Sunteţi sigur(ă)?",
+ "CommentWithCount": "{0} comentarii",
+ "Comment": "Comentează",
+ "ShareOnTwitter": "Distribuie pe Twitter",
+ "CoverImage": "Imagine de copertă",
+ "CreateANewPost": "Creaţi o nouă postare",
+ "CreateANewBlog": "Creaţi un nou blog",
+ "WhatIsNew": "Ce este nou?",
+ "Name": "Nume",
+ "ShortName": "Nume pe scurt",
+ "CreationTime": "Data creării",
+ "Description": "Descriere",
+ "Blogs": "Bloguri",
+ "Tags": "Etichete",
+ "ShareOn": "Distribuie",
+ "TitleLengthWarning": "Păstraţi lungimea titlului sub 60 de caractere pentru a fi SEO friendly!",
+ "ClearCache": "Goleşte cache",
+ "ClearCacheConfirmationMessage": "Sunteţi sigur(ă) că vreţi să goliţi cache-ul?"
+ }
+}
\ No newline at end of file
diff --git a/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/CmsKitHttpApiHostModule.cs b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/CmsKitHttpApiHostModule.cs
index 31026fdc8f..b9c27df3c9 100644
--- a/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/CmsKitHttpApiHostModule.cs
+++ b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/CmsKitHttpApiHostModule.cs
@@ -104,6 +104,7 @@ namespace Volo.CmsKit
options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi", "in"));
options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it"));
options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
+ options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română"));
options.Languages.Add(new LanguageInfo("ru", "ru", "Русский"));
options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak"));
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
diff --git a/modules/cms-kit/host/Volo.CmsKit.IdentityServer/CmsKitIdentityServerModule.cs b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/CmsKitIdentityServerModule.cs
index bd3bb70cd4..89a0d57921 100644
--- a/modules/cms-kit/host/Volo.CmsKit.IdentityServer/CmsKitIdentityServerModule.cs
+++ b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/CmsKitIdentityServerModule.cs
@@ -110,6 +110,7 @@ namespace Volo.CmsKit
options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi", "in"));
options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it"));
options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
+ options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română"));
options.Languages.Add(new LanguageInfo("ru", "ru", "Русский"));
options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak"));
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs
index ba573a6eb5..40ac74d788 100644
--- a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs
+++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs
@@ -131,6 +131,7 @@ namespace Volo.CmsKit
options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi", "in"));
options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it"));
options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português (Brasil)"));
+ options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română"));
options.Languages.Add(new LanguageInfo("ru", "ru", "Русский"));
options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak"));
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
diff --git a/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ro-RO.json b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ro-RO.json
new file mode 100644
index 0000000000..3e7e1caaa9
--- /dev/null
+++ b/modules/cms-kit/src/Volo.CmsKit.Domain.Shared/Volo/CmsKit/Localization/Resources/ro-RO.json
@@ -0,0 +1,163 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "AddSubMenuItem": "Adaugă submeniu",
+ "AreYouSure": "Sunteţi sigur(ă)?",
+ "BlogDeletionConfirmationMessage": "Blogul '{0}' va fi şters. Sunteţi sigur(ă)?",
+ "BlogFeatureNotAvailable": "Această caracteristică nu este disponibilă acum. Activaţi-o cu 'GlobalFeatureManager' pentru a o folosi.",
+ "BlogId": "Blog",
+ "BlogPostDeletionConfirmationMessage": "Postul '{0}' va fi şters. Sunteţi sigur(ă)?",
+ "BlogPosts": "Postări de Blog",
+ "Blogs": "Bloguri",
+ "ChoosePreference": "Alegeţi preferinţele...",
+ "Cms": "CMS",
+ "CmsKit.Comments": "Comentarii",
+ "CmsKit.Ratings": "Evaluări",
+ "CmsKit.Reactions": "Reacţii",
+ "CmsKit.Tags": "Etichete",
+ "CmsKit:0002": "Conţinutul există deja!",
+ "CmsKit:0003": "Entitatea {0} nu este etichetabilă.",
+ "CmsKit:Blog:0001": "Slugul ({Slug}) există deja!",
+ "CmsKit:BlogPost:0001": "Slugul dat există deja!",
+ "CmsKit:Comments:0001": "Nu se poate comenta la entitatea {EntityType}.",
+ "CmsKit:Media:0001": "'{Name}' nu este un nume valid de media.",
+ "CmsKit:Media:0002": "Entitatea nu poate avea media.",
+ "CmsKit:Page:0001": "Url-ul dat ({Slug}) există deja. Vă rugăm să reîncercaţi cu un alt url.",
+ "CmsKit:Rating:0001": "Entititatea {EntityType} nu poate fi evaluată.",
+ "CmsKit:Reaction:0001": "Entitatea {EntityType} nu poate avea reacţii.",
+ "CmsKit:Tag:0002": "Entitatea nu este etichetabilă!",
+ "CommentAuthorizationExceptionMessage": "Aceste comentarii nu sunt permise pentru afişarea publică.",
+ "CommentDeletionConfirmationMessage": "Acest comentariu şi toate replicile vor fi şterse!",
+ "Comments": "Comentarii",
+ "Content": "Conţinut",
+ "ContentDeletionConfirmationMessage": "Sunteţi sigur(ă) că vreţi să ştergeţi conţinutul?",
+ "Contents": "Cuprins",
+ "CoverImage": "Imagine de copertă",
+ "CreateBlogPostPage": "Postare nouă pe blog",
+ "CreationTime": "Data creării",
+ "Delete": "Şterge",
+ "Detail": "Detaliu",
+ "Details": "Detalii",
+ "DisplayName": "Numele afişat",
+ "DoYouPreferAdditionalEmails": "Preferaţi emailuri adiţionale?",
+ "Edit": "Editează",
+ "EndDate": "Data de sfărşit",
+ "EntityId": "Id-ul entităţii",
+ "EntityType": "Tipul entităţii",
+ "ExportCSV": "Export CSV",
+ "Features": "Caracteristici",
+ "GenericDeletionConfirmationMessage": "Sigur ştergeţi '{0}'?",
+ "IsActive" : "Activ",
+ "LastModification": "Ultima modificare",
+ "LastModificationTime": "Data ultimei modificări",
+ "LoginToAddComment": "Autentificaţi-vă pentru a comenta",
+ "LoginToRate": "Autentificaţi-vă pentru a evalua",
+ "LoginToReact": "Autentificaţi-vă pentru a reacţiona",
+ "LoginToReply": "Autentificaţi-vă pentru a răspunde",
+ "MainMenu": "Meniu principal",
+ "MakeMainMenu": "Faceţi meniu principal",
+ "Menu:CMS": "CMS",
+ "Menus": "Meniuri",
+ "MenuDeletionConfirmationMessage": "Meniul '{0}' va fi şters. Sunteţi sigur(ă)?",
+ "MenuItemDeletionConfirmationMessage": "Sunteţi sigur(ă) că vreţi să ştergeţi acest element de meniu?",
+ "MenuItemMoveConfirmMessage": "Sunteţi sigur că vreţi să mutaţi '{0}' sub '{1}'?",
+ "MenuItems": "Elementele meniului",
+ "Message": "Mesaj",
+ "MessageDeletionConfirmationMessage": "Acest comentariu va fi şters.",
+ "NewBlog": "Blog nou",
+ "NewBlogPost": "Postare nouă pe blog",
+ "NewMenu": "Meniu nou",
+ "NewMenuItem": "Nod nou de meniu",
+ "NewPage": "Pagină nouă",
+ "NewTag": "Etichetă nouă",
+ "NoMenuItems": "Nu există încă niciun element de meniu!",
+ "OK": "OK",
+ "PageDeletionConfirmationMessage": "Sunteţi sigur(ă) că vreţi să ştergeţi această pagină?",
+ "PageId": "Pagina",
+ "Pages": "Pagini",
+ "PageSlugInformation": "Slug este folosit pe url. Url-ul dumneavoastră va fi '/pages/{{slug}}'.",
+ "Permission:BlogManagement": "Administrare Blog",
+ "Permission:BlogManagement.Create": "Creează",
+ "Permission:BlogManagement.Delete": "Şterge",
+ "Permission:BlogManagement.Features": "Caracteristici",
+ "Permission:BlogManagement.Update": "Actualizează",
+ "Permission:BlogPostManagement": "Administrarea postărilor de blog",
+ "Permission:BlogPostManagement.Create": "Creează",
+ "Permission:BlogPostManagement.Delete": "Şterge",
+ "Permission:BlogPostManagement.Update": "Actualizează",
+ "Permission:CmsKit": "CmsKit",
+ "Permission:Comments": "Administrarea comentariilor",
+ "Permission:Comments.Delete": "Şterge",
+ "Permission:Contents": "Administrarea conţinutului",
+ "Permission:Contents.Create": "Creează conţinut",
+ "Permission:Contents.Delete": "Şterge conţinut",
+ "Permission:Contents.Update": "Actualizează conţinut",
+ "Permission:MediaDescriptorManagement": "Administrarea media",
+ "Permission:MediaDescriptorManagement:Create": "Creează",
+ "Permission:MediaDescriptorManagement:Delete": "Şterge",
+ "Permission:MenuItemManagement": "Administrarea elementelor de meniu",
+ "Permission:MenuItemManagement.Create": "Creează",
+ "Permission:MenuItemManagement.Delete": "Şterge",
+ "Permission:MenuItemManagement.Update": "Actualizează",
+ "Permission:MenuManagement": "Administrează meniu",
+ "Permission:MenuManagement.Create": "Creează",
+ "Permission:MenuManagement.Delete": "Şterge",
+ "Permission:MenuManagement.Update": "Actualizează",
+ "Permission:Menus": "Administrarea meniului",
+ "Permission:Menus.Create": "Creează",
+ "Permission:Menus.Delete": "Şterge",
+ "Permission:Menus.Update": "Actualizează",
+ "Permission:PageManagement": "Administrarea paginilor",
+ "Permission:PageManagement:Create": "Creează",
+ "Permission:PageManagement:Delete": "Şterge",
+ "Permission:PageManagement:Update": "Actualizează",
+ "Permission:TagManagement": "Administrarea etichetelor",
+ "Permission:TagManagement.Create": "Creează",
+ "Permission:TagManagement.Delete": "Şterge",
+ "Permission:TagManagement.Update": "Actualizează",
+ "PickYourReaction": "Alegeţi-vă reacţia",
+ "Rating": "Evaluare",
+ "RatingUndoMessage": "Evaluarea dumneavoastră va fi anulată.",
+ "Reactions": "Reacţii",
+ "Read": "Citeşte",
+ "RepliesToThisComment": "Replici la acest comentariu",
+ "Reply": "Răspunde",
+ "ReplyTo": "Răspunde la",
+ "SamplePageMessage": "Un exemplu de pagină pentru modulul Pro",
+ "SaveChanges": "Salvaţi modificările",
+ "Script": "Script",
+ "SelectAll": "Selectaţi toate",
+ "Send": "Trimite",
+ "SendMessage": "Trimite mesaj",
+ "ShortDescription": "Descriere pe scurt",
+ "Slug": "Slug",
+ "Source": "Sursa",
+ "SourceUrl": "Sursa Url",
+ "Star": "Stea",
+ "StartDate": "Data de început",
+ "Style": "Stil",
+ "Subject": "Subiect",
+ "SubjectPlaceholder": "Vă rugăm să scrieţi un subiect",
+ "Submit": "Trimiteţi",
+ "Subscribe": "Abonaţi-vă",
+ "SuccessfullySaved": "Salvat cu succes!",
+ "TagDeletionConfirmationMessage": "Sunteţi sigur(ă) că vreţi să ştergeţi eticheta '{0}'?",
+ "Tags": "Etichete",
+ "Text": "Text",
+ "ThankYou": "Vă mulţumim",
+ "Title": "Titlu",
+ "Undo": "Anulează",
+ "Update": "Actualizează",
+ "UpdatePreferenceSuccessMessage": "Preferinţele dumneavoastră au fost salvate.",
+ "UpdateYourEmailPreferences": "Actualizaţi-vă preferinţele de email",
+ "UnMakeMainMenu": "Anulaţi meniul principal",
+ "UploadFailedMessage": "Încărcarea a eşuat.",
+ "UserId": "Id utilizator",
+ "Username": "Nume utilizator",
+ "YourComment": "Comentariul dumneavoastră",
+ "YourEmailAddress": "Adresa dumneavoastră de e-mail",
+ "YourFullName": "Numele dumneavoastră complet",
+ "YourMessage": "Mesajul dumneavoastră",
+ "YourReply": "Replica dumneavoastră"
+ }
+}
diff --git a/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/ro-RO.json b/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/ro-RO.json
new file mode 100644
index 0000000000..41e756e55b
--- /dev/null
+++ b/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/ro-RO.json
@@ -0,0 +1,10 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "DocsTitle": "VoloDocs",
+ "WelcomeVoloDocs": "Bun venit pe VoloDocs!",
+ "NoProjectWarning": "Nu există niciun proiect definit încă!",
+ "CreateYourFirstProject": "Click aici pentru a începe primul dumneavoastră proiect",
+ "NoProject": "Niciun proiect!"
+ }
+}
\ No newline at end of file
diff --git a/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs b/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs
index 32779b6acf..8f9cdc7e0d 100644
--- a/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs
+++ b/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs
@@ -129,6 +129,7 @@ namespace VoloDocs.Web
options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi", "in"));
options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it"));
options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar"));
+ options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română"));
options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak"));
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/ro-RO.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/ro-RO.json
new file mode 100644
index 0000000000..03c583227c
--- /dev/null
+++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/ro-RO.json
@@ -0,0 +1,59 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "Permission:DocumentManagement": "Administrarea documentelor",
+ "Permission:Projects": "Proiecte",
+ "Permission:Edit": "Editează",
+ "Permission:Delete": "Şterge",
+ "Permission:Create": "Creează",
+ "Permission:Documents": "Documente",
+ "Menu:Documents": "Documente",
+ "Menu:DocumentManagement": "Documente",
+ "Menu:ProjectManagement": "Proiecte",
+ "CreateANewProject": "Creează un nou proiect",
+ "Edit": "Editează",
+ "Create": "Creează",
+ "Pull": "Pull",
+ "Projects": "Proiecte",
+ "Name": "Nume",
+ "ShortName": "Nume pe scurt",
+ "DocumentStoreType": "DocumentStoreType",
+ "Format": "Format",
+ "ShortNameInfoText": "Va fi folosit pentru URL unic.",
+ "DisplayName:Name": "Nume",
+ "DisplayName:ShortName": "Nume pe scurt",
+ "DisplayName:Format": "Format",
+ "DisplayName:DefaultDocumentName": "Nume implicit document",
+ "DisplayName:NavigationDocumentName": "Nume document de navigare",
+ "DisplayName:MinimumVersion": "Versiune minimă",
+ "DisplayName:MainWebsiteUrl": "URL site web principal",
+ "DisplayName:LatestVersionBranchName": "Latest version branch name",
+ "DisplayName:GitHubRootUrl": "GitHub root URL",
+ "DisplayName:GitHubAccessToken": "GitHub access token",
+ "DisplayName:GitHubUserAgent": "GitHub user agent",
+ "DisplayName:GithubVersionProviderSource": "GitHub version provider source",
+ "DisplayName:VersionBranchPrefix": "Version branch prefix",
+ "DisplayName:All": "Pull all",
+ "DisplayName:LanguageCode": "Codul limbii",
+ "DisplayName:Version": "Versiune",
+ "Documents": "Documente",
+ "RemoveFromCache": "Şterge din cache",
+ "Reindex": "Reindexează",
+ "ReindexCompleted": "Reindexare completă",
+ "RemovedFromCache": "Şters din cache",
+ "RemoveFromCacheConfirmation": "Sunteţi sigur(ă) că vreţi să ştergeţi acest obiect din cache?",
+ "ReIndexDocumentConfirmation": "Sunteţi sigur(ă) că vreţi să reindexaţi acest obiect?",
+ "DeleteFromDatabase": "Şterge din baza de date",
+ "Deleted": "Şters",
+ "Search": "Caută",
+ "StartDate": "Data de început",
+ "EndDate": "Data de sfârşit",
+ "CreationTime": "Data creării",
+ "LastUpdateTime": "Ultima actualizare",
+ "LastSignificantUpdateTime": "Ultima actualizare semnificativă",
+ "Version": "Versiune",
+ "LanguageCode": "Codul limbii",
+ "FileName": "Nume fişier",
+ "LastCachedTime": "Durată cache"
+ }
+}
\ No newline at end of file
diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentRepository.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentRepository.cs
index 6abd112533..6b911c6e36 100644
--- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentRepository.cs
+++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentRepository.cs
@@ -25,6 +25,12 @@ namespace Volo.Docs.Documents
string version,
CancellationToken cancellationToken = default);
+ Task> GetListAsync(
+ Guid? projectId,
+ string version,
+ string name,
+ CancellationToken cancellationToken = default);
+
Task> GetAllAsync(
Guid? projectId,
string name,
@@ -67,4 +73,4 @@ namespace Volo.Docs.Documents
Task GetAsync(Guid id, CancellationToken cancellationToken = default);
}
-}
\ No newline at end of file
+}
diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/ro-RO.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/ro-RO.json
new file mode 100644
index 0000000000..dfc47b978f
--- /dev/null
+++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/ro-RO.json
@@ -0,0 +1,41 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "Documents": "Documente",
+ "BackToWebsite": "Înapoi la website",
+ "Contributors": "Contribuitori",
+ "ShareOn": "Distribuie pe",
+ "Version": "Versiune",
+ "Edit": "Editează",
+ "LastEditTime": "Ultima modificare",
+ "Delete": "Şterge",
+ "ClearCache": "Goleşte cache",
+ "ClearCacheConfirmationMessage": "Sunteţi sigur(ă) că vreţi să ştergeţi tot cache-ul pentru proiectul \"{0}\"",
+ "ReIndexAllProjects": "Reindexaţi toate proiectele",
+ "ReIndexProject": "Reindexaţi proiectul",
+ "ReIndexProjectConfirmationMessage": "Sunteţi sigur(ă) că vreţi să reindexaţi pentru proiectul \"{0}\"",
+ "SuccessfullyReIndexProject": "Reindexaţi cu succes pentru proiectul \"{0}\"",
+ "ReIndexAllProjectConfirmationMessage": "Sunteţi sigur(ă) că vreţi să reindexaţi toate proiectele?",
+ "SuccessfullyReIndexAllProject": "Reindexare cu succes pentru toate proiectele",
+ "InThisDocument": "În acest document",
+ "GoToTop": "Înapoi sus",
+ "Projects": "Proiect(e)",
+ "NoProjectWarning": "Nu există proiecte momentan!",
+ "DocumentNotFound": "Oops, documentul dorit nu a fost găsit!",
+ "ProjectNotFound": "Oops, proiectul dorit nu a fost găsit!",
+ "NavigationDocumentNotFound": "Această versiune nu are un document de navigare!",
+ "DocumentNotFoundInSelectedLanguage": "Documentul în limba dorită de dumneavoastră nu a fost găsit. Documentul este afişat în limba implicită.",
+ "FilterTopics": "Filtraţi subiectele",
+ "FullSearch": "Caută în documente",
+ "Volo.Docs.Domain:010001": "Căutarea elastică nu este activată.",
+ "MultipleVersionDocumentInfo": "Acest document are multiple versiuni. Selectaţi opţiunile cele mai potrivite pentru dumneavoastră.",
+ "New": "Nou",
+ "Upd": "Upd",
+ "NewExplanation": "Creat în ultimele două săptămâni.",
+ "UpdatedExplanation": "Actualizat în ultimele două săptămâni.",
+ "Volo.Docs.Domain:010002": "Numele pe scurt {ShortName} există deja.",
+ "Preview": "previzualizare",
+ "Search": "Caută",
+ "SearchResults": "Rezultatele căutării"
+ }
+}
\ No newline at end of file
diff --git a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Documents/EFCoreDocumentRepository.cs b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Documents/EFCoreDocumentRepository.cs
index e44c52c61c..a322120c3d 100644
--- a/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Documents/EFCoreDocumentRepository.cs
+++ b/modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Documents/EFCoreDocumentRepository.cs
@@ -38,6 +38,15 @@ namespace Volo.Docs.Documents
return await (await GetDbSetAsync()).Where(d => d.ProjectId == projectId).ToListAsync(cancellationToken: cancellationToken);
}
+ public async Task> GetListAsync(Guid? projectId, string version, string name, CancellationToken cancellationToken = default)
+ {
+ return await (await GetDbSetAsync())
+ .WhereIf(version != null, x => x.Version == version)
+ .WhereIf(name != null, x => x.Name == name)
+ .WhereIf(projectId.HasValue, x => x.ProjectId == projectId)
+ .ToListAsync(cancellationToken: cancellationToken);
+ }
+
public async Task> GetAllAsync(
Guid? projectId,
string name,
diff --git a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs
index 955319d848..3a57330557 100644
--- a/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs
+++ b/modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs
@@ -57,6 +57,16 @@ namespace Volo.Docs.Documents
x.Version == version, cancellationToken: cancellationToken);
}
+ public async Task> GetListAsync(Guid? projectId, string version, string name, CancellationToken cancellationToken = default)
+ {
+ return await (await GetMongoQueryableAsync(cancellationToken))
+ .WhereIf(version != null, x => x.Version == version)
+ .WhereIf(name != null, x => x.Name == name)
+ .WhereIf(projectId.HasValue, x => x.ProjectId == projectId)
+ .As>()
+ .ToListAsync(cancellationToken);
+ }
+
public async Task> GetAllAsync(
Guid? projectId,
string name,
diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css
index 118e70848c..e917ce1b67 100644
--- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css
+++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.css
@@ -72,7 +72,7 @@
.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul {
font-size: 14px;
list-style: none;
- padding: 0 1rem;
+ padding: 0 1rem 1rem;
margin: 0; }
.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li {
margin-left: 0px;
diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.min.css b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.min.css
index ca0a754a36..3e0cdc1e32 100644
--- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.min.css
+++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.min.css
@@ -1 +1 @@
-body{position:relative;}.docs-page{background:#f5f7f9;}.docs-page .anchorjs-link{transition:all .25s linear;}.docs-page *:hover>.anchorjs-link{margin-left:-1.125em !important;transition:color .25s linear;color:#808080;}.docs-page .anchorjs-link:hover{text-decoration:none;}.docs-page .docs-sidebar{padding-right:1rem;position:relative;top:0;left:0;position:fixed;background:#1d1d1d;}.docs-page .docs-sidebar .input-group{border-radius:5px;overflow:hidden;}.docs-page .docs-sidebar .docs-sidebar-wrapper{width:300px;float:right;}.docs-page .docs-sidebar .docs-sidebar-wrapper input.form-control{border:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper input.form-control:focus,.docs-page .docs-sidebar .docs-sidebar-wrapper input.form-control:active,.docs-page .docs-sidebar .docs-sidebar-wrapper input.form-control:hover,.docs-page .docs-sidebar .docs-sidebar-wrapper input.form-control:visited{box-shadow:none;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version{position:relative;padding:0 1rem;margin:.25rem 0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select{border-radius:3px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select .input-group-text{padding:0 10px;font-size:.9rem;width:26px;height:34px;line-height:1;border-radius:0;border:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select .input-group-text i{color:#666;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control{padding:0 10px 2px 10px;border:0;min-height:34px;height:34px;font-size:.9em;border-radius:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control:focus,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control:active,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control:hover,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control:visited,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control:focus,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control:active,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control:hover,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control:visited{box-shadow:none;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control{padding:0 10px 2px 6px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-filter{padding:0 1rem;margin:.5rem 0;font-size:.9em;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-filter .filter-icon i.fa{color:#ddd;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list{height:100vh;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list>ul{display:block;height:calc(100vh - 230px);overflow-y:auto;margin-right:12px !important;margin-top:20px !important;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul{font-size:14px;list-style:none;padding:0 1rem;margin:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li{margin-left:0;padding-left:24px;display:block;width:100%;position:relative;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a{color:#999;font-weight:700;padding:7px 0;display:block;border-bottom:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a:hover{color:#000;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a.last-link{top:11px;color:#aaa;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li .badge{text-transform:uppercase;font-size:9px;position:relative;letter-spacing:.125px;top:-2px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li span.tree-toggle{color:#999;padding:7px 0;display:block;border-bottom:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li .plus-icon{font-size:.85em;transition:.3s;width:18px;height:18px;text-align:center;padding:0;line-height:1;border-radius:50%;margin-right:4px;position:absolute;left:2px;top:11px;color:#aaa;cursor:default;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li .plus-icon .fa-long-arrow-right.no-link{color:#555;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li .plus-icon .fa-chevron-right{cursor:pointer;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul{padding:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul li a{font-weight:400;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul li ul{padding:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul li ul li a{font-weight:300;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree>a{color:#000;transition:.4s;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree>span .fa{transform:rotate(90deg);color:#007bff;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree.last-link>span .fa{transform:rotate(0deg);}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand{font-size:1.35rem;color:#000;font-weight:700;padding:15px 0 15px;line-height:1;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand strong{font-weight:300;text-transform:uppercase;font-size:.7em;letter-spacing:1px;}.docs-page .docs-sidebar .docs-top .navbar-logo .go-back-site{color:#000;opacity:.65;transition:.2s;font-size:.8em;font-weight:300;}.docs-page .docs-sidebar .docs-top .navbar-logo .go-back-site:hover{text-decoration:none;opacity:1;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-logo-desc{font-size:.85em;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-logo-desc strong{display:block;}.docs-page .docs-content{overflow-x:scroll;min-height:100vh;}.docs-page .docs-content .contributors{position:absolute;top:15px;right:5px;}.docs-page .docs-content .contributors .contributors-avatar{border-radius:21px;width:21px;height:21px;}.docs-page .docs-content .contributors a{padding:0;width:21px;height:21px;display:inline-block;margin:0 0 0 2px;}.docs-page .docs-content .contributors a:hover{text-decoration:none;}.docs-page .docs-content .docs-link-btns{background:#f5f7fa;padding:15px 30px;margin:0 -15px;text-align:right;font-size:.8em;min-height:48px;}.docs-page .docs-content .docs-link-btns a{color:#222;}.docs-page .docs-content .docs-link-btns a .text-muted{color:#ccc !important;}.docs-page .docs-content .docs-link-btns a:hover{color:#000;text-decoration:none;}.docs-page .docs-content .docs-link-btns .search-area{margin:-5px 0 -5px -10px;box-shadow:0 0 10px #e8e8e8;}.docs-page .docs-content .docs-link-btns .search-area .input-group-text{background:#fff;border:0;color:#000;font-size:1em;}.docs-page .docs-content .docs-link-btns .search-area .form-control{background:#fff;border:0;font-size:1em;padding-left:0;outline:0;box-shadow:none;}.docs-page .docs-content .docs-text-field{padding:2rem;}.docs-page .docs-content article.docs-body{word-break:break-word;}.docs-page .docs-content article.docs-body h1{padding-top:1rem;font-size:2.25rem;padding-bottom:10px;}.docs-page .docs-content article.docs-body h2{padding-top:2rem;padding-bottom:10px;font-size:2rem;}.docs-page .docs-content article.docs-body h3,.docs-page .docs-content article.docs-body h4,.docs-page .docs-content article.docs-body h5,.docs-page .docs-content article.docs-body h6{padding-top:20px;padding-bottom:5px;font-size:1.5rem;}.docs-page .docs-content article.docs-body h1,.docs-page .docs-content article.docs-body h2,.docs-page .docs-content article.docs-body h3,.docs-page .docs-content article.docs-body h4,.docs-page .docs-content article.docs-body h5,.docs-page .docs-content article.docs-body h6{position:relative;}.docs-page .docs-content article.docs-body h1 .anchor,.docs-page .docs-content article.docs-body h2 .anchor,.docs-page .docs-content article.docs-body h3 .anchor,.docs-page .docs-content article.docs-body h4 .anchor,.docs-page .docs-content article.docs-body h5 .anchor,.docs-page .docs-content article.docs-body h6 .anchor{position:absolute;right:-26px;font-size:18px;bottom:5px;color:#999;opacity:0;transition:.5s;}.docs-page .docs-content article.docs-body h1:hover .anchor,.docs-page .docs-content article.docs-body h2:hover .anchor,.docs-page .docs-content article.docs-body h3:hover .anchor,.docs-page .docs-content article.docs-body h4:hover .anchor,.docs-page .docs-content article.docs-body h5:hover .anchor,.docs-page .docs-content article.docs-body h6:hover .anchor{opacity:1;}.docs-page .docs-content article.docs-body .blockquote{margin-bottom:1rem;margin-left:0;border-left:3px solid #d2dbe4;padding:1em 1.5em;background-color:#e9edf1;padding-bottom:.2em;font-size:1em;}.docs-page .docs-content article.docs-body img{max-width:100%;border:1px solid #f4f5f7;margin:15px 0 25px;box-shadow:0 0 45px #f8f9fa;border-radius:6px;}.docs-page .docs-content article.docs-body table{display:block;overflow:auto;width:100%;}.docs-page .docs-content article.docs-body table thead tr{border-bottom:2px inset;}.docs-page .docs-content article.docs-body table th{font-weight:600;}.docs-page .docs-content article.docs-body table td,.docs-page .docs-content article.docs-body table th{border:1px solid #dfe2e5;padding:6px 13px;}.docs-page .docs-content article.docs-body table tr{background-color:#fff;border-top:1px solid #c6cbd1;}.docs-page .docs-content article.docs-body table tr:nth-child(2n){background-color:#f6f8fa;}.docs-page .docs-content article.docs-body table img{background-color:initial;}.docs-page .doc-social-btns{margin:0 -15px 0;font-size:.8em;background:#e9ecf0;height:53px;padding:15px 20px;position:fixed;top:0;width:100%;}.docs-page .doc-social-btns a:hover{text-decoration:none;}.docs-page .doc-social-btns .twitter{color:#00acee;}.docs-page .doc-social-btns .linkedin{color:#0077b5;}.docs-page .doc-social-btns .email{color:#5a5a5a;}.docs-page .doc-social-btns .share-button{margin-left:10px;}.docs-page .cont-container a.cont-avatar{position:relative;}.docs-page .cont-container a.cont-avatar img{width:24px;height:24px;box-shadow:0 0 8px #c1bbbb;border:2px solid #fff;margin-left:-10px;display:inline-block;margin-top:-2px;transition:.2s;}.docs-page .cont-container:hover a.cont-avatar img{margin-left:-2px;}.docs-page .docs-page-index{min-height:90vh;background-color:#f5f7fa !important;}.docs-page .docs-page-index #scroll-index{max-height:90vh;}.docs-page .docs-page-index .docs-inner-anchors{position:fixed;top:50px;padding:10px;font-size:.9em;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills{font-size:.92em;margin-left:15px;border-left:1px solid #eee;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-link{padding:3px 14px 4px;color:#aaa;line-height:1.2;position:relative;border-left:1px solid #eee;border-radius:0;margin-left:-1px;margin-top:1px;margin-bottom:1px;transition:.2s;font-weight:normal;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-link.active{border-left:1px solid #007bff;background:none;color:#007bff;font-weight:normal;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-pills .nav-link.active{color:#007bff;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-pills .nav-pills .nav-link.active{color:#007bff;}.docs-page .docs-page-index .docs-inner-anchors .index-scroll{margin-left:-30px;}.docs-page .docs-page-index .docs-inner-anchors .docs-anchors-wrapper{max-width:300px;float:left;}.docs-page .docs-page-index .scroll-top-btn{display:none;font-size:.85em;color:#aaa;text-decoration:none;padding-left:18px;}.docs-page .docs-page-index .scroll-top-btn.showup{display:block;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control{background:#000;color:#fff;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control{background:#000;color:#fff;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control::placeholder{color:#fff;opacity:.5;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select label{background:#000;border-color:#000;color:#ddd;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-filter .form-control{background:#333;color:#999;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-filter select{border:0;border-radius:6px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-filter .filter-icon i.fa{color:#aaa;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a{color:#aaa;border-bottom:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a:hover{color:#fff;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a .plus-icon{font-size:.85em;transition:.3s;width:18px;height:18px;text-align:center;padding:0;line-height:1;border-radius:50%;margin-right:4px;position:absolute;left:2px;top:11px;color:#aaa;cursor:default;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a .plus-icon .fa-long-arrow-right.no-link{color:#555;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a .plus-icon .fa-chevron-right{cursor:pointer;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a .plus-icon.last-link{top:11px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li span.tree-toggle{color:#555;padding:7px 0;display:block;border-bottom:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree>a{color:#fff;transition:.4s;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree>a span .fa{color:#fff;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree>a span:not(.last-link) .fa{transform:rotate(90deg);color:#fff;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand{color:#fff;text-transform:uppercase;white-space:unset;}.docs-page .docs-sidebar .docs-top .navbar-logo .go-back-site{color:#fff;text-align:center;display:block;width:100%;background:#444;padding:6px 0 8px;border-radius:5px;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-logo-desc{color:#ddd;}@media(min-width:1100px){.container{max-width:1080px;}}@media(min-width:1366px){.container{max-width:1340px;}}@media(min-width:1440px){.container{max-width:1400px;}}@media(max-width:767px){.docs-page .docs-content article.docs-body h1{padding-top:1.5rem;}.docs-page{background:#f5f7f9;}.docs-page>.container-fluid{display:block;}.docs-page>.container-fluid>.row{display:block;}.docs-page .docs-sidebar{position:fixed;max-width:100%;width:100%;display:block;padding:0 !important;top:0;left:0;z-index:100;right:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper{max-width:100%;width:100%;top:0;position:relative;margin:0 !important;height:72px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list{padding:.5rem 1.5rem 2rem 1.5rem;position:fixed;top:70px;font-size:17px;left:0;width:100%;z-index:100;background:#1d1d1d;display:none;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list .docs-filter{padding:0 0 1rem !important;}.docs-page .docs-sidebar .docs-top .navbar-logo{padding:0;padding-top:.3rem;display:block;text-align:center;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand{font-size:1.25rem;font-weight:700;display:block;margin-right:0;padding:10px 0 15px;text-transform:uppercase;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand .docs-logo{width:110px;}.docs-page .docs-sidebar .docs-top .navbar-logo .go-back-site{display:none;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-logo-desc{font-size:1em;display:none;}.docs-page .docs-sidebar .docs-top .open-dmenu{position:absolute;top:10px;left:20px;}.docs-page .docs-content{padding-top:72px;max-width:100%;display:block !important;}.docs-page .docs-content .docs-text-field{padding:1rem 1.5rem;}.docs-page .docs-page-index{display:none;}}.for-mobile{display:none;}.for-desktop{display:inline-block;}pre[class*="language-"]{padding:1.4em 2em !important;margin:15px 0 25px !important;border-radius:6px;}code{padding:.2em .4em;margin:0;font-size:82%;background-color:#f0f1f3;border-radius:3px;color:#28a745;}pre code{padding:0;}pre .token.keyword{color:#569cd6;}pre .token.atrule,pre .token.attr-value,pre .token.function,pre .token.class-name{color:#d69d85;}:not(pre)>code[class*="language-"],pre[class*="language-"]{background:#191919 !important;}div.code-toolbar>.toolbar span{cursor:default;}div.code-toolbar>.toolbar a{cursor:copy;}.logo-nav ul{width:300px !important;}@media(max-width:767px){body{font-size:14px;}.for-mobile{display:inline-block;}.for-desktop{display:none;}.close-mmenu,.close-dmenu{position:absolute;top:-78px;left:25px;color:#fff;font-size:68px;background:#fff;opacity:0;}.navbar{padding:.5rem 1.75rem;}.navbar .navbar-collapse{background:#38003d;position:fixed;top:86px;left:0;width:100%;height:100vh;height:calc(100vh - 86px);z-index:100 !important;}.navbar .navbar-collapse .navbar-nav{height:100vh;padding:20px 30px;overflow:auto;}.navbar .navbar-collapse .navbar-nav .nav-link{padding:1.2rem !important;}.navbar .navbar-toggler{padding:.5rem .75rem;font-size:1.5rem;line-height:1;background-color:transparent;border:0;border-radius:.25rem;color:#fff !important;margin-left:-1rem;}.section-with-logos img{margin:15px;opacity:1;-webkit-filter:grayscale(0%);filter:grayscale(0%);}span.code-arrow{padding:0 0 0;display:block;transform:rotate(90deg);font-size:2em;}.mb-5,.my-5{margin-bottom:2rem !important;}}@media screen and (max-width:767px){.navbar-logo .navbar-brand{display:inline-block;margin:0 auto !important;max-width:70%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}}.alert-criteria{padding:1.25em 1.5em;max-width:100%;}.alert-criteria p.alert-p{font-size:.96em;}.alert-criteria .input-group .input-group-text,.alert-criteria .input-group .form-control{font-size:.96em;}@media screen and (max-width:767px){.alert-criteria .input-group .input-group-text,.alert-criteria .input-group .form-control{font-size:.88em;}}.alert-criteria .input-group .input-group-text{color:#004085;background-color:#bddcfd;border:1px solid #bddcfd;}@media screen and (max-width:1366px){.alert-criteria .input-group .input-group-text{display:none;}}.alert-criteria .input-group .form-control{color:#004085;background-color:#fff;border:1px solid #bddcfd;}@media screen and (max-width:1366px){.alert-criteria .input-group .form-control{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem;}}.scrolledMore{padding-top:107px;}.scrolledMore .alert-criteria{position:fixed;top:0;z-index:10;border:0;border-radius:0;margin-left:-47px;padding:.5em .75em;}@media screen and (max-width:767px){.scrolledMore .alert-criteria{top:72px;margin-left:-36px;}}.scrolledMore .alert-criteria p.alert-p{display:none;}.mCS-autoHide>.mCustomScrollBox>.mCSB_scrollTools,.mCS-autoHide>.mCustomScrollBox~.mCSB_scrollTools{opacity:1 !important;filter:"alpha(opacity=1)";-ms-filter:"alpha(opacity=1)";}
\ No newline at end of file
+body{position:relative;}.docs-page{background:#f5f7f9;}.docs-page .anchorjs-link{transition:all .25s linear;}.docs-page *:hover>.anchorjs-link{margin-left:-1.125em !important;transition:color .25s linear;color:#808080;}.docs-page .anchorjs-link:hover{text-decoration:none;}.docs-page .docs-sidebar{padding-right:1rem;position:relative;top:0;left:0;position:fixed;background:#1d1d1d;}.docs-page .docs-sidebar .input-group{border-radius:5px;overflow:hidden;}.docs-page .docs-sidebar .docs-sidebar-wrapper{width:300px;float:right;}.docs-page .docs-sidebar .docs-sidebar-wrapper input.form-control{border:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper input.form-control:focus,.docs-page .docs-sidebar .docs-sidebar-wrapper input.form-control:active,.docs-page .docs-sidebar .docs-sidebar-wrapper input.form-control:hover,.docs-page .docs-sidebar .docs-sidebar-wrapper input.form-control:visited{box-shadow:none;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version{position:relative;padding:0 1rem;margin:.25rem 0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select{border-radius:3px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select .input-group-text{padding:0 10px;font-size:.9rem;width:26px;height:34px;line-height:1;border-radius:0;border:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select .input-group-text i{color:#666;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control{padding:0 10px 2px 10px;border:0;min-height:34px;height:34px;font-size:.9em;border-radius:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control:focus,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control:active,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control:hover,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control:visited,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control:focus,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control:active,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control:hover,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control:visited{box-shadow:none;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control{padding:0 10px 2px 6px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-filter{padding:0 1rem;margin:.5rem 0;font-size:.9em;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-filter .filter-icon i.fa{color:#ddd;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list{height:100vh;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list>ul{display:block;height:calc(100vh - 230px);overflow-y:auto;margin-right:12px !important;margin-top:20px !important;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul{font-size:14px;list-style:none;padding:0 1rem 1rem;margin:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li{margin-left:0;padding-left:24px;display:block;width:100%;position:relative;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a{color:#999;font-weight:700;padding:7px 0;display:block;border-bottom:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a:hover{color:#000;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a.last-link{top:11px;color:#aaa;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li .badge{text-transform:uppercase;font-size:9px;position:relative;letter-spacing:.125px;top:-2px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li span.tree-toggle{color:#999;padding:7px 0;display:block;border-bottom:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li .plus-icon{font-size:.85em;transition:.3s;width:18px;height:18px;text-align:center;padding:0;line-height:1;border-radius:50%;margin-right:4px;position:absolute;left:2px;top:11px;color:#aaa;cursor:default;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li .plus-icon .fa-long-arrow-right.no-link{color:#555;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li .plus-icon .fa-chevron-right{cursor:pointer;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul{padding:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul li a{font-weight:400;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul li ul{padding:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li ul li ul li a{font-weight:300;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree>a{color:#000;transition:.4s;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree>span .fa{transform:rotate(90deg);color:#007bff;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree.last-link>span .fa{transform:rotate(0deg);}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand{font-size:1.35rem;color:#000;font-weight:700;padding:15px 0 15px;line-height:1;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand strong{font-weight:300;text-transform:uppercase;font-size:.7em;letter-spacing:1px;}.docs-page .docs-sidebar .docs-top .navbar-logo .go-back-site{color:#000;opacity:.65;transition:.2s;font-size:.8em;font-weight:300;}.docs-page .docs-sidebar .docs-top .navbar-logo .go-back-site:hover{text-decoration:none;opacity:1;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-logo-desc{font-size:.85em;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-logo-desc strong{display:block;}.docs-page .docs-content{overflow-x:scroll;min-height:100vh;}.docs-page .docs-content .contributors{position:absolute;top:15px;right:5px;}.docs-page .docs-content .contributors .contributors-avatar{border-radius:21px;width:21px;height:21px;}.docs-page .docs-content .contributors a{padding:0;width:21px;height:21px;display:inline-block;margin:0 0 0 2px;}.docs-page .docs-content .contributors a:hover{text-decoration:none;}.docs-page .docs-content .docs-link-btns{background:#f5f7fa;padding:15px 30px;margin:0 -15px;text-align:right;font-size:.8em;min-height:48px;}.docs-page .docs-content .docs-link-btns a{color:#222;}.docs-page .docs-content .docs-link-btns a .text-muted{color:#ccc !important;}.docs-page .docs-content .docs-link-btns a:hover{color:#000;text-decoration:none;}.docs-page .docs-content .docs-link-btns .search-area{margin:-5px 0 -5px -10px;box-shadow:0 0 10px #e8e8e8;}.docs-page .docs-content .docs-link-btns .search-area .input-group-text{background:#fff;border:0;color:#000;font-size:1em;}.docs-page .docs-content .docs-link-btns .search-area .form-control{background:#fff;border:0;font-size:1em;padding-left:0;outline:0;box-shadow:none;}.docs-page .docs-content .docs-text-field{padding:2rem;}.docs-page .docs-content article.docs-body{word-break:break-word;}.docs-page .docs-content article.docs-body h1{padding-top:1rem;font-size:2.25rem;padding-bottom:10px;}.docs-page .docs-content article.docs-body h2{padding-top:2rem;padding-bottom:10px;font-size:2rem;}.docs-page .docs-content article.docs-body h3,.docs-page .docs-content article.docs-body h4,.docs-page .docs-content article.docs-body h5,.docs-page .docs-content article.docs-body h6{padding-top:20px;padding-bottom:5px;font-size:1.5rem;}.docs-page .docs-content article.docs-body h1,.docs-page .docs-content article.docs-body h2,.docs-page .docs-content article.docs-body h3,.docs-page .docs-content article.docs-body h4,.docs-page .docs-content article.docs-body h5,.docs-page .docs-content article.docs-body h6{position:relative;}.docs-page .docs-content article.docs-body h1 .anchor,.docs-page .docs-content article.docs-body h2 .anchor,.docs-page .docs-content article.docs-body h3 .anchor,.docs-page .docs-content article.docs-body h4 .anchor,.docs-page .docs-content article.docs-body h5 .anchor,.docs-page .docs-content article.docs-body h6 .anchor{position:absolute;right:-26px;font-size:18px;bottom:5px;color:#999;opacity:0;transition:.5s;}.docs-page .docs-content article.docs-body h1:hover .anchor,.docs-page .docs-content article.docs-body h2:hover .anchor,.docs-page .docs-content article.docs-body h3:hover .anchor,.docs-page .docs-content article.docs-body h4:hover .anchor,.docs-page .docs-content article.docs-body h5:hover .anchor,.docs-page .docs-content article.docs-body h6:hover .anchor{opacity:1;}.docs-page .docs-content article.docs-body .blockquote{margin-bottom:1rem;margin-left:0;border-left:3px solid #d2dbe4;padding:1em 1.5em;background-color:#e9edf1;padding-bottom:.2em;font-size:1em;}.docs-page .docs-content article.docs-body img{max-width:100%;border:1px solid #f4f5f7;margin:15px 0 25px;box-shadow:0 0 45px #f8f9fa;border-radius:6px;}.docs-page .docs-content article.docs-body table{display:block;overflow:auto;width:100%;}.docs-page .docs-content article.docs-body table thead tr{border-bottom:2px inset;}.docs-page .docs-content article.docs-body table th{font-weight:600;}.docs-page .docs-content article.docs-body table td,.docs-page .docs-content article.docs-body table th{border:1px solid #dfe2e5;padding:6px 13px;}.docs-page .docs-content article.docs-body table tr{background-color:#fff;border-top:1px solid #c6cbd1;}.docs-page .docs-content article.docs-body table tr:nth-child(2n){background-color:#f6f8fa;}.docs-page .docs-content article.docs-body table img{background-color:initial;}.docs-page .doc-social-btns{margin:0 -15px 0;font-size:.8em;background:#e9ecf0;height:53px;padding:15px 20px;position:fixed;top:0;width:100%;}.docs-page .doc-social-btns a:hover{text-decoration:none;}.docs-page .doc-social-btns .twitter{color:#00acee;}.docs-page .doc-social-btns .linkedin{color:#0077b5;}.docs-page .doc-social-btns .email{color:#5a5a5a;}.docs-page .doc-social-btns .share-button{margin-left:10px;}.docs-page .cont-container a.cont-avatar{position:relative;}.docs-page .cont-container a.cont-avatar img{width:24px;height:24px;box-shadow:0 0 8px #c1bbbb;border:2px solid #fff;margin-left:-10px;display:inline-block;margin-top:-2px;transition:.2s;}.docs-page .cont-container:hover a.cont-avatar img{margin-left:-2px;}.docs-page .docs-page-index{min-height:90vh;background-color:#f5f7fa !important;}.docs-page .docs-page-index #scroll-index{max-height:90vh;}.docs-page .docs-page-index .docs-inner-anchors{position:fixed;top:50px;padding:10px;font-size:.9em;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills{font-size:.92em;margin-left:15px;border-left:1px solid #eee;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-link{padding:3px 14px 4px;color:#aaa;line-height:1.2;position:relative;border-left:1px solid #eee;border-radius:0;margin-left:-1px;margin-top:1px;margin-bottom:1px;transition:.2s;font-weight:normal;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-link.active{border-left:1px solid #007bff;background:none;color:#007bff;font-weight:normal;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-pills .nav-link.active{color:#007bff;}.docs-page .docs-page-index .docs-inner-anchors .navbar .nav-pills .nav-pills .nav-pills .nav-link.active{color:#007bff;}.docs-page .docs-page-index .docs-inner-anchors .index-scroll{margin-left:-30px;}.docs-page .docs-page-index .docs-inner-anchors .docs-anchors-wrapper{max-width:300px;float:left;}.docs-page .docs-page-index .scroll-top-btn{display:none;font-size:.85em;color:#aaa;text-decoration:none;padding-left:18px;}.docs-page .docs-page-index .scroll-top-btn.showup{display:block;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select select.form-control,.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control{background:#000;color:#fff;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control{background:#000;color:#fff;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select input.form-control::placeholder{color:#fff;opacity:.5;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-version .version-select label{background:#000;border-color:#000;color:#ddd;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-filter .form-control{background:#333;color:#999;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-filter select{border:0;border-radius:6px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-filter .filter-icon i.fa{color:#aaa;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a{color:#aaa;border-bottom:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a:hover{color:#fff;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a .plus-icon{font-size:.85em;transition:.3s;width:18px;height:18px;text-align:center;padding:0;line-height:1;border-radius:50%;margin-right:4px;position:absolute;left:2px;top:11px;color:#aaa;cursor:default;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a .plus-icon .fa-long-arrow-right.no-link{color:#555;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a .plus-icon .fa-chevron-right{cursor:pointer;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li a .plus-icon.last-link{top:11px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li span.tree-toggle{color:#555;padding:7px 0;display:block;border-bottom:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree>a{color:#fff;transition:.4s;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree>a span .fa{color:#fff;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list ul li.selected-tree>a span:not(.last-link) .fa{transform:rotate(90deg);color:#fff;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand{color:#fff;text-transform:uppercase;white-space:unset;}.docs-page .docs-sidebar .docs-top .navbar-logo .go-back-site{color:#fff;text-align:center;display:block;width:100%;background:#444;padding:6px 0 8px;border-radius:5px;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-logo-desc{color:#ddd;}@media(min-width:1100px){.container{max-width:1080px;}}@media(min-width:1366px){.container{max-width:1340px;}}@media(min-width:1440px){.container{max-width:1400px;}}@media(max-width:767px){.docs-page .docs-content article.docs-body h1{padding-top:1.5rem;}.docs-page{background:#f5f7f9;}.docs-page>.container-fluid{display:block;}.docs-page>.container-fluid>.row{display:block;}.docs-page .docs-sidebar{position:fixed;max-width:100%;width:100%;display:block;padding:0 !important;top:0;left:0;z-index:100;right:0;}.docs-page .docs-sidebar .docs-sidebar-wrapper{max-width:100%;width:100%;top:0;position:relative;margin:0 !important;height:72px;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list{padding:.5rem 1.5rem 2rem 1.5rem;position:fixed;top:70px;font-size:17px;left:0;width:100%;z-index:100;background:#1d1d1d;display:none;}.docs-page .docs-sidebar .docs-sidebar-wrapper .docs-tree-list .docs-filter{padding:0 0 1rem !important;}.docs-page .docs-sidebar .docs-top .navbar-logo{padding:0;padding-top:.3rem;display:block;text-align:center;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand{font-size:1.25rem;font-weight:700;display:block;margin-right:0;padding:10px 0 15px;text-transform:uppercase;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-brand .docs-logo{width:110px;}.docs-page .docs-sidebar .docs-top .navbar-logo .go-back-site{display:none;}.docs-page .docs-sidebar .docs-top .navbar-logo .navbar-logo-desc{font-size:1em;display:none;}.docs-page .docs-sidebar .docs-top .open-dmenu{position:absolute;top:10px;left:20px;}.docs-page .docs-content{padding-top:72px;max-width:100%;display:block !important;}.docs-page .docs-content .docs-text-field{padding:1rem 1.5rem;}.docs-page .docs-page-index{display:none;}}.for-mobile{display:none;}.for-desktop{display:inline-block;}pre[class*="language-"]{padding:1.4em 2em !important;margin:15px 0 25px !important;border-radius:6px;}code{padding:.2em .4em;margin:0;font-size:82%;background-color:#f0f1f3;border-radius:3px;color:#28a745;}pre code{padding:0;}pre .token.keyword{color:#569cd6;}pre .token.atrule,pre .token.attr-value,pre .token.function,pre .token.class-name{color:#d69d85;}:not(pre)>code[class*="language-"],pre[class*="language-"]{background:#191919 !important;}div.code-toolbar>.toolbar span{cursor:default;}div.code-toolbar>.toolbar a{cursor:copy;}.logo-nav ul{width:300px !important;}@media(max-width:767px){body{font-size:14px;}.for-mobile{display:inline-block;}.for-desktop{display:none;}.close-mmenu,.close-dmenu{position:absolute;top:-78px;left:25px;color:#fff;font-size:68px;background:#fff;opacity:0;}.navbar{padding:.5rem 1.75rem;}.navbar .navbar-collapse{background:#38003d;position:fixed;top:86px;left:0;width:100%;height:100vh;height:calc(100vh - 86px);z-index:100 !important;}.navbar .navbar-collapse .navbar-nav{height:100vh;padding:20px 30px;overflow:auto;}.navbar .navbar-collapse .navbar-nav .nav-link{padding:1.2rem !important;}.navbar .navbar-toggler{padding:.5rem .75rem;font-size:1.5rem;line-height:1;background-color:transparent;border:0;border-radius:.25rem;color:#fff !important;margin-left:-1rem;}.section-with-logos img{margin:15px;opacity:1;-webkit-filter:grayscale(0%);filter:grayscale(0%);}span.code-arrow{padding:0 0 0;display:block;transform:rotate(90deg);font-size:2em;}.mb-5,.my-5{margin-bottom:2rem !important;}}@media screen and (max-width:767px){.navbar-logo .navbar-brand{display:inline-block;margin:0 auto !important;max-width:70%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}}.alert-criteria{padding:1.25em 1.5em;max-width:100%;}.alert-criteria p.alert-p{font-size:.96em;}.alert-criteria .input-group .input-group-text,.alert-criteria .input-group .form-control{font-size:.96em;}@media screen and (max-width:767px){.alert-criteria .input-group .input-group-text,.alert-criteria .input-group .form-control{font-size:.88em;}}.alert-criteria .input-group .input-group-text{color:#004085;background-color:#bddcfd;border:1px solid #bddcfd;}@media screen and (max-width:1366px){.alert-criteria .input-group .input-group-text{display:none;}}.alert-criteria .input-group .form-control{color:#004085;background-color:#fff;border:1px solid #bddcfd;}@media screen and (max-width:1366px){.alert-criteria .input-group .form-control{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem;}}.scrolledMore{padding-top:107px;}.scrolledMore .alert-criteria{position:fixed;top:0;z-index:10;border:0;border-radius:0;margin-left:-47px;padding:.5em .75em;}@media screen and (max-width:767px){.scrolledMore .alert-criteria{top:72px;margin-left:-36px;}}.scrolledMore .alert-criteria p.alert-p{display:none;}.mCS-autoHide>.mCustomScrollBox>.mCSB_scrollTools,.mCS-autoHide>.mCustomScrollBox~.mCSB_scrollTools{opacity:1 !important;filter:"alpha(opacity=1)";-ms-filter:"alpha(opacity=1)";}
\ No newline at end of file
diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.scss b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.scss
index ec877a119b..792abdc2e8 100644
--- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.scss
+++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Shared/Styles/vs.scss
@@ -112,7 +112,7 @@ body {
ul {
font-size: 14px;
list-style: none;
- padding: 0 1rem;
+ padding: 0 1rem 1rem;
margin: 0;
li {
diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/ro-RO.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/ro-RO.json
new file mode 100644
index 0000000000..824d789291
--- /dev/null
+++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/ro-RO.json
@@ -0,0 +1,10 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "Features": "Caracteristici",
+ "NoFeatureFoundMessage": "Nu există nicio caracteristică disponibilă.",
+ "Permission:FeatureManagement": "Administrare caracteristici",
+ "Permission:FeatureManagement.ManageHostFeatures": "Gestionare caracteristici gazdă",
+ "Volo.Abp.FeatureManagement:InvalidFeatureValue" : "Valoarea {0} a caracteristicii nu este validă!"
+ }
+}
\ No newline at end of file
diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ro-RO.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ro-RO.json
new file mode 100644
index 0000000000..c9afce70c8
--- /dev/null
+++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/ro-RO.json
@@ -0,0 +1,110 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "Menu:IdentityManagement": "Administrarea identităţii",
+ "Users": "Utilizatori",
+ "NewUser": "Utilizator nou",
+ "UserName": "Nume de utilizator",
+ "EmailAddress": "Adresa de email",
+ "PhoneNumber": "Număr de telefon",
+ "UserInformations": "Informaţii de utilizator",
+ "DisplayName:IsDefault": "Implicit",
+ "DisplayName:IsStatic": "Static",
+ "DisplayName:IsPublic": "Public",
+ "Roles": "Roluri",
+ "Password": "Parola",
+ "PersonalInfo": "Profilul meu",
+ "PersonalSettings": "Setări personale",
+ "UserDeletionConfirmationMessage": "Utilizatorul '{0}' va fi şters. Sunteţi sigur(ă)?",
+ "RoleDeletionConfirmationMessage": "Rolul '{0}' va fi şters. Sunteţi sigur(ă)?",
+ "DisplayName:RoleName": "Nume rol",
+ "DisplayName:UserName": "Nume de utilizator",
+ "DisplayName:Name": "Nume",
+ "DisplayName:Surname": "Nume",
+ "DisplayName:Password": "Parola",
+ "DisplayName:Email": "Adresa de email",
+ "DisplayName:PhoneNumber": "Număr de telefon",
+ "DisplayName:TwoFactorEnabled": "Autentificare în doi paşi",
+ "DisplayName:LockoutEnabled": "Blocaţi contul după încercări eşuate de autentificare",
+ "NewRole": "Rol nou",
+ "RoleName": "Nume rol",
+ "CreationTime": "Data creării",
+ "Permissions": "Permisiuni",
+ "DisplayName:CurrentPassword": "Parola curentă",
+ "DisplayName:NewPassword": "Parola nouă",
+ "DisplayName:NewPasswordConfirm": "Confirmaţi noua parolă",
+ "PasswordChangedMessage": "Parola dumneavoastră a fost schimbată cu succes.",
+ "PersonalSettingsSavedMessage": "Setările personale ale dumneavoastră au fost salvate cu succes.",
+ "Volo.Abp.Identity:DefaultError": "A intervenit o eroare neaşteptată.",
+ "Volo.Abp.Identity:ConcurrencyFailure": "Eşec concurenţial optimist, obiectul a fost modificat.",
+ "Volo.Abp.Identity:DuplicateEmail": "Emailul '{0}' este deja luat.",
+ "Volo.Abp.Identity:DuplicateRoleName": "Numele de rol '{0}' este deja luat.",
+ "Volo.Abp.Identity:DuplicateUserName": "Numele de utilizator '{0}' este deja luat.",
+ "Volo.Abp.Identity:InvalidEmail": "Emailul '{0}' este invalid.",
+ "Volo.Abp.Identity:InvalidPasswordHasherCompatibilityMode": "Modul PasswordHasherCompatibilityMode este invalid.",
+ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "Numărul de iteraţii trebuie să fie un număr întreg pozitiv..",
+ "Volo.Abp.Identity:InvalidRoleName": "Numele de rol '{0}' este invalid.",
+ "Volo.Abp.Identity:InvalidToken": "Invalid token.",
+ "Volo.Abp.Identity:InvalidUserName": "Numele de utilizator '{0}' este invalid, poate conţine doar litere şi cifre.",
+ "Volo.Abp.Identity:LoginAlreadyAssociated": "Un utilizator cu această autentificare există deja.",
+ "Volo.Abp.Identity:PasswordMismatch": "Parolă incorectă.",
+ "Volo.Abp.Identity:PasswordRequiresDigit": "Parolele trebuie să conţină cel puţin o cifră ('0'-'9').",
+ "Volo.Abp.Identity:PasswordRequiresLower": "Parolele trebuie să conţină cel puţin o literă ('a'-'z').",
+ "Volo.Abp.Identity:PasswordRequiresNonAlphanumeric": "Parolele trebuie să conţină cel puţin un caracter non alphanumeric.",
+ "Volo.Abp.Identity:PasswordRequiresUpper": "Parolele trebuie să conţină cel puţin o majusculă ('A'-'Z').",
+ "Volo.Abp.Identity:PasswordTooShort": "Parolele trebuie să aibă cel puţin {0} caractere.",
+ "Volo.Abp.Identity:RoleNotFound": "Rolul {0} nu există does not exist.",
+ "Volo.Abp.Identity:UserAlreadyHasPassword": "Utilizatorul şi-a setat deja o parolă.",
+ "Volo.Abp.Identity:UserAlreadyInRole": "Utilizatorul are deja rolul '{0}'.",
+ "Volo.Abp.Identity:UserLockedOut": "Utilizatorul este blocat.",
+ "Volo.Abp.Identity:UserLockoutNotEnabled": "Blocarea nu este activată pentru acest utilizator.",
+ "Volo.Abp.Identity:UserNameNotFound": "Utilizatorul {0} nu există.",
+ "Volo.Abp.Identity:UserNotInRole": "Utilizatorul nu are rolul '{0}'.",
+ "Volo.Abp.Identity:PasswordConfirmationFailed": "Parola nu este aceeaşi cu confirm password.",
+ "Volo.Abp.Identity:010001": "Nu vă puteţi şterge contul!",
+ "Volo.Abp.Identity:010002": "Nu pot fi setate mai mult de {MaxUserMembershipCount} unităţi organizaţionale pentru un utilizator!",
+ "Volo.Abp.Identity:010003": "Nu poate fi schimbată parola unui utilizator autentificat din exterior!",
+ "Volo.Abp.Identity:010004": "Există deja o unitate organizaţională cu numele {0}. Nu pot fi create două unităţi cu aceleaşi nume pe acelaşi nivel.",
+ "Volo.Abp.Identity:010005": "Rolurile statice nu pot fi redenumite.",
+ "Volo.Abp.Identity:010006": "Rolurile statice nu pot fi şterse.",
+ "Volo.Abp.Identity:010007": "Nu vă puteţi schimba setările de autentificare în doi paşi.",
+ "Volo.Abp.Identity:010008": "Nu este permisă modificarea setărilor autentificării în doi paşi.",
+ "Identity.OrganizationUnit.MaxUserMembershipCount": "Numărul maxim de unităţi organizaţionale permise pentru un utilizator",
+ "Permission:IdentityManagement": "Administrare identităţii",
+ "Permission:RoleManagement": "Administrare rolurilor",
+ "Permission:Create": "Creează",
+ "Permission:Edit": "Editează",
+ "Permission:Delete": "Şterge",
+ "Permission:ChangePermissions": "Schimbă permisiunile",
+ "Permission:UserManagement": "Administrarea utilizatorilor",
+ "Permission:UserLookup": "Căutarea utilizatorilor",
+ "DisplayName:Abp.Identity.Password.RequiredLength": "Lungimea necesară",
+ "DisplayName:Abp.Identity.Password.RequiredUniqueChars": "Numărul de caractere unice necesare",
+ "DisplayName:Abp.Identity.Password.RequireNonAlphanumeric": "Numărul de caractere non-alfanumerice",
+ "DisplayName:Abp.Identity.Password.RequireLowercase": "Numărul de caractere",
+ "DisplayName:Abp.Identity.Password.RequireUppercase": "Numărul de caractere cu majusculă",
+ "DisplayName:Abp.Identity.Password.RequireDigit": "Numărul de cifre",
+ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Activat pentru noi utilizatori",
+ "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Durata blocării (secunde)",
+ "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Numărul maxim de încercări de acces eşuate",
+ "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Solicită email confirmat",
+ "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Permite utilizatorilor să îşi confirme numărul de telefon",
+ "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Solicită număr de telefon confirmat",
+ "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Permite utilizatorilor să îşi schimbe numele de utilizator",
+ "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Permite utilizatorilor să îşi schimbe adresa de email",
+ "Description:Abp.Identity.Password.RequiredLength": "Lungimea minimă a parolei.",
+ "Description:Abp.Identity.Password.RequiredUniqueChars": "Numărul minim de caractere unice pe care trebuie să-l conţină parola.",
+ "Description:Abp.Identity.Password.RequireNonAlphanumeric": "Dacă parolele trebuie să conţină caractere non-alfanumerice.",
+ "Description:Abp.Identity.Password.RequireLowercase": "Dacă parolele trebuie să conţină un caracter ASCII.",
+ "Description:Abp.Identity.Password.RequireUppercase": "Dacă parolele trebuie să conţină un caracter ASCII cu majusculă.",
+ "Description:Abp.Identity.Password.RequireDigit": "Dacă parolele trebuie să conţină o cifră.",
+ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Dacă un utilizator nou poate fi blocat.",
+ "Description:Abp.Identity.Lockout.LockoutDuration": "Durata blocării unui utilizator când intervine blocarea.",
+ "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Numărul de accesări eşuate permise înainte de a bloca un utilizator, presupunând că blocarea este activată.",
+ "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Dacă o adresă de email confirmată este obligatorie pentru autentificare.",
+ "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Dacă numărul de telefon poate fi confirmată de către utilizator.",
+ "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Dacă un număr de telefon confirmat este oblicatoriu pentru autentificare.",
+ "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Dacă numele de utilizator poate fi actualizat de către utilizator.",
+ "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Dacă emailul poate fi actualizat de către utilizator."
+ }
+}
\ No newline at end of file
diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/LocalizationExtensions/ro-RO.json b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/LocalizationExtensions/ro-RO.json
new file mode 100644
index 0000000000..aabf36fad8
--- /dev/null
+++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/LocalizationExtensions/ro-RO.json
@@ -0,0 +1,7 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "Volo.Abp.Identity:PasswordTooShort": "Lungimea parolei trebuie să fie mai mare de {0} caractere.",
+ "Volo.Abp.Identity:PasswordRequiresNonAlphanumeric": "Parola trebuie să conţină cel puţin un caracter non-alfanumeric."
+ }
+}
\ No newline at end of file
diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/ro-RO.json b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/ro-RO.json
new file mode 100644
index 0000000000..7917e7118c
--- /dev/null
+++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain.Shared/Volo/Abp/IdentityServer/Localization/Resources/ro-RO.json
@@ -0,0 +1,15 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "Volo.IdentityServer:DuplicateIdentityResourceName": "Numele resursei de identitate există deja: {Name}",
+ "Volo.IdentityServer:DuplicateApiResourceName": "Numele resursei API există deja: {Name}",
+ "Volo.IdentityServer:DuplicateApiScopeName": "Api Scope name already exist: {Name}",
+ "Volo.IdentityServer:DuplicateClientId": "Id-ul de client există deja: {ClientId}",
+ "UserLockedOut": "Contul de utilizator a fost blocat din cauza încercărilor de autentificare eşuate. Vă rugăm să aşteptaţi puţin şi după să încercaţi din nou.",
+ "InvalidUserNameOrPassword": "Nume de utilizator sau parolă invalidă!",
+ "LoginIsNotAllowed": "Nu vă este permisă autentificarea! Trebuie să vă confirmaţi emailul/numărul de telefon.",
+ "InvalidUsername": "Nume de utilizator sau parolă invalidă!",
+ "InvalidAuthenticatorCode": "Cod de autentificare invalid!",
+ "TheTargetUserIsNotLinkedToYou": "Utilizatorul ţintă nu este conectat la dumneavoastră!"
+ }
+}
\ No newline at end of file
diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/ro-RO.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/ro-RO.json
new file mode 100644
index 0000000000..54b6cc1454
--- /dev/null
+++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/ro-RO.json
@@ -0,0 +1,10 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "Permissions": "Permisiuni",
+ "OnlyProviderPermissons": "Doar acest furnizor",
+ "All": "Toate",
+ "SelectAllInAllTabs": "Acordă toate permisiunile",
+ "SelectAllInThisTab": "Selectează toate"
+ }
+}
\ No newline at end of file
diff --git a/modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/DemoAppModule.cs b/modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/DemoAppModule.cs
index f20f081c33..82c1013f4a 100644
--- a/modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/DemoAppModule.cs
+++ b/modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/DemoAppModule.cs
@@ -87,6 +87,7 @@ namespace Volo.Abp.SettingManagement.DemoApp
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
options.Languages.Add(new LanguageInfo("fi", "fi", "Finnish"));
options.Languages.Add(new LanguageInfo("fr", "fr", "Français"));
+ options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română"));
options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi", "in"));
options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it"));
});
diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ro-RO.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ro-RO.json
new file mode 100644
index 0000000000..6fdf056170
--- /dev/null
+++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/ro-RO.json
@@ -0,0 +1,22 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "Settings": "Setări",
+ "SuccessfullySaved": "Salvat cu succes",
+ "Permission:SettingManagement": "Administrarea setărilor",
+ "Permission:Emailing": "Emailing",
+ "Menu:Emailing": "Emailing",
+ "SmtpHost": "Host",
+ "SmtpPort": "Port",
+ "SmtpUserName": "Nume de utilizator",
+ "SmtpPassword": "Parolă",
+ "SmtpDomain": "Domeniu",
+ "SmtpEnableSsl": "Activează SSL",
+ "SmtpUseDefaultCredentials": "Foloseşte credenţialele implicite",
+ "DefaultFromAddress": "Implicit de la adresa",
+ "DefaultFromDisplayName": "Implicit de la numele de afişare",
+ "Feature:SettingManagementGroup": "Administrarea setărilor",
+ "Feature:SettingManagementEnable": "Activează administrarea setărilor",
+ "Feature:SettingManagementEnableDescription": "Activează sistemul de administrare a setărilor în aplicaţie."
+ }
+}
\ No newline at end of file
diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/ro-RO.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/ro-RO.json
new file mode 100644
index 0000000000..70147d9921
--- /dev/null
+++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/ro-RO.json
@@ -0,0 +1,23 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "Menu:TenantManagement": "Administrarea clienţilor",
+ "Tenants": "Clienţi",
+ "NewTenant": "Client nou",
+ "TenantName": "Nume client",
+ "DisplayName:TenantName": "Nume client",
+ "TenantDeletionConfirmationMessage": "Clientul '{0}' va fi şters. Sunteţi sigur(ă)?",
+ "ConnectionStrings": "Connection Strings",
+ "DisplayName:DefaultConnectionString": "Connection String implicit",
+ "DisplayName:UseSharedDatabase": "Folosiţi baza de date partajată",
+ "ManageHostFeatures": "Administraţi caracteristicile de host",
+ "Permission:TenantManagement": "Administrarea clienţilor",
+ "Permission:Create": "Creează",
+ "Permission:Edit": "Editează",
+ "Permission:Delete": "Şterge",
+ "Permission:ManageConnectionStrings": "Administrează stringurile de conexiune",
+ "Permission:ManageFeatures": "Administrarea caracteristicilor",
+ "DisplayName:AdminEmailAddress": "Adresa de email admin",
+ "DisplayName:AdminPassword": "Parola admin"
+ }
+}
\ No newline at end of file
diff --git a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/AbpVirtualFileExplorerDemoAppModule.cs b/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/AbpVirtualFileExplorerDemoAppModule.cs
index e55beb118a..62f636ff35 100644
--- a/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/AbpVirtualFileExplorerDemoAppModule.cs
+++ b/modules/virtual-file-explorer/app/Volo.Abp.VirtualFileExplorer.DemoApp/AbpVirtualFileExplorerDemoAppModule.cs
@@ -25,6 +25,7 @@ namespace Volo.Abp.VirtualFileExplorer.DemoApp
options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi", "in"));
options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it"));
options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar"));
+ options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română"));
options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak"));
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
diff --git a/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/ro-RO.json b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/ro-RO.json
new file mode 100644
index 0000000000..67abc693a4
--- /dev/null
+++ b/modules/virtual-file-explorer/src/Volo.Abp.VirtualFileExplorer.Web/Localization/Resources/ro-RO.json
@@ -0,0 +1,14 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "VirtualFileExplorer" : "Explorator de fişiere virtuale",
+ "VirtualFileType" : "Tip fişier virtual",
+ "Menu:VirtualFileExplorer" : "Explorator de fişiere virtuale",
+ "LastUpdateTime" : "Data ultimei actualizări",
+ "VirtualFileName" : "Nume fişier virtual",
+ "FileContent" : "Conţinut fişier",
+ "Size" : "Mărimea",
+ "BackToRoot" : "Înapoi la rădăcină",
+ "EmptyFileInfoList" : "Nu există fişiere virtuale"
+ }
+}
\ No newline at end of file
diff --git a/npm/lerna.json b/npm/lerna.json
index baed8c1b51..25da1e62ac 100644
--- a/npm/lerna.json
+++ b/npm/lerna.json
@@ -1,5 +1,5 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"packages": [
"packs/*"
],
diff --git a/npm/ng-packs/packages/theme-shared/extensions/src/lib/adapters/date.adapter.ts b/npm/ng-packs/packages/theme-shared/extensions/src/lib/adapters/date.adapter.ts
index 4449bae024..17db36415e 100644
--- a/npm/ng-packs/packages/theme-shared/extensions/src/lib/adapters/date.adapter.ts
+++ b/npm/ng-packs/packages/theme-shared/extensions/src/lib/adapters/date.adapter.ts
@@ -7,9 +7,15 @@ export class DateAdapter extends NgbDateAdapter {
fromModel(value: string | Date): NgbDateStruct | null {
if (!value) return null;
- const date = new Date(value);
+ let date: Date;
- if (isNaN((date as unknown) as number)) return null;
+ if (typeof value === 'string') {
+ date = this.dateOf(value);
+ } else {
+ date = new Date(value);
+ }
+
+ if (isNaN(date as unknown as number)) return null;
return {
day: date.getDate(),
@@ -26,4 +32,9 @@ export class DateAdapter extends NgbDateAdapter {
return formattedDate;
}
+
+ protected dateOf(value: string): Date {
+ const dateUtc = new Date(Date.parse(value));
+ return new Date(dateUtc.getTime() + Math.abs(dateUtc.getTimezoneOffset() * 60000));
+ }
}
diff --git a/npm/ng-packs/packages/theme-shared/extensions/src/lib/components/extensible-table/extensible-table.component.html b/npm/ng-packs/packages/theme-shared/extensions/src/lib/components/extensible-table/extensible-table.component.html
index ebbece2277..81e2845ac0 100644
--- a/npm/ng-packs/packages/theme-shared/extensions/src/lib/components/extensible-table/extensible-table.component.html
+++ b/npm/ng-packs/packages/theme-shared/extensions/src/lib/components/extensible-table/extensible-table.component.html
@@ -1,6 +1,6 @@
implements OnChanges {
readonly trackByFn: TrackByFunction> = (_, item) => item.name;
+ hasAtLeastOnePermittedAction: boolean;
+
constructor(
@Inject(LOCALE_ID) private locale: string,
private config: ConfigStateService,
@@ -75,8 +78,14 @@ export class ExtensibleTableComponent implements OnChanges {
const extensions = injector.get(ExtensionsService);
const name = injector.get(EXTENSIONS_IDENTIFIER);
this.propList = extensions.entityProps.get(name).props;
- this.actionList = (extensions['entityActions'].get(name)
- .actions as unknown) as EntityActionList;
+ this.actionList = extensions['entityActions'].get(name)
+ .actions as unknown as EntityActionList;
+
+ const permissionService = injector.get(PermissionService);
+ this.hasAtLeastOnePermittedAction =
+ permissionService.filterItemsByPolicy(
+ this.actionList.toArray().map(action => ({ requiredPolicy: action.permission })),
+ ).length > 0;
this.setColumnWidths(DEFAULT_ACTIONS_COLUMN_WIDTH);
}
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts
index e33573438e..feb4ba5fd8 100644
--- a/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts
+++ b/npm/ng-packs/packages/theme-shared/src/lib/components/modal/modal.component.ts
@@ -1,4 +1,4 @@
-import { SubscriptionService } from '@abp/ng.core';
+import { SubscriptionService, uuid } from '@abp/ng.core';
import {
Component,
ContentChild,
@@ -6,13 +6,13 @@ import {
EventEmitter,
Inject,
Input,
+ isDevMode,
OnDestroy,
+ OnInit,
Optional,
Output,
TemplateRef,
- ViewChild,
- isDevMode,
- OnInit,
+ ViewChild
} from '@angular/core';
import { NgbModal, NgbModalOptions, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
import { fromEvent, Subject } from 'rxjs';
@@ -21,7 +21,7 @@ import { Confirmation } from '../../models/confirmation';
import { ConfirmationService } from '../../services/confirmation.service';
import { SUPPRESS_UNSAVED_CHANGES_WARNING } from '../../tokens/suppress-unsaved-changes-warning.token';
import { ButtonComponent } from '../button/button.component';
-import { DismissableModal, ModalRefService, ModalDismissMode } from './modal-ref.service';
+import { DismissableModal, ModalDismissMode, ModalRefService } from './modal-ref.service';
export type ModalSize = 'sm' | 'md' | 'lg' | 'xl';
@@ -105,10 +105,16 @@ export class ModalComponent implements OnInit, OnDestroy, DismissableModal {
destroy$ = new Subject();
+ modalIdentifier = `modal-${uuid()}`;
+
private toggle$ = new Subject();
+ get modalWindowRef() {
+ return document.querySelector(`ngb-modal-window.${this.modalIdentifier}`);
+ }
+
get isFormDirty(): boolean {
- return Boolean(document.querySelector('.modal-dialog .ng-dirty'));
+ return Boolean(this.modalWindowRef.querySelector('.ng-dirty'));
}
constructor(
@@ -160,7 +166,6 @@ export class ModalComponent implements OnInit, OnDestroy, DismissableModal {
this.modalRef = this.modal.open(this.modalContent, {
// TODO: set size to 'lg' when removed the size variable
size: this.size,
- windowClass: this.modalClass,
centered: this.centered,
keyboard: false,
scrollable: true,
@@ -171,6 +176,7 @@ export class ModalComponent implements OnInit, OnDestroy, DismissableModal {
return !this.visible;
},
...this.options,
+ windowClass: `${this.modalClass} ${this.options.windowClass || ''} ${this.modalIdentifier}`,
});
this.appear.emit();
@@ -193,6 +199,7 @@ export class ModalComponent implements OnInit, OnDestroy, DismissableModal {
.warn(
'AbpAccount::AreYouSureYouWantToCancelEditingWarningMessage',
'AbpAccount::AreYouSure',
+ { dismissible: false },
)
.subscribe((status: Confirmation.Status) => {
this.isConfirmationOpen = false;
@@ -206,7 +213,7 @@ export class ModalComponent implements OnInit, OnDestroy, DismissableModal {
}
listen() {
- fromEvent(document, 'keyup')
+ fromEvent(this.modalWindowRef, 'keyup')
.pipe(
takeUntil(this.destroy$),
debounceTime(150),
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/constants/styles.ts b/npm/ng-packs/packages/theme-shared/src/lib/constants/styles.ts
index 365d3adf52..669fc2cbae 100644
--- a/npm/ng-packs/packages/theme-shared/src/lib/constants/styles.ts
+++ b/npm/ng-packs/packages/theme-shared/src/lib/constants/styles.ts
@@ -149,7 +149,7 @@ export default `
.ngx-datatable.material {
box-shadow: none;
}
-ngb-typeahead-window {
+ngb-typeahead-window, ngb-typeahead-window.dropdown-menu {
max-height: 25em;
overflow-y: scroll !important;
z-index: 1050;
diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tests/modal.component.spec.ts b/npm/ng-packs/packages/theme-shared/src/lib/tests/modal.component.spec.ts
index 60c71b8e16..db6bcbc39c 100644
--- a/npm/ng-packs/packages/theme-shared/src/lib/tests/modal.component.spec.ts
+++ b/npm/ng-packs/packages/theme-shared/src/lib/tests/modal.component.spec.ts
@@ -157,8 +157,7 @@ describe('ModalComponent', () => {
it('should close with esc key', async () => {
await wait0ms();
-
- spectator.dispatchKeyboardEvent(document.body, 'keyup', 'Escape');
+ spectator.dispatchKeyboardEvent(spectator.component.modalWindowRef, 'keyup', 'Escape');
await wait300ms();
@@ -176,7 +175,7 @@ describe('ModalComponent', () => {
expect(disappearFn).not.toHaveBeenCalled();
});
- it('should not let window unload when form is dirty', async done => {
+ xit('should not let window unload when form is dirty', async done => {
fromEvent(window, 'beforeunload')
.pipe(
take(2),
diff --git a/npm/packs/anchor-js/package.json b/npm/packs/anchor-js/package.json
index 77745ef32b..f0cbe63040 100644
--- a/npm/packs/anchor-js/package.json
+++ b/npm/packs/anchor-js/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/anchor-js",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/core": "~4.4.0-rc.2",
+ "@abp/core": "~4.4.0",
"anchor-js": "^4.2.2"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/aspnetcore.components.server.basictheme/package.json b/npm/packs/aspnetcore.components.server.basictheme/package.json
index 090ab19cf3..47ea5c5a53 100644
--- a/npm/packs/aspnetcore.components.server.basictheme/package.json
+++ b/npm/packs/aspnetcore.components.server.basictheme/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/aspnetcore.components.server.basictheme",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/aspnetcore.components.server.theming": "~4.4.0-rc.2"
+ "@abp/aspnetcore.components.server.theming": "~4.4.0"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
}
diff --git a/npm/packs/aspnetcore.components.server.theming/package.json b/npm/packs/aspnetcore.components.server.theming/package.json
index 857168036e..6d81dce9f4 100644
--- a/npm/packs/aspnetcore.components.server.theming/package.json
+++ b/npm/packs/aspnetcore.components.server.theming/package.json
@@ -1,12 +1,12 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/aspnetcore.components.server.theming",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/bootstrap": "~4.4.0-rc.2",
- "@abp/font-awesome": "~4.4.0-rc.2"
+ "@abp/bootstrap": "~4.4.0",
+ "@abp/font-awesome": "~4.4.0"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
}
diff --git a/npm/packs/aspnetcore.mvc.ui.theme.basic/package.json b/npm/packs/aspnetcore.mvc.ui.theme.basic/package.json
index 79afa465ce..f668b90b2f 100644
--- a/npm/packs/aspnetcore.mvc.ui.theme.basic/package.json
+++ b/npm/packs/aspnetcore.mvc.ui.theme.basic/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/aspnetcore.mvc.ui.theme.basic",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/aspnetcore.mvc.ui.theme.shared": "~4.4.0-rc.2"
+ "@abp/aspnetcore.mvc.ui.theme.shared": "~4.4.0"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
}
diff --git a/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json b/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json
index 566d21d5e9..b67ca37768 100644
--- a/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json
+++ b/npm/packs/aspnetcore.mvc.ui.theme.shared/package.json
@@ -1,24 +1,24 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/aspnetcore.mvc.ui.theme.shared",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/aspnetcore.mvc.ui": "~4.4.0-rc.2",
- "@abp/bootstrap": "~4.4.0-rc.2",
- "@abp/bootstrap-datepicker": "~4.4.0-rc.2",
- "@abp/datatables.net-bs4": "~4.4.0-rc.2",
- "@abp/font-awesome": "~4.4.0-rc.2",
- "@abp/jquery-form": "~4.4.0-rc.2",
- "@abp/jquery-validation-unobtrusive": "~4.4.0-rc.2",
- "@abp/lodash": "~4.4.0-rc.2",
- "@abp/luxon": "~4.4.0-rc.2",
- "@abp/malihu-custom-scrollbar-plugin": "~4.4.0-rc.2",
- "@abp/select2": "~4.4.0-rc.2",
- "@abp/sweetalert": "~4.4.0-rc.2",
- "@abp/timeago": "~4.4.0-rc.2",
- "@abp/toastr": "~4.4.0-rc.2"
+ "@abp/aspnetcore.mvc.ui": "~4.4.0",
+ "@abp/bootstrap": "~4.4.0",
+ "@abp/bootstrap-datepicker": "~4.4.0",
+ "@abp/datatables.net-bs4": "~4.4.0",
+ "@abp/font-awesome": "~4.4.0",
+ "@abp/jquery-form": "~4.4.0",
+ "@abp/jquery-validation-unobtrusive": "~4.4.0",
+ "@abp/lodash": "~4.4.0",
+ "@abp/luxon": "~4.4.0",
+ "@abp/malihu-custom-scrollbar-plugin": "~4.4.0",
+ "@abp/select2": "~4.4.0",
+ "@abp/sweetalert": "~4.4.0",
+ "@abp/timeago": "~4.4.0",
+ "@abp/toastr": "~4.4.0"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
}
diff --git a/npm/packs/aspnetcore.mvc.ui/package-lock.json b/npm/packs/aspnetcore.mvc.ui/package-lock.json
index 6ce46cade0..a976f85cc6 100644
--- a/npm/packs/aspnetcore.mvc.ui/package-lock.json
+++ b/npm/packs/aspnetcore.mvc.ui/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "@abp/aspnetcore.mvc.ui",
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/npm/packs/aspnetcore.mvc.ui/package.json b/npm/packs/aspnetcore.mvc.ui/package.json
index 51a33e4984..52b2d98ff5 100644
--- a/npm/packs/aspnetcore.mvc.ui/package.json
+++ b/npm/packs/aspnetcore.mvc.ui/package.json
@@ -1,5 +1,5 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/aspnetcore.mvc.ui",
"publishConfig": {
"access": "public"
diff --git a/npm/packs/blogging/package.json b/npm/packs/blogging/package.json
index a54e6c9b69..95faa90760 100644
--- a/npm/packs/blogging/package.json
+++ b/npm/packs/blogging/package.json
@@ -1,14 +1,14 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/blogging",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/aspnetcore.mvc.ui.theme.shared": "~4.4.0-rc.2",
- "@abp/owl.carousel": "~4.4.0-rc.2",
- "@abp/prismjs": "~4.4.0-rc.2",
- "@abp/tui-editor": "~4.4.0-rc.2"
+ "@abp/aspnetcore.mvc.ui.theme.shared": "~4.4.0",
+ "@abp/owl.carousel": "~4.4.0",
+ "@abp/prismjs": "~4.4.0",
+ "@abp/tui-editor": "~4.4.0"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
}
diff --git a/npm/packs/bootstrap-datepicker/package.json b/npm/packs/bootstrap-datepicker/package.json
index a6cd0fd7af..9f49b7ec42 100644
--- a/npm/packs/bootstrap-datepicker/package.json
+++ b/npm/packs/bootstrap-datepicker/package.json
@@ -1,5 +1,5 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/bootstrap-datepicker",
"publishConfig": {
"access": "public"
diff --git a/npm/packs/bootstrap/package.json b/npm/packs/bootstrap/package.json
index 96d77e9781..21c3e04261 100644
--- a/npm/packs/bootstrap/package.json
+++ b/npm/packs/bootstrap/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/bootstrap",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/core": "~4.4.0-rc.2",
+ "@abp/core": "~4.4.0",
"bootstrap": "^4.6.0",
"bootstrap-v4-rtl": "4.6.0-1"
},
diff --git a/npm/packs/chart.js/package.json b/npm/packs/chart.js/package.json
index a34ad990d2..2f3d78c77d 100644
--- a/npm/packs/chart.js/package.json
+++ b/npm/packs/chart.js/package.json
@@ -1,5 +1,5 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/chart.js",
"publishConfig": {
"access": "public"
diff --git a/npm/packs/clipboard/package.json b/npm/packs/clipboard/package.json
index d45f4ca206..5fae1899ec 100644
--- a/npm/packs/clipboard/package.json
+++ b/npm/packs/clipboard/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/clipboard",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/core": "~4.4.0-rc.2",
+ "@abp/core": "~4.4.0",
"clipboard": "^2.0.6"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/cms-kit.admin/package.json b/npm/packs/cms-kit.admin/package.json
index 9e713c6c11..424163f7e5 100644
--- a/npm/packs/cms-kit.admin/package.json
+++ b/npm/packs/cms-kit.admin/package.json
@@ -1,14 +1,14 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/cms-kit.admin",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/jstree": "~4.4.0-rc.2",
- "@abp/slugify": "~4.4.0-rc.2",
- "@abp/tui-editor": "~4.4.0-rc.2",
- "@abp/uppy": "~4.4.0-rc.2"
+ "@abp/jstree": "~4.4.0",
+ "@abp/slugify": "~4.4.0",
+ "@abp/tui-editor": "~4.4.0",
+ "@abp/uppy": "~4.4.0"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
}
diff --git a/npm/packs/cms-kit.public/package.json b/npm/packs/cms-kit.public/package.json
index 1afa95b445..1c00cc3623 100644
--- a/npm/packs/cms-kit.public/package.json
+++ b/npm/packs/cms-kit.public/package.json
@@ -1,12 +1,12 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/cms-kit.public",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/highlight.js": "~4.4.0-rc.2",
- "@abp/star-rating-svg": "~4.4.0-rc.2"
+ "@abp/highlight.js": "~4.4.0",
+ "@abp/star-rating-svg": "~4.4.0"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
}
diff --git a/npm/packs/cms-kit/package.json b/npm/packs/cms-kit/package.json
index 418e06e6ba..5dae6eab82 100644
--- a/npm/packs/cms-kit/package.json
+++ b/npm/packs/cms-kit/package.json
@@ -1,12 +1,12 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/cms-kit",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/cms-kit.admin": "~4.4.0-rc.2",
- "@abp/cms-kit.public": "~4.4.0-rc.2"
+ "@abp/cms-kit.admin": "~4.4.0",
+ "@abp/cms-kit.public": "~4.4.0"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
}
diff --git a/npm/packs/codemirror/package.json b/npm/packs/codemirror/package.json
index 435d62c7b9..1478699908 100644
--- a/npm/packs/codemirror/package.json
+++ b/npm/packs/codemirror/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/codemirror",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/core": "~4.4.0-rc.2",
+ "@abp/core": "~4.4.0",
"codemirror": "^5.54.0"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/core/package.json b/npm/packs/core/package.json
index 623032ce9c..5a5b596a6c 100644
--- a/npm/packs/core/package.json
+++ b/npm/packs/core/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/core",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/utils": "^4.4.0-rc.2"
+ "@abp/utils": "^4.4.0"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
}
diff --git a/npm/packs/cropperjs/package.json b/npm/packs/cropperjs/package.json
index 03be5e3604..2dadf76e88 100644
--- a/npm/packs/cropperjs/package.json
+++ b/npm/packs/cropperjs/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/cropperjs",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/core": "~4.4.0-rc.2",
+ "@abp/core": "~4.4.0",
"cropperjs": "^1.5.7"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/datatables.net-bs4/package.json b/npm/packs/datatables.net-bs4/package.json
index 2e9b11fe61..d820edbf28 100644
--- a/npm/packs/datatables.net-bs4/package.json
+++ b/npm/packs/datatables.net-bs4/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/datatables.net-bs4",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/datatables.net": "~4.4.0-rc.2",
+ "@abp/datatables.net": "~4.4.0",
"datatables.net-bs4": "^1.10.21"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/datatables.net/package.json b/npm/packs/datatables.net/package.json
index c478bded22..d46790ef60 100644
--- a/npm/packs/datatables.net/package.json
+++ b/npm/packs/datatables.net/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/datatables.net",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/jquery": "~4.4.0-rc.2",
+ "@abp/jquery": "~4.4.0",
"datatables.net": "^1.10.21"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/docs/package.json b/npm/packs/docs/package.json
index 927601017c..da318cf566 100644
--- a/npm/packs/docs/package.json
+++ b/npm/packs/docs/package.json
@@ -1,15 +1,15 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/docs",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/anchor-js": "~4.4.0-rc.2",
- "@abp/clipboard": "~4.4.0-rc.2",
- "@abp/malihu-custom-scrollbar-plugin": "~4.4.0-rc.2",
- "@abp/popper.js": "~4.4.0-rc.2",
- "@abp/prismjs": "~4.4.0-rc.2"
+ "@abp/anchor-js": "~4.4.0",
+ "@abp/clipboard": "~4.4.0",
+ "@abp/malihu-custom-scrollbar-plugin": "~4.4.0",
+ "@abp/popper.js": "~4.4.0",
+ "@abp/prismjs": "~4.4.0"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
}
diff --git a/npm/packs/flag-icon-css/package.json b/npm/packs/flag-icon-css/package.json
index 425c723d26..e0d5a89228 100644
--- a/npm/packs/flag-icon-css/package.json
+++ b/npm/packs/flag-icon-css/package.json
@@ -1,5 +1,5 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/flag-icon-css",
"publishConfig": {
"access": "public"
diff --git a/npm/packs/font-awesome/package.json b/npm/packs/font-awesome/package.json
index 17c131129f..6e14dddfd8 100644
--- a/npm/packs/font-awesome/package.json
+++ b/npm/packs/font-awesome/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/font-awesome",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/core": "~4.4.0-rc.2",
+ "@abp/core": "~4.4.0",
"@fortawesome/fontawesome-free": "^5.13.0"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/highlight.js/package.json b/npm/packs/highlight.js/package.json
index 5612359bd6..a5e46b27bb 100644
--- a/npm/packs/highlight.js/package.json
+++ b/npm/packs/highlight.js/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/highlight.js",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/core": "~4.4.0-rc.2"
+ "@abp/core": "~4.4.0"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
}
diff --git a/npm/packs/jquery-form/package.json b/npm/packs/jquery-form/package.json
index ef98ed34f4..7d0c321ea1 100644
--- a/npm/packs/jquery-form/package.json
+++ b/npm/packs/jquery-form/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/jquery-form",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/jquery": "~4.4.0-rc.2",
+ "@abp/jquery": "~4.4.0",
"jquery-form": "^4.3.0"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/jquery-validation-unobtrusive/package.json b/npm/packs/jquery-validation-unobtrusive/package.json
index a29781c092..7b3d14a6ab 100644
--- a/npm/packs/jquery-validation-unobtrusive/package.json
+++ b/npm/packs/jquery-validation-unobtrusive/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/jquery-validation-unobtrusive",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/jquery-validation": "~4.4.0-rc.2",
+ "@abp/jquery-validation": "~4.4.0",
"jquery-validation-unobtrusive": "^3.2.11"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/jquery-validation/package.json b/npm/packs/jquery-validation/package.json
index afa61e23f5..563ebe16e6 100644
--- a/npm/packs/jquery-validation/package.json
+++ b/npm/packs/jquery-validation/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/jquery-validation",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/jquery": "~4.4.0-rc.2",
+ "@abp/jquery": "~4.4.0",
"jquery-validation": "^1.19.2"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/jquery/package.json b/npm/packs/jquery/package.json
index 8560d33631..3f45d55e31 100644
--- a/npm/packs/jquery/package.json
+++ b/npm/packs/jquery/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/jquery",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/core": "~4.4.0-rc.2",
+ "@abp/core": "~4.4.0",
"jquery": "~3.6.0"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/jstree/package.json b/npm/packs/jstree/package.json
index a4be68fe48..39cda21d9c 100644
--- a/npm/packs/jstree/package.json
+++ b/npm/packs/jstree/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/jstree",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/jquery": "~4.4.0-rc.2",
+ "@abp/jquery": "~4.4.0",
"jstree": "^3.3.9"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/lodash/package.json b/npm/packs/lodash/package.json
index 45499c33c8..24865bfae5 100644
--- a/npm/packs/lodash/package.json
+++ b/npm/packs/lodash/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/lodash",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/core": "~4.4.0-rc.2",
+ "@abp/core": "~4.4.0",
"lodash": "^4.17.15"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/luxon/package.json b/npm/packs/luxon/package.json
index b782857c72..3958a0ecf8 100644
--- a/npm/packs/luxon/package.json
+++ b/npm/packs/luxon/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/luxon",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/core": "~4.4.0-rc.2",
+ "@abp/core": "~4.4.0",
"luxon": "^1.24.1"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/malihu-custom-scrollbar-plugin/package.json b/npm/packs/malihu-custom-scrollbar-plugin/package.json
index 1429410107..9c0d50c679 100644
--- a/npm/packs/malihu-custom-scrollbar-plugin/package.json
+++ b/npm/packs/malihu-custom-scrollbar-plugin/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/malihu-custom-scrollbar-plugin",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/core": "~4.4.0-rc.2",
+ "@abp/core": "~4.4.0",
"malihu-custom-scrollbar-plugin": "^3.1.5"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/markdown-it/package.json b/npm/packs/markdown-it/package.json
index e18bf9c050..8e9f1ec04a 100644
--- a/npm/packs/markdown-it/package.json
+++ b/npm/packs/markdown-it/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/markdown-it",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/core": "~4.4.0-rc.2",
+ "@abp/core": "~4.4.0",
"markdown-it": "^11.0.0"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/owl.carousel/package.json b/npm/packs/owl.carousel/package.json
index 72926bef3e..4c303bbc09 100644
--- a/npm/packs/owl.carousel/package.json
+++ b/npm/packs/owl.carousel/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/owl.carousel",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/core": "~4.4.0-rc.2",
+ "@abp/core": "~4.4.0",
"owl.carousel": "^2.3.4"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/popper.js/package.json b/npm/packs/popper.js/package.json
index 0d99ac6255..cf19cf4ae0 100644
--- a/npm/packs/popper.js/package.json
+++ b/npm/packs/popper.js/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/popper.js",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/core": "~4.4.0-rc.2",
+ "@abp/core": "~4.4.0",
"popper.js": "^1.16.0"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/prismjs/package.json b/npm/packs/prismjs/package.json
index 5665e5b19c..d5f5085511 100644
--- a/npm/packs/prismjs/package.json
+++ b/npm/packs/prismjs/package.json
@@ -1,12 +1,12 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/prismjs",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/clipboard": "~4.4.0-rc.2",
- "@abp/core": "~4.4.0-rc.2",
+ "@abp/clipboard": "~4.4.0",
+ "@abp/core": "~4.4.0",
"prismjs": "^1.20.0"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/select2/package.json b/npm/packs/select2/package.json
index 8a73a3bb53..7147f60d4d 100644
--- a/npm/packs/select2/package.json
+++ b/npm/packs/select2/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/select2",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/core": "~4.4.0-rc.2",
+ "@abp/core": "~4.4.0",
"select2": "^4.0.13"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/signalr/package.json b/npm/packs/signalr/package.json
index 0f09044c71..91ac801df5 100644
--- a/npm/packs/signalr/package.json
+++ b/npm/packs/signalr/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/signalr",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/core": "~4.4.0-rc.2",
+ "@abp/core": "~4.4.0",
"@microsoft/signalr": "~3.1.5"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/slugify/package.json b/npm/packs/slugify/package.json
index 1085976a4a..13eeb99a77 100644
--- a/npm/packs/slugify/package.json
+++ b/npm/packs/slugify/package.json
@@ -1,5 +1,5 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/slugify",
"publishConfig": {
"access": "public"
diff --git a/npm/packs/star-rating-svg/package.json b/npm/packs/star-rating-svg/package.json
index c900f62112..20743beabf 100644
--- a/npm/packs/star-rating-svg/package.json
+++ b/npm/packs/star-rating-svg/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/star-rating-svg",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/jquery": "~4.4.0-rc.2",
+ "@abp/jquery": "~4.4.0",
"star-rating-svg": "^3.5.0"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/sweetalert/package.json b/npm/packs/sweetalert/package.json
index 12ba1349dd..62d0015052 100644
--- a/npm/packs/sweetalert/package.json
+++ b/npm/packs/sweetalert/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/sweetalert",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/core": "~4.4.0-rc.2",
+ "@abp/core": "~4.4.0",
"sweetalert": "^2.1.2"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/timeago/package.json b/npm/packs/timeago/package.json
index c1df5253e8..cd4e9a56b3 100644
--- a/npm/packs/timeago/package.json
+++ b/npm/packs/timeago/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/timeago",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/jquery": "~4.4.0-rc.2",
+ "@abp/jquery": "~4.4.0",
"timeago": "^1.6.7"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/toastr/package.json b/npm/packs/toastr/package.json
index 32180de445..14f22f37aa 100644
--- a/npm/packs/toastr/package.json
+++ b/npm/packs/toastr/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/toastr",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/jquery": "~4.4.0-rc.2",
+ "@abp/jquery": "~4.4.0",
"toastr": "^2.1.4"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/tui-editor/package.json b/npm/packs/tui-editor/package.json
index da956d273e..6490b7c147 100644
--- a/npm/packs/tui-editor/package.json
+++ b/npm/packs/tui-editor/package.json
@@ -1,14 +1,14 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/tui-editor",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/codemirror": "~4.4.0-rc.2",
- "@abp/highlight.js": "~4.4.0-rc.2",
- "@abp/jquery": "~4.4.0-rc.2",
- "@abp/markdown-it": "~4.4.0-rc.2",
+ "@abp/codemirror": "~4.4.0",
+ "@abp/highlight.js": "~4.4.0",
+ "@abp/jquery": "~4.4.0",
+ "@abp/markdown-it": "~4.4.0",
"@toast-ui/editor": "^2.5.1"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/uppy/package.json b/npm/packs/uppy/package.json
index 62f93f3ae5..e5d0f70799 100644
--- a/npm/packs/uppy/package.json
+++ b/npm/packs/uppy/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/uppy",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/core": "~4.4.0-rc.2",
+ "@abp/core": "~4.4.0",
"uppy": "^1.16.1"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/utils/package.json b/npm/packs/utils/package.json
index 2bb50560a6..92827f6847 100644
--- a/npm/packs/utils/package.json
+++ b/npm/packs/utils/package.json
@@ -1,6 +1,6 @@
{
"name": "@abp/utils",
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"scripts": {
"prepublish": "yarn install --ignore-scripts && node prepublish.js",
"ng": "ng",
diff --git a/npm/packs/vee-validate/package.json b/npm/packs/vee-validate/package.json
index 40e2ca0614..162e44e351 100644
--- a/npm/packs/vee-validate/package.json
+++ b/npm/packs/vee-validate/package.json
@@ -1,11 +1,11 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/vee-validate",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/vue": "~4.4.0-rc.2",
+ "@abp/vue": "~4.4.0",
"vee-validate": "~3.4.4"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
diff --git a/npm/packs/virtual-file-explorer/package.json b/npm/packs/virtual-file-explorer/package.json
index 27b2539e9b..b27984c1a4 100644
--- a/npm/packs/virtual-file-explorer/package.json
+++ b/npm/packs/virtual-file-explorer/package.json
@@ -1,12 +1,12 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/virtual-file-explorer",
"publishConfig": {
"access": "public"
},
"dependencies": {
- "@abp/clipboard": "~4.4.0-rc.2",
- "@abp/prismjs": "~4.4.0-rc.2"
+ "@abp/clipboard": "~4.4.0",
+ "@abp/prismjs": "~4.4.0"
},
"gitHead": "bb4ea17d5996f01889134c138d00b6c8f858a431"
}
diff --git a/npm/packs/vue/package.json b/npm/packs/vue/package.json
index 709a73507f..d146ed3f37 100644
--- a/npm/packs/vue/package.json
+++ b/npm/packs/vue/package.json
@@ -1,5 +1,5 @@
{
- "version": "4.4.0-rc.2",
+ "version": "4.4.0",
"name": "@abp/vue",
"publishConfig": {
"access": "public"
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyCompanyName.MyProjectName.Blazor.Server.Tiered.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyCompanyName.MyProjectName.Blazor.Server.Tiered.csproj
index 1c88aabcd5..aa0170cca4 100644
--- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyCompanyName.MyProjectName.Blazor.Server.Tiered.csproj
+++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyCompanyName.MyProjectName.Blazor.Server.Tiered.csproj
@@ -14,8 +14,8 @@
-
-
+
+
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyProjectNameBlazorModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyProjectNameBlazorModule.cs
index fac76131e3..6cfddfd272 100644
--- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyProjectNameBlazorModule.cs
+++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyProjectNameBlazorModule.cs
@@ -221,6 +221,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Tiered
options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi", "in"));
options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it"));
options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
+ options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română"));
options.Languages.Add(new LanguageInfo("ru", "ru", "Русский"));
options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak"));
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/gulpfile.js b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/gulpfile.js
deleted file mode 100644
index f7ebc78f23..0000000000
--- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/gulpfile.js
+++ /dev/null
@@ -1,9 +0,0 @@
-"use strict";
-
-var gulp = require("gulp"),
- path = require('path'),
- copyResources = require('./node_modules/@abp/aspnetcore.mvc.ui/gulp/copy-resources.js');
-
-exports.default = function(){
- return copyResources(path.resolve('./'));
-};
\ No newline at end of file
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj
index 362a1068f2..b83e86df6f 100644
--- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj
+++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj
@@ -14,8 +14,8 @@
-
-
+
+
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyProjectNameBlazorModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyProjectNameBlazorModule.cs
index a0f1537fb5..b0d6cf87ce 100644
--- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyProjectNameBlazorModule.cs
+++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyProjectNameBlazorModule.cs
@@ -182,6 +182,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Server
options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi", "in"));
options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it"));
options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
+ options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română"));
options.Languages.Add(new LanguageInfo("ru", "ru", "Русский"));
options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak"));
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/gulpfile.js b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/gulpfile.js
deleted file mode 100644
index f7ebc78f23..0000000000
--- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/gulpfile.js
+++ /dev/null
@@ -1,9 +0,0 @@
-"use strict";
-
-var gulp = require("gulp"),
- path = require('path'),
- copyResources = require('./node_modules/@abp/aspnetcore.mvc.ui/gulp/copy-resources.js');
-
-exports.default = function(){
- return copyResources(path.resolve('./'));
-};
\ No newline at end of file
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj
index 74e8f8ca07..0bde45f899 100644
--- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj
+++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj
@@ -10,8 +10,8 @@
-
-
+
+
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/ro-RO.json b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/ro-RO.json
new file mode 100644
index 0000000000..1fe560196e
--- /dev/null
+++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/ro-RO.json
@@ -0,0 +1,8 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "Menu:Home": "Acasă",
+ "Welcome": "Bun venit",
+ "LongWelcomeMessage": "Bun venit la aplicaţie. Acesta este un proiect de pornire bazat pe framework-ul ABP. Pentru mai multe informaţii, vizitaţi, visit abp.io."
+ }
+}
\ No newline at end of file
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs
index f6473f92e1..9861a1becd 100644
--- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs
+++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs
@@ -132,6 +132,7 @@ namespace MyCompanyName.MyProjectName
options.Languages.Add(new LanguageInfo("fr", "fr", "Français"));
options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi", "in"));
options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it"));
+ options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română"));
options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar"));
options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
options.Languages.Add(new LanguageInfo("ru", "ru", "Русский"));
@@ -191,12 +192,6 @@ namespace MyCompanyName.MyProjectName
}
app.UseAbpRequestLocalization();
-
- if (!env.IsDevelopment())
- {
- app.UseErrorPage();
- }
-
app.UseCorrelationId();
app.UseStaticFiles();
app.UseRouting();
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs
index 29e0877ce3..87f4783a44 100644
--- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs
+++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs
@@ -161,6 +161,7 @@ namespace MyCompanyName.MyProjectName
options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it"));
options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar"));
options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
+ options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română"));
options.Languages.Add(new LanguageInfo("ru", "ru", "Русский"));
options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak"));
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/gulpfile.js b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/gulpfile.js
deleted file mode 100644
index f7ebc78f23..0000000000
--- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/gulpfile.js
+++ /dev/null
@@ -1,9 +0,0 @@
-"use strict";
-
-var gulp = require("gulp"),
- path = require('path'),
- copyResources = require('./node_modules/@abp/aspnetcore.mvc.ui/gulp/copy-resources.js');
-
-exports.default = function(){
- return copyResources(path.resolve('./'));
-};
\ No newline at end of file
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs
index 5e76b19724..8cbb91d486 100644
--- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs
+++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs
@@ -68,6 +68,7 @@ namespace MyCompanyName.MyProjectName
options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it"));
options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar"));
options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
+ options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română"));
options.Languages.Add(new LanguageInfo("ru", "ru", "Русский"));
options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak"));
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/gulpfile.js b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/gulpfile.js
deleted file mode 100644
index 5dcf4c5c6f..0000000000
--- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.IdentityServer/gulpfile.js
+++ /dev/null
@@ -1,9 +0,0 @@
-"use strict";
-
-var gulp = require("gulp"),
- path = require('path'),
- copyResources = require('./node_modules/@abp/aspnetcore.mvc.ui/gulp/copy-resources.js');
-
-exports.default = function(){
- return copyResources(path.resolve('./'));
-};
\ No newline at end of file
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/gulpfile.js b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/gulpfile.js
deleted file mode 100644
index f7ebc78f23..0000000000
--- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/gulpfile.js
+++ /dev/null
@@ -1,9 +0,0 @@
-"use strict";
-
-var gulp = require("gulp"),
- path = require('path'),
- copyResources = require('./node_modules/@abp/aspnetcore.mvc.ui/gulp/copy-resources.js');
-
-exports.default = function(){
- return copyResources(path.resolve('./'));
-};
\ No newline at end of file
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs
index 8ab982a275..67af34b073 100644
--- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs
+++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs
@@ -170,6 +170,7 @@ namespace MyCompanyName.MyProjectName.Web
options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi", "in"));
options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it"));
options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
+ options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română"));
options.Languages.Add(new LanguageInfo("ru", "ru", "Русский"));
options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak"));
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/gulpfile.js b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/gulpfile.js
deleted file mode 100644
index f7ebc78f23..0000000000
--- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/gulpfile.js
+++ /dev/null
@@ -1,9 +0,0 @@
-"use strict";
-
-var gulp = require("gulp"),
- path = require('path'),
- copyResources = require('./node_modules/@abp/aspnetcore.mvc.ui/gulp/copy-resources.js');
-
-exports.default = function(){
- return copyResources(path.resolve('./'));
-};
\ No newline at end of file
diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj
index 9beaac9818..6adc30e7f6 100644
--- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj
+++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Host/MyCompanyName.MyProjectName.Blazor.Host.csproj
@@ -8,8 +8,8 @@
-
-
+
+
diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyCompanyName.MyProjectName.Blazor.Server.Host.csproj b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyCompanyName.MyProjectName.Blazor.Server.Host.csproj
index 923814f92b..098b542d4f 100644
--- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyCompanyName.MyProjectName.Blazor.Server.Host.csproj
+++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyCompanyName.MyProjectName.Blazor.Server.Host.csproj
@@ -13,8 +13,8 @@
-
-
+
+
diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyProjectNameBlazorHostModule.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyProjectNameBlazorHostModule.cs
index 9f5fd42006..a288e815c9 100644
--- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyProjectNameBlazorHostModule.cs
+++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyProjectNameBlazorHostModule.cs
@@ -168,6 +168,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host
options.Languages.Add(new LanguageInfo("it", "it", "Italian", "it"));
options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar"));
options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português (Brasil)"));
+ options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română"));
options.Languages.Add(new LanguageInfo("ru", "ru", "Русский"));
options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak"));
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/gulpfile.js b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/gulpfile.js
deleted file mode 100644
index f7ebc78f23..0000000000
--- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/gulpfile.js
+++ /dev/null
@@ -1,9 +0,0 @@
-"use strict";
-
-var gulp = require("gulp"),
- path = require('path'),
- copyResources = require('./node_modules/@abp/aspnetcore.mvc.ui/gulp/copy-resources.js');
-
-exports.default = function(){
- return copyResources(path.resolve('./'));
-};
\ No newline at end of file
diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs
index d9ab50d83a..80b40a0cca 100644
--- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs
+++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs
@@ -103,6 +103,7 @@ namespace MyCompanyName.MyProjectName
options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it"));
options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar"));
options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
+ options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română"));
options.Languages.Add(new LanguageInfo("ru", "ru", "Русский"));
options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak"));
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
@@ -164,7 +165,6 @@ namespace MyCompanyName.MyProjectName
}
else
{
- app.UseErrorPage();
app.UseHsts();
}
diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs
index 0829a70a7e..447c4e979a 100644
--- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs
+++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs
@@ -113,13 +113,14 @@ namespace MyCompanyName.MyProjectName
options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it"));
options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar"));
options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
+ options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română"));
options.Languages.Add(new LanguageInfo("ru", "ru", "Русский"));
options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak"));
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文"));
options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch"));
- options.Languages.Add(new LanguageInfo("es", "es", "Español"s));
+ options.Languages.Add(new LanguageInfo("es", "es", "Español"));
});
Configure(options =>
diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/gulpfile.js b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/gulpfile.js
deleted file mode 100644
index 5dcf4c5c6f..0000000000
--- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/gulpfile.js
+++ /dev/null
@@ -1,9 +0,0 @@
-"use strict";
-
-var gulp = require("gulp"),
- path = require('path'),
- copyResources = require('./node_modules/@abp/aspnetcore.mvc.ui/gulp/copy-resources.js');
-
-exports.default = function(){
- return copyResources(path.resolve('./'));
-};
\ No newline at end of file
diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/gulpfile.js b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/gulpfile.js
deleted file mode 100644
index f7ebc78f23..0000000000
--- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/gulpfile.js
+++ /dev/null
@@ -1,9 +0,0 @@
-"use strict";
-
-var gulp = require("gulp"),
- path = require('path'),
- copyResources = require('./node_modules/@abp/aspnetcore.mvc.ui/gulp/copy-resources.js');
-
-exports.default = function(){
- return copyResources(path.resolve('./'));
-};
\ No newline at end of file
diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs
index 57bd71c2eb..d4b6d3f310 100644
--- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs
+++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs
@@ -110,6 +110,7 @@ namespace MyCompanyName.MyProjectName
options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it"));
options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar"));
options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português (Brasil)"));
+ options.Languages.Add(new LanguageInfo("ro-RO", "ro-RO", "Română"));
options.Languages.Add(new LanguageInfo("ru", "ru", "Русский"));
options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak"));
options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/gulpfile.js b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/gulpfile.js
deleted file mode 100644
index 5dcf4c5c6f..0000000000
--- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/gulpfile.js
+++ /dev/null
@@ -1,9 +0,0 @@
-"use strict";
-
-var gulp = require("gulp"),
- path = require('path'),
- copyResources = require('./node_modules/@abp/aspnetcore.mvc.ui/gulp/copy-resources.js');
-
-exports.default = function(){
- return copyResources(path.resolve('./'));
-};
\ No newline at end of file
diff --git a/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/ro-RO.json b/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/ro-RO.json
new file mode 100644
index 0000000000..18086dbf04
--- /dev/null
+++ b/templates/module/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/ro-RO.json
@@ -0,0 +1,7 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "MyAccount": "Contul meu",
+ "SamplePageMessage": "Un exemplu de pagină pentru modululul MyProjectName"
+ }
+}
\ No newline at end of file