diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json
index 541d1eaa62..de2f917fc9 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json
@@ -407,6 +407,8 @@
"ExportToExcel": "Export to Excel",
"OverallTotalPrice": "Overall Total Price",
"OverallDiscountPrice": "Overall Discount Price",
- "OverallDiscountText": "Overall Discount Text"
+ "OverallDiscountText": "Overall Discount Text",
+ "SelectReport": "- Select Report -",
+ "NoDataAvailable": "No data available"
}
}
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json
index 4b883b430c..0dcd69bbd8 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Base/Localization/Resources/zh-Hans.json
@@ -179,6 +179,10 @@
"Post": "邮政",
"ExploreTheContentsCreatedByTheCoreABPTeamAndTheABPCommunity": "探索核心 ABP 团队和 ABP 社区创建的内容。",
"WelcomeFallCampaign": "欢迎秋季活动!",
- "GiveAwayForNewPurchases": "新购买将赠送应用程序开发课堂培训!"
+ "GiveAwayForNewPurchases": "新购买将赠送应用程序开发课堂培训!",
+ "BlackFriday": "黑色 星期五",
+ "ValidForExistingCustomers": "也适用于
现有用户!",
+ "CampaignBetweenDates": "从 {0}
至 {1}",
+ "SaveUpTo": "最多节省 至${0}K"
}
-}
\ No newline at end of file
+}
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
index 4f017817dd..0aeadf3f43 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
@@ -747,7 +747,7 @@
"SeeWhatToldAboutAbpCommercial": "See what has been told about ABP Commercial and write your thoughts if you want.",
"BlazoriseLicense": "Do we need to buy Blazorise license?",
"BlazoriseLicenseExplanation": "We have an agreement between Volosoft and Megabit, with this agreement Blazorise license is bundled with ABP Commercial products therefore our customers do not need to purchase an extra Blazorise license.",
- "ExtendPaymentInfoSection_DeveloperPrice": "{0} x Developer(s) Price",
+ "ExtendPaymentInfoSection_DeveloperPrice": "{0}x Additional Developer(s)",
"ExtendPaymentInfoSection_DiscountRate": "Discount {0}%",
"TotalNetPrice": "Total Net Price",
"EFCore": "Entity Framework Core",
@@ -804,6 +804,7 @@
"UpgradePaymentInfoSection_LicenseRenewalPrice": "License renewal",
"Total": "Total",
"SupportPolicyFaqTitle": "What is your support policy?",
- "SupportPolicyFaqExplanation": "We do support only the active and the previous major version. We do not guarantee a patch release for the 3rd and older major versions. For example, if the active version is 7.0.0, we will release patch releases for both 6.x.x and 7.x.x. Besides, we provide support only for ABP Framework and ABP Commercial related issues. That means no support is given for the 3rd party applications, cloud services and other peripheral libraries used by ABP products. We will use commercially reasonable efforts to provide our customers with technical support during \"Volosoft Bilisim A.S\"s official business hours. On the other hand, we do not commit to a service-level agreement (SLA) response time, but we will try to respond to the technical issues as quickly as possible within our official working hours. Unless a special agreement is made with the customer, we only provide support at https://support.abp.io. We also have private email support, which is only available to Enterprise License holders."
+ "SupportPolicyFaqExplanation": "We do support only the active and the previous major version. We do not guarantee a patch release for the 3rd and older major versions. For example, if the active version is 7.0.0, we will release patch releases for both 6.x.x and 7.x.x. Besides, we provide support only for ABP Framework and ABP Commercial related issues. That means no support is given for the 3rd party applications, cloud services and other peripheral libraries used by ABP products. We will use commercially reasonable efforts to provide our customers with technical support during \"Volosoft Bilisim A.S\"s official business hours. On the other hand, we do not commit to a service-level agreement (SLA) response time, but we will try to respond to the technical issues as quickly as possible within our official working hours. Unless a special agreement is made with the customer, we only provide support at https://support.abp.io. We also have private email support, which is only available to Enterprise License holders.",
+ "TotalDevelopers": "Total {0} developer(s)"
}
}
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json
index 155218939a..8d1c67efae 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json
@@ -745,9 +745,9 @@
"Testimonial_ShortDescription_4": "Az ABP Commercial volt a legjobban megfelelő az igényeinknek.",
"OnlineReviewersOnAbpCommercial": "Online vélemények az ABP Commercial-ról",
"SeeWhatToldAboutAbpCommercial": "Tekintse meg, mit mondtak az ABP Commercialról, és írja le gondolatait, ha akarja.",
- "ExtendPaymentInfoSection_DeveloperPrice": "{0} x Developer(s) Price",
+ "ExtendPaymentInfoSection_DeveloperPrice": "{0}x További Fejlesztő(k)",
"ExtendPaymentInfoSection_DiscountRate": "Kedvezmény: {0}%",
"TotalNetPrice": "Total Net Price",
"BlackFridayDiscount": "Black Friday Kedvezmény"
}
-}
\ No newline at end of file
+}
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json
index 0e4a694652..bce1fc11d7 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json
@@ -737,11 +737,73 @@
"EmailVerificationMailNotSent": "电子邮件验证邮件不能发送。",
"GetConfirmationEmail": "点击这里获取确认邮件 如果你还没有收到。",
"WhichLicenseTypeYouAreInterestedIn": "你感兴趣的许可证类型是什么?",
+ "DontTakeOurWordForIt": "不要相信我们的话......",
+ "ReadAbpCommercialUsersWantYouToKnow": "阅读 ABP Commercial 用户希望您了解到的内容",
+ "Testimonial_ShortDescription_1": "ABP 的模块化使得团队能够及时交付项目。",
+ "Testimonial_ShortDescription_2": "比以前更快地构建新功能。",
+ "Testimonial_ShortDescription_3": "我们从开箱即用的功能开始,只专注于我们真正需要编写的内容。",
+ "Testimonial_ShortDescription_4": "ABP Commercial 最适合我们的需求。",
+ "OnlineReviewersOnAbpCommercial": "ABP Commercial 在线评论",
+ "SeeWhatToldAboutAbpCommercial": "查看关于 ABP Comemrcial 的报道,并根据需要写下您的想法。",
"BlazoriseLicense": "我们是否需要购买Blazorise许可证?",
"BlazoriseLicenseExplanation": "我公司Volosoft和公司Megabit之间有合作协议,根据此协议,购买将同时包含了Blazorise许可证与ABP商业产品,因此我们的客户不需要再额外购买Blazorise许可证。",
- "ExtendPaymentInfoSection_DeveloperPrice": "{0} x 开发者价格",
+ "ExtendPaymentInfoSection_DeveloperPrice": "{0}x 额外的 开发者价格",
"ExtendPaymentInfoSection_DiscountRate": "折扣 {0}%",
"TotalNetPrice": "总净价",
- "BlackFridayDiscount": "黑色星期五折扣"
+ "EFCore": "实体框架核心",
+ "All": "全部",
+ "Mvc": "MVC",
+ "DataBaseProvider": "数据提供者",
+ "UIFramework": "UI 框架",
+ "LeptonXThemeForDashboard": "管理仪表板的 LeptonX 主题",
+ "AbpPlatform": "ABP 平台",
+ "YouDeserveGoodUXUI": "您值得拥有良好的用户界面和更好的用户体验。 ABP 的 LeptonX Theme 就是为它服务的。",
+ "ViewLiveDemo": "查看在线主题演示",
+ "GetLeptonX": "立即获取 LeptonX",
+ "SeeLeptonXDocumentation": "请参阅 LeptonX 文档",
+ "SimplifiedMenu": "简化菜单",
+ "SimplifiedMenuDescription": "您可以通过过滤菜单轻松找到您要查找的页面",
+ "YourFavoritePages": "您最喜欢的页面触手可及",
+ "YourFavoritePagesDescription": "通过单击页面右上角的星形图标,可以轻松地将页面添加到收藏夹或从中删除。",
+ "BreadCrumbs": "用于无缝切换的页面路径导航",
+ "BreadCrumbsDescription": "使用页面路径导航,您可以一键切换到同一级别的页面,即使是左侧菜单关闭,它适用于平板电脑和移动设备响应!",
+ "YourMenu": "随心所欲的菜单",
+ "YourMenuDescription": "根据需要自定义用户菜单上可直接单击的图标和下拉框。 用户菜单可完全根据您的需要定制",
+ "RtlSupport": "对您的语言的 RTL 支持",
+ "RtlSupportDescription": "LeptonX 主题支持您的语言的 RTL。 语言选项位于设置菜单中,供您更改语言。",
+ "YourColors": "您在管理仪表板 UI 上的颜色",
+ "YourColorsDescription": "LeptonX 主题根据您的系统偏好工作,并具有仪表板浅色主题、仪表板深色主题和仪表板半深色主题选项。",
+ "ArrangeContentWidth": "轻松安排您的内容宽度",
+ "ArrangeContentWidthDescription": "轻松更改内容区域的宽度。",
+ "LeptonXCompatibleWith": "与LeptonX主题兼容",
+ "MobileResponsiveTemplate": "移动设备响应模板",
+ "MobileResponsiveTemplateDescription1": "从您喜欢的任何设备访问您的LeptonX管理仪表板。",
+ "MobileResponsiveTemplateDescription2": "它是为您设计的,在您的每一个设备上都可以轻松使用。它可以在移动设备和平板电脑上响应。",
+ "TopMenuLayoutOption": "菜单顶部布局选项",
+ "TopMenuLayoutOptionDescription1": "如果你想设置你的网站与相同的管理仪表板,通过使用LeptonX主题是可以做到的!",
+ "TopMenuLayoutOptionDescription2": "只需尝试LeptonX顶部菜单布局,就可以实现!",
+ "EasilyCustomizable": "易于定制您的品牌颜色",
+ "EasilyCustomizableDescription1": "您可以仅使用几个SCSS变量自定义LeptonX主题。没有重写,没有额外的CSS加载!",
+ "EasilyCustomizableDescription2": "使用LeptonX,您可以随意安排您的管理仪表板。",
+ "IndependentLayout": "独立的布局和内容区域",
+ "IndependentLayoutDescription1": "LeptonX 的布局基础设施的设计与内容完全分开。",
+ "IndependentLayoutDescription2": "这意味着您可以根据需要使用 Bootstrap 以外的内容结构自由设计您的项目。",
+ "MostUsedLibraries": "与 LeptonX 集成的最常用的库",
+ "MostUsedLibrariesDescription1": "LeptonX包含您最常用的库。它允许您使用库,如 ApexCharts, DataTables, DropZone, FullCalender, JSTree, Select2, Toastr 并毫不费力。",
+ "MostUsedLibrariesDescription2": "LeptonX还支持MVC Angular和Blazor特定的库。",
+ "CreateAndCustomize": "使用LeptonX自定义页面在几秒钟内创建和自定义所需的页面",
+ "CreateAndCustomizeDescription": "通过使用LeptonX Theme,您还可以访问许多预先制作的html页面。这些包括许多页面,如登录页面,博客,常见问题解答,订阅列表,发票,定价,文件管理。",
+ "LeptonThemeForAdmin": "为您的管理仪表板的Lepton主题",
+ "LeptonThemeForAdminDescription": "Lepton主题仍然可用,并将保持。如果您想以Lepton Theme用户的身份切换到LeptonX Theme,您可以查看文档了解如何操作。",
+ "LeptonCompatibleWith": "Lepton主题兼容",
+ "BlackFridayDiscount": "黑色星期五折扣",
+ "UpgradePaymentInfoSection_DeveloperPrice": "{0} 对于 {1} 额外的开发人员",
+ "Upgrade": "升级",
+ "Renewal": "续订",
+ "UpgradePaymentInfoSection_LicensePrice": "{0} 许可证",
+ "UpgradePaymentInfoSection_LicenseRenewalPrice": "许可证续订",
+ "Total": "总计",
+ "SupportPolicyFaqTitle": "您的支持政策是什么?",
+ "SupportPolicyFaqExplanation": "我们只支持有效的和以前的主要版本。 我们不保证为第 3 个和更早的主要版本发布补丁。 例如,如果有效版本是 7.0.0,我们将发布 6.x.x 和 7.x.x 的补丁版本。 此外,我们仅对 ABP Framework 和 ABP Commercial 相关问题提供支持。 这意味着不支持 ABP 产品使用的第 3 方应用程序、云服务和其他外围库。 我们将尽商业上合理的努力在“Volosoft Bilisim A.S”的正式营业时间内为我们的客户提供技术支持。 另一方面,我们不承诺服务级别协议 (SLA) 响应时间,但我们会尽量在我们的官方工作时间内尽快响应技术问题。 除非与客户达成特殊协议,否则我们仅在 https://support.abp.io 上提供支持。 我们还提供私人电子邮件支持,仅适用于企业许可证持有者。"
}
-}
\ No newline at end of file
+}
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json
index 23a98b5e4f..8225b0c2fd 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Community/Localization/Resources/zh-Hans.json
@@ -183,6 +183,7 @@
"Post_Index_Page_MetaDescription": "ABP 社区的目的是为使用 ABP 框架的开发人员创建一个贡献环境。",
"Layout_Title": "{0} | ABP 社区",
"Layout_MetaDescription": "ABP 社区是一个人们可以分享有关 ABP 框架的帖子并关注项目的环境。",
- "Index_Page_CommunityIntroduction": "这是 ABP 框架、.NET 和软件开发的中心。 您可以阅读文章,观看视频教程,了解 ABP 的开发进度和 ABP 相关事件,帮助其他开发人员并与 ABP 社区分享您的专业知识。"
+ "Index_Page_CommunityIntroduction": "这是 ABP 框架、.NET 和软件开发的中心。 您可以阅读文章,观看视频教程,了解 ABP 的开发进度和 ABP 相关事件,帮助其他开发人员并与 ABP 社区分享您的专业知识。",
+ "TagsInArticle": "文章中的标签"
}
-}
\ No newline at end of file
+}
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json
index c55dd947f3..24a5d64116 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json
@@ -406,6 +406,8 @@
"SingleLayerApplicationExplanation1": "Creates a single-layer web application. ",
"SingleLayerApplicationExplanation2": "Recommended for building an application with a simpler and easy to understand architecture.",
"ApplicationModule": "Application
Module",
- "SeeTheScreenshot": "See the screenshot"
+ "SeeTheScreenshot": "See the screenshot",
+ "ApplicationModuleExplanation1": "Creates a reusable, fully layered application module solution.",
+ "ApplicationModuleExplanation2": "You can use this option to create modules for your modular application."
}
}
diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json
index 76863f9e64..a6ef45db1d 100644
--- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json
+++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/zh-Hans.json
@@ -372,8 +372,42 @@
"MasteringAbpFramework_Book_WhoIsThisBookFor": "这本书是给谁看的",
"MasteringAbpFramework_Book_WhoIsThisBookFor_Description": "本书适用于希望学习软件架构和最佳实践的 Web 开发人员,以使用 Microsoft 技术和 ABP 框架构建\n 可维护的基于 Web 的解决方案。 C#\n 和 ASP.NET Core 的基本知识是开始阅读本书所必需的。",
"ComputersAndTechnology": "计算机与技术",
+ "BuildingMicroserviceSolutions": "构建微服务解决方案",
+ "MicroserviceBookPracticalGuide": "本书是使用 ABP 框架开发和管理基于微服务的应用程序的参考指南。 它引用了 .NET 微服务示例参考应用程序:eShopOnContainers,并讨论了使用 ABP 框架的架构设计和实现方法。 读完本书,您将了解 ABP 如何处理常见的微服务复杂性,例如授权、分布式事务、微服务间通信、部署等。",
+ "IntroducingTheSolution": "介绍 eShopOnAbp 解决方案",
+ "RunningTheSolution": "运行解决方案",
+ "UnderstandingTheAuthenticationSystem": "了解身份验证系统",
+ "ExploringTheApplications": "探索应用",
+ "UnderstandingTheAPIGateways": "了解 API 网关",
+ "DevelopingTheMicroservices": "开发微服务",
+ "UnderstandingTheInfrastructure": "了解基础设施",
+ "DiggingInTheUseCases": "挖掘用例",
+ "DeployingTheSolution": "部署解决方案",
"ThisBookIsInDraftStageAndIsNotCompletedYet": "这本书正在草案阶段,还没有完成。",
- "SelectUITheme": "选择 UI 主题"
-
+ "Authors": "作者",
+ "MicroserviceEBook": "微服务电子书",
+ "SelectUITheme": "选择 UI 主题",
+ "LeptonXLiteTheme": "LeptonX Lite 主题",
+ "BasicTheme": "基本主题",
+ "LeptonXLiteThemeInfo": " 现代时尚的 Bootstrap UI 主题。 如果你想要一个生产就绪的 UI 主题,这是理想的选择。 这是最新的主题,也是默认主题。",
+ "BasicThemeInfo": "具有简单 Bootstrap 颜色和样式的极简 UI 主题。 如果您要构建自己的 UI 主题,则非常适合。",
+ "SeeDocumentation": "请参阅 文档.",
+ "SeeFullScreen": "🖼️ 如截图所示",
+ "BuildingMicroserviceSolutionsShortDescription": "本书是使用 ABP 框架开发和管理基于微服务的应用程序的参考指南。",
+ "InstallAbpCliMessage": "如果之前没有安装,请在命令行终端中安装 ABP CLI:",
+ "Terminal": "终端",
+ "Copy": "复制",
+ "RunTheFollowingCommand": "在命令行终端中运行以下命令:",
+ "ChangeSolutionOptionsBelow": "您可以更改下面的解决方案选项。",
+ "MultiLayerApplication": "多层
应用",
+ "MultiLayerApplicationExplanation1": "基于领域驱动设计实践创建完全分层的解决方案。",
+ "MultiLayerApplicationExplanation2": "推荐用于需要可维护和可扩展代码库的长期项目。",
+ "SingleLayerApplication": "单层
应用",
+ "SingleLayerApplicationExplanation1": "创建单层 Web 应用程序。 ",
+ "SingleLayerApplicationExplanation2": "推荐用于构建具有更简单且易于理解的体系结构的应用程序。",
+ "ApplicationModule": "应用程序模块",
+ "SeeTheScreenshot": "如截图所示",
+ "ApplicationModuleExplanation1": "创建可重用的、完全分层的应用程序模块解决方案。",
+ "ApplicationModuleExplanation2": "您可以使用此选项为您的模块化应用程序创建模块。"
}
-}
\ No newline at end of file
+}
diff --git a/common.props b/common.props
index 2824a1fb8f..faab44ccd2 100644
--- a/common.props
+++ b/common.props
@@ -1,7 +1,7 @@
latest
- 7.0.0-rc.2
+ 7.1.0
$(NoWarn);CS1591;CS0436
https://abp.io/assets/abp_nupkg.png
https://abp.io/
diff --git a/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/POST.md b/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/POST.md
new file mode 100644
index 0000000000..73a0d7589c
--- /dev/null
+++ b/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/POST.md
@@ -0,0 +1,129 @@
+# How to add a custom grant type in OpenIddict
+
+## ITokenExtensionGrant
+
+Create a class that inherits `ITokenExtensionGrant`, and then register it with the framework.
+
+In the `MyTokenExtensionGrant` class below we try to get the token details, The `ForbidResult` handles the failure case and `SignInResult` returns a new token response, You can pass more parameters to implement business checks.
+
+```cs
+public class MyTokenExtensionGrant : ITokenExtensionGrant
+{
+ public const string ExtensionGrantName = "MyTokenExtensionGrant";
+
+ public string Name => ExtensionGrantName;
+ public async Task HandleAsync(ExtensionGrantContext context)
+ {
+ var userToken = context.Request.GetParameter("token").ToString();
+
+ if (string.IsNullOrEmpty(userToken))
+ {
+ return new ForbidResult(
+ new[] {OpenIddictServerAspNetCoreDefaults.AuthenticationScheme},
+ properties: new AuthenticationProperties(new Dictionary
+ {
+ [OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidRequest
+ }!));
+ }
+
+ var transaction = await context.HttpContext.RequestServices.GetRequiredService().CreateTransactionAsync();
+ transaction.EndpointType = OpenIddictServerEndpointType.Introspection;
+ transaction.Request = new OpenIddictRequest
+ {
+ ClientId = context.Request.ClientId,
+ ClientSecret = context.Request.ClientSecret,
+ Token = userToken
+ };
+
+ var notification = new OpenIddictServerEvents.ProcessAuthenticationContext(transaction);
+ var dispatcher = context.HttpContext.RequestServices.GetRequiredService();
+ await dispatcher.DispatchAsync(notification);
+
+ if (notification.IsRejected)
+ {
+ return new ForbidResult(
+ new []{ OpenIddictServerAspNetCoreDefaults.AuthenticationScheme },
+ properties: new AuthenticationProperties(new Dictionary
+ {
+ [OpenIddictServerAspNetCoreConstants.Properties.Error] = notification.Error ?? OpenIddictConstants.Errors.InvalidRequest,
+ [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = notification.ErrorDescription,
+ [OpenIddictServerAspNetCoreConstants.Properties.ErrorUri] = notification.ErrorUri
+ }));
+ }
+
+ var principal = notification.GenericTokenPrincipal;
+ if (principal == null)
+ {
+ return new ForbidResult(
+ new []{ OpenIddictServerAspNetCoreDefaults.AuthenticationScheme },
+ properties: new AuthenticationProperties(new Dictionary
+ {
+ [OpenIddictServerAspNetCoreConstants.Properties.Error] = notification.Error ?? OpenIddictConstants.Errors.InvalidRequest,
+ [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = notification.ErrorDescription,
+ [OpenIddictServerAspNetCoreConstants.Properties.ErrorUri] = notification.ErrorUri
+ }));
+ }
+
+ var userId = principal.FindUserId();
+ var userManager = context.HttpContext.RequestServices.GetRequiredService();
+ var user = await userManager.GetByIdAsync(userId.Value);
+ var userClaimsPrincipalFactory = context.HttpContext.RequestServices.GetRequiredService>();
+ var claimsPrincipal = await userClaimsPrincipalFactory.CreateAsync(user);
+ claimsPrincipal.SetScopes(principal.GetScopes());
+ claimsPrincipal.SetResources(await GetResourcesAsync(context, principal.GetScopes()));
+ await context.HttpContext.RequestServices.GetRequiredService().SetAsync(principal);
+ return new SignInResult(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, claimsPrincipal);
+ }
+
+ private async Task> GetResourcesAsync(ExtensionGrantContext context, ImmutableArray scopes)
+ {
+ var resources = new List();
+ if (!scopes.Any())
+ {
+ return resources;
+ }
+
+ await foreach (var resource in context.HttpContext.RequestServices.GetRequiredService().ListResourcesAsync(scopes))
+ {
+ resources.Add(resource);
+ }
+ return resources;
+ }
+}
+```
+
+```cs
+public override void PreConfigureServices(ServiceConfigurationContext context)
+{
+ //...
+ PreConfigure(builder =>
+ {
+ builder.Configure(openIddictServerOptions =>
+ {
+ openIddictServerOptions.GrantTypes.Add(MyTokenExtensionGrant.ExtensionGrantName);
+ });
+ });
+ //...
+}
+
+public override void ConfigureServices(ServiceConfigurationContext context)
+{
+ //...
+ Configure(options =>
+ {
+ options.Grants.Add(MyTokenExtensionGrant.ExtensionGrantName, new MyTokenExtensionGrant());
+ });
+ //...
+}
+```
+
+
+
+
+
+
+## Source code
+
+https://github.com/abpframework/abp/commit/3210f138454697647689b4868c8d4b7b3da02d44
+
+
diff --git a/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/postman1.png b/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/postman1.png
new file mode 100644
index 0000000000..1e2c7535c5
Binary files /dev/null and b/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/postman1.png differ
diff --git a/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/postman2.png b/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/postman2.png
new file mode 100644
index 0000000000..c3dbb7324a
Binary files /dev/null and b/docs/en/Community-Articles/2022-11-14-How-to-add-a-custom-grant-type-in-OpenIddict/postman2.png differ
diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/hr.json b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/hr.json
new file mode 100644
index 0000000000..83f6459a7c
--- /dev/null
+++ b/framework/src/Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy/Volo/Abp/AspNetCore/Mvc/UI/MultiTenancy/Localization/hr.json
@@ -0,0 +1,13 @@
+{
+ "culture": "hr",
+ "texts": {
+ "GivenTenantIsNotExist": "Odabrani tenant ne postoji: {0}",
+ "GivenTenantIsNotAvailable": "Odabrani tenant nije dostupan: {0}",
+ "Tenant": "Tenant",
+ "Switch": "promjena",
+ "Name": "Naziv",
+ "SwitchTenantHint": "Polje naziv ostavite prazno kako bi se prebacili na host-ovu stranu.",
+ "SwitchTenant": "Promjena tenant-a",
+ "NotSelected": "Nije odabrano"
+ }
+}
diff --git a/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/hr.json b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/hr.json
new file mode 100644
index 0000000000..e359210aae
--- /dev/null
+++ b/framework/src/Volo.Abp.UI.Navigation/Volo/Abp/Ui/Navigation/Localization/Resource/hr.json
@@ -0,0 +1,6 @@
+{
+ "culture": "hr",
+ "texts": {
+ "Menu:Administration": "Administracija"
+ }
+}
\ No newline at end of file
diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hr.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hr.json
new file mode 100644
index 0000000000..9cbef79b12
--- /dev/null
+++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hr.json
@@ -0,0 +1,53 @@
+{
+ "culture": "hr",
+ "texts": {
+ "Languages": "Jezici",
+ "AreYouSure": "Jeste li sigurni?",
+ "Cancel": "Odustani",
+ "Clear": "Očisti",
+ "Yes": "Da",
+ "No": "Ne",
+ "Ok": "Ok",
+ "Close": "Zatvori",
+ "Save": "Spremi",
+ "SavingWithThreeDot": "Spremanje...",
+ "Actions": "Akcije",
+ "Delete": "Izbrisati",
+ "SuccessfullyDeleted": "Uspješno izbrisano",
+ "Edit": "Uredi",
+ "Refresh": "Osvježi",
+ "Language": "Jezik",
+ "LoadMore": "Učitaj još",
+ "ProcessingWithThreeDot": "Obrada...",
+ "LoadingWithThreeDot": "Učitavanje...",
+ "Welcome": "Dobrodošli",
+ "Login": "Prijava",
+ "Register": "Registracija",
+ "Logout": "Odjava",
+ "Submit": "Pošalji",
+ "Back": "Nazad",
+ "PagerSearch": "Pretraga",
+ "PagerNext": "Sljedeći",
+ "PagerPrevious": "Prethodni",
+ "PagerFirst": "Prvi",
+ "PagerLast": "Zadnji",
+ "PagerInfo": "Prikazano _START_ do _END_ do _TOTAL_ zapisa",
+ "PagerInfo{0}{1}{2}": "Prikazano {0} do {1} od {2} zapisa",
+ "PagerInfoEmpty": "Prikazano 0 do 0 od 0 zapisa",
+ "PagerInfoFiltered": "(filtrirano od _MAX_ ukupnih zapisa)",
+ "NoDataAvailableInDatatable": "Nema dostupnih podataka",
+ "Total": "ukupno",
+ "Selected": "odabrano",
+ "PagerShowMenuEntries": "Pokaži _MENU_ zapise",
+ "DatatableActionDropdownDefaultText": "Akcije",
+ "ChangePassword": "Promjena lozinke",
+ "PersonalInfo": "Moj profil",
+ "AreYouSureYouWantToCancelEditingWarningMessage": "Imate nespremljene promjene.",
+ "GoHomePage": "Natrag na početnu",
+ "GoBack": "Idi natrag",
+ "Search": "Pretraga",
+ "ItemWillBeDeletedMessageWithFormat": "{0} zapis će biti obrisan!",
+ "ItemWillBeDeletedMessage": "Ovaj zapis će biti obrisan!",
+ "ManageYourAccount": "Upravljaj korisničkim računom"
+ }
+}
diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/hr.json b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/hr.json
new file mode 100644
index 0000000000..6bb5cf7d5e
--- /dev/null
+++ b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/Localization/hr.json
@@ -0,0 +1,36 @@
+{
+ "culture": "hr",
+ "texts": {
+ "'{0}' and '{1}' do not match.": "'{0}' i '{1}' se ne podudaraju.",
+ "The {0} field is not a valid credit card number.": "{0} nije važeći broj kreditne kartice.",
+ "{0} is not valid.": "{0} nije valjan.",
+ "The {0} field is not a valid e-mail address.": "{0} nije valjana e-mail adresa.",
+ "The {0} field only accepts files with the following extensions: {1}": "{0} polje prihvaća samo datoteke sa sljedećim ekstenzijama: {1}",
+ "The field {0} must be a string or array type with a maximum length of '{1}'.": "Polje {0} mora biti text ili niz sa maksimalnom dužinom od '{1}'.",
+ "The field {0} must be a string or array type with a minimum length of '{1}'.": "Polje {0} mora biti text ili niz sa minimalnom dužinom od '{1}'.",
+ "The {0} field is not a valid phone number.": "{0} nije valjan broj telefona.",
+ "The field {0} must be between {1} and {2}.": "{0} mora biti između {1} i {2}.",
+ "The field {0} must match the regular expression '{1}'.": "{0} ne odgovara traženom formatu.",
+ "The {0} field is required.": "{0} polje je obavezno.",
+ "The field {0} must be a string with a maximum length of {1}.": "Polje {0} mora biti text sa maksimalnom dužinom od {1}.",
+ "The field {0} must be a string with a minimum length of {2} and a maximum length of {1}.": "Polje {0} mora biti text sa minimalnom du�inom od {2} i maksimalnom dužinom od {1}.",
+ "The {0} field is not a valid fully-qualified http, https, or ftp URL.": "{0} nije valjan potpuno kvalificirani http, https, ili ftp URL.",
+ "The field {0} is invalid.": "Polje {0} nije važeće.",
+ "ThisFieldIsNotAValidCreditCardNumber.": "Ovo polje nije važeći broj kreditne kartice.",
+ "ThisFieldIsNotValid.": "Ovo polje nije valjano.",
+ "ThisFieldIsNotAValidEmailAddress.": "Ovo polje nije valjana e-mail adresa.",
+ "ThisFieldOnlyAcceptsFilesWithTheFollowingExtensions:{0}": "Ovo polje prihvaća samo datoteke sa sljedećim ekstenzijama: {0}",
+ "ThisFieldMustBeAStringOrArrayTypeWithAMaximumLengthOf{0}": "Ovo polje mora biti text ili niz sa maksimalnom dužinom od '{0}'.",
+ "ThisFieldMustBeAStringOrArrayTypeWithAMinimumLengthOf{0}": "Ovo polje mora biti text ili niz sa minimalnom dužinom od '{0}'.",
+ "ThisFieldIsNotAValidPhoneNumber.": "Ovo polje nije važeći broj telefona.",
+ "ThisFieldMustBeBetween{0}And{1}": "Ovo polje mora biti između {0} i {1}.",
+ "ThisFieldMustBeGreaterThanOrEqual{0}": "Ovo polje mora biti veće od ili jednako {0}.",
+ "ThisFieldMustBeLessOrEqual{0}": "Ovo polje mora biti manje od ili jednako {0}.",
+ "ThisFieldMustMatchTheRegularExpression{0}": "Ovo polje mora odgovarati regularnom izrazu '{0}'.",
+ "ThisFieldIsRequired.": "Ovo polje je obavezno.",
+ "ThisFieldMustBeAStringWithAMaximumLengthOf{0}": "Ovo polje mora biti niz maksimalne duljine od: {0}.",
+ "ThisFieldMustBeAStringWithAMinimumLengthOf{1}AndAMaximumLengthOf{0}": "Ovo polja mora biti tekst sa minimalnom duljinom od {1} i maksimalnom duljinom od {0}.",
+ "ThisFieldIsNotAValidFullyQualifiedHttpHttpsOrFtpUrl": "Ovo polje nije važeći potpuno kvalificirani http, https ili ftp URL.",
+ "ThisFieldIsInvalid.": "Ovo polje je nevažeće."
+ }
+}
diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/hr.json b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/hr.json
new file mode 100644
index 0000000000..ddc677eb2a
--- /dev/null
+++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Localization/Resource/hr.json
@@ -0,0 +1,10 @@
+{
+ "culture": "hr",
+ "texts": {
+ "DisplayName:PersonModel:BirthDate1": "Datum rođenja1",
+ "DisplayName:BirthDate2": "Datum rođenja2",
+ "PersonModel:BirthDate3": "Datum rođenja3",
+ "BirthDate": "Datum rođenja",
+ "Value1": "Vrijednost jedan"
+ }
+}
diff --git a/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/hr.json b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/hr.json
new file mode 100644
index 0000000000..6fbc1c2176
--- /dev/null
+++ b/framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/Localization/hr.json
@@ -0,0 +1,6 @@
+{
+ "culture": "hr",
+ "texts": {
+ "hello": "Hej"
+ }
+}
\ No newline at end of file
diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/hr.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/hr.json
new file mode 100644
index 0000000000..2717dda0ce
--- /dev/null
+++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/CountryNames/hr.json
@@ -0,0 +1,7 @@
+{
+ "culture": "hr",
+ "texts": {
+ "USA": "Sjedinjene Američke Države",
+ "Brazil": "Brazil"
+ }
+}
diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/hr.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/hr.json
new file mode 100644
index 0000000000..09f68e9142
--- /dev/null
+++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Base/Validation/hr.json
@@ -0,0 +1,7 @@
+{
+ "culture": "hr",
+ "texts": {
+ "ThisFieldIsRequired": "Ovo polje je obavezno",
+ "MaxLenghtErrorMessage": "Ovo polje može imati najviše '{0}' znakova"
+ }
+}
diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/hr.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/hr.json
new file mode 100644
index 0000000000..c1fb8ad91c
--- /dev/null
+++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/Source/hr.json
@@ -0,0 +1,11 @@
+{
+ "culture": "hr",
+ "texts": {
+ "Hello {0}.": "Hej {0}.",
+ "Car": "Auto",
+ "CarPlural": "Auta",
+ "MaxLenghtErrorMessage": "Dužina ovog polja može biti maksimalno '{0}' znakova",
+ "Universe": "Univerzum",
+ "FortyTwo": "Četrdeset dva"
+ }
+}
diff --git a/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/hr.json b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/hr.json
new file mode 100644
index 0000000000..12f451bc0b
--- /dev/null
+++ b/framework/test/Volo.Abp.Localization.Tests/Volo/Abp/Localization/TestResources/SourceExt/hr.json
@@ -0,0 +1,6 @@
+{
+ "culture": "hr",
+ "texts": {
+ "SeeYou": "Vidimo se"
+ }
+}
\ No newline at end of file
diff --git a/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hr.json b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hr.json
new file mode 100644
index 0000000000..5a49982146
--- /dev/null
+++ b/modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/hr.json
@@ -0,0 +1,71 @@
+{
+ "culture": "hr",
+ "texts": {
+ "Menu:Account": "Korisnički račun",
+ "UserName": "Korisničko ime",
+ "EmailAddress": "Email adresa",
+ "UserNameOrEmailAddress": "Korisničko ime ili email adresa",
+ "Password": "Lozinka",
+ "RememberMe": "Zapamti me",
+ "UseAnotherServiceToLogin": "Koristite drugu uslugu za prijavu",
+ "UserLockedOutMessage": "Korisnički račun je zaključan zbog nevažećih pokušaja prijave. Pričekajte malo i pokušajte ponovo.",
+ "InvalidUserNameOrPassword": "Neispravno korisničko ime ili lozinka!",
+ "LoginIsNotAllowed": "Nemate dopuštenje za prijavu! Vaš račun nije aktivan ili treba potvrditi vašu e-poštu/broj telefona.",
+ "SelfRegistrationDisabledMessage": "Samoregistracija je onemogućena za ovu aplikaciju. Molimo kontaktirajte administratora aplikacije za registraciju novog korisnika.",
+ "LocalLoginDisabledMessage": "Lokalna prijava je onemogućena za ovu aplikaciju.",
+ "Login": "Prijavi se",
+ "Cancel": "Odustani",
+ "Register": "Registracija",
+ "AreYouANewUser": "Jeste li novi korisnik?",
+ "AlreadyRegistered": "Već registrirani?",
+ "InvalidLoginRequest": "Nevažeći zahtjev za prijavu",
+ "ThereAreNoLoginSchemesConfiguredForThisClient": "Za ovog klijenta nema konfiguriranih shema prijave.",
+ "LogInUsingYourProviderAccount": "Prijavite se koristeći svoj {0} račun",
+ "DisplayName:CurrentPassword": "Trenutna lozinka",
+ "DisplayName:NewPassword": "Nova lozinka",
+ "DisplayName:NewPasswordConfirm": "Potvrdite novu lozinku",
+ "PasswordChangedMessage": "Vaša lozinka je uspješno promijenjena.",
+ "DisplayName:UserName": "Korisničko ime",
+ "DisplayName:Email": "E-mail",
+ "DisplayName:Name": "Ime",
+ "DisplayName:Surname": "Prezime",
+ "DisplayName:Password": "Zaporka",
+ "DisplayName:EmailAddress": "Email adresa",
+ "DisplayName:PhoneNumber": "Broj telefona",
+ "PersonalSettings": "Osobne postavke",
+ "PersonalSettingsSaved": "Osobne postavke spremljene",
+ "PersonalSettingsChangedConfirmationModalTitle": "Osobni podaci promijenjeni",
+ "PersonalSettingsChangedConfirmationModalDescription": "Ako želite primijeniti ove promjene, morate se ponovno prijaviti. Želite li se odjaviti?",
+ "PasswordChanged": "Lozinka promijenjena",
+ "NewPasswordConfirmFailed": "Molimo potvrdite novu lozinku.",
+ "NewPasswordSameAsOld": "Nova lozinka mora se razlikovati od stare.",
+ "Manage": "Upravljati",
+ "MyAccount": "Moj račun",
+ "DisplayName:Abp.Account.IsSelfRegistrationEnabled": "Je li omogućena samoregistracija",
+ "Description:Abp.Account.IsSelfRegistrationEnabled": "Može li korisnik sam registrirati račun.",
+ "DisplayName:Abp.Account.EnableLocalLogin": "Autentificirajte se s lokalnim računom",
+ "Description:Abp.Account.EnableLocalLogin": "Označava hoće li poslužitelj dopustiti korisnicima autentifikaciju s lokalnim računom.",
+ "LoggedOutTitle": "Odjavljen/a",
+ "LoggedOutText": "Odjavljeni ste i uskoro ćete biti preusmjereni.",
+ "ReturnToText": "Kliknite ovdje za povratak na aplikaciju",
+ "OrLoginWith": "Ili se prijavite sa:",
+ "ForgotPassword": "Zaboravili ste lozinku?",
+ "SendPasswordResetLink_Information": "Link za ponovno postavljanje lozinke bit će poslan na vašu e-poštu kako bi ste ponovno postavili lozinku. Ako ne dobijete e-poruku u roku od nekoliko minuta, pokušajte ponovo.",
+ "PasswordResetMailSentMessage": "Poruka e-pošte za oporavak računa poslana je na vašu adresu e-pošte. Ako ne vidite ovu e-poruku u pristigloj pošti u roku od 15 minuta, potražite je u mapi bezvrijedne pošte. Ako poruku pronađete tamo, označite je kao -Nije smeće-. ",
+ "ResetPassword": "Resetiranje lozinke",
+ "ConfirmPassword": "Potvrdite (ponovite) lozinku",
+ "ResetPassword_Information": "Unesite svoju novu lozinku.",
+ "YourPasswordIsSuccessfullyReset": "Vaša lozinka je uspješno poništena.",
+ "GoToTheApplication": "Idite na aplikaciju",
+ "BackToLogin": "Natrag na prijavu",
+ "ProfileTab:Password": "Promjena lozinke",
+ "ProfileTab:PersonalInfo": "Osobne informacije",
+ "ReturnToApplication": "Povratak na aplikaciju",
+ "Volo.Account:InvalidEmailAddress": "Email adresa nije pronađena: {0}",
+ "PasswordReset": "Ponovno postavljanje lozinke",
+ "PasswordResetInfoInEmail": "Primili smo zahtjev za oporavak računa! Ako ste vi pokrenuli ovaj zahtjev, kliknite na sljedeću poveznicu za ponovno postavljanje lozinke.",
+ "ResetMyPassword": "Resetirati moju lozinku",
+ "AccessDenied": "Pristup odbijen!",
+ "AccessDeniedMessage": "Nemate pristup ovom resursu."
+ }
+}
diff --git a/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/hr.json b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/hr.json
new file mode 100644
index 0000000000..9cfef4eeba
--- /dev/null
+++ b/modules/blogging/src/Volo.Blogging.Domain.Shared/Volo/Blogging/Localization/Resources/hr.json
@@ -0,0 +1,64 @@
+{
+ "culture": "hr",
+ "texts": {
+ "Menu:Blogs": "Blogovi",
+ "Menu:BlogManagement": "Bloganje",
+ "Permission:Management": "Upravljanje",
+ "Permission:Edit": "Uredi",
+ "Permission:Create": "Dodaj",
+ "Permission:Delete": "Izbrisati",
+ "Permission:Blogging": "Blog",
+ "Permission:Blogs": "Blogovi",
+ "Permission:Posts": "Postovi",
+ "Permission:Tags": "Tagovi",
+ "Permission:Comments": "Komentari",
+ "Permission:ClearCache": "Očisti predmemoriju",
+ "Title": "Titula",
+ "Delete": "Izbrisati",
+ "Reply": "Odgovor",
+ "ReplyTo": "Odgovor na {0}",
+ "ContinueReading": "Nastavi čitati",
+ "DaysAgo": "Prije {0} dana",
+ "YearsAgo": "Prije {0} godina",
+ "MonthsAgo": "Prije {0} mjeseci",
+ "WeeksAgo": "Prije {0} tjedana",
+ "MinutesAgo": "Prije {0} minuta",
+ "SecondsAgo": "Prije {0} sekundi",
+ "HoursAgo": "Prije {0} sati",
+ "Now": "sada",
+ "Content": "Sadržaj",
+ "SeeAll": "Vidi sve",
+ "PopularTags": "Popularne oznake",
+ "WiewsWithCount": "{0} pregleda",
+ "LastPosts": "Zadnji postovi",
+ "LeaveComment": "Ostavite komentar",
+ "TagsInThisArticle": "Oznake u ovom članku",
+ "Posts": "Postovi",
+ "Edit": "Uredi",
+ "BLOG": "BLOG",
+ "CommentDeletionWarningMessage": "Komentar će biti izbrisan.",
+ "PostDeletionWarningMessage": "Post će biti izbrisan.",
+ "BlogDeletionWarningMessage": "Blog će biti izbrisan.",
+ "AreYouSure": "Jesi li siguran?",
+ "CommentWithCount": "{0} komentara",
+ "Comment": "Komentar",
+ "ShareOnTwitter": "Podijelite na Twitteru",
+ "CoverImage": "Naslovna slika",
+ "CreateANewPost": "Napravi novi post",
+ "CreateANewBlog": "Napravi novi blog",
+ "WhatIsNew": "Što je novo?",
+ "Name": "Ime",
+ "ShortName": "Nadimak",
+ "CreationTime": "Vrijeme stvaranja",
+ "Description": "Opis",
+ "Blogs": "Blogovi",
+ "Tags": "Oznake",
+ "ShareOn": "Podijeli na",
+ "TitleLengthWarning": "Neka vaš naslov bude ispod 60 znakova kako bi bio SEO optimiziran!",
+ "ClearCache": "Očisti predmemoriju",
+ "ClearCacheConfirmationMessage": "Jeste li sigurni da želite isprazniti predmemoriju?",
+ "MarkdownSupported": "Markdown je podržan",
+ "FileUploadInfo": "Povucite, ispustite ili zalijepite kopiranu sliku.",
+ "PostDescriptionHint": "* Prikazat će se u pretpregledu veze članka, podržava HTML"
+ }
+}
diff --git a/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/hr.json b/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/hr.json
new file mode 100644
index 0000000000..5316468de8
--- /dev/null
+++ b/modules/docs/app/VoloDocs.Web/Localization/Resources/VoloDocs/Web/hr.json
@@ -0,0 +1,10 @@
+{
+ "culture": "hr",
+ "texts": {
+ "DocsTitle": "VoloDocs",
+ "WelcomeVoloDocs": "Dobrodošli u VoloDocs!",
+ "NoProjectWarning": "Još nema definiranog projekta!",
+ "CreateYourFirstProject": "Kliknite ovdje kako biste započeli svoj prvi projekt",
+ "NoProject": "Nema projekta!"
+ }
+}
diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/hr.json b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/hr.json
new file mode 100644
index 0000000000..2469d21c4b
--- /dev/null
+++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Localization/Resources/Docs/ApplicationContracts/hr.json
@@ -0,0 +1,61 @@
+{
+ "culture": "hr",
+ "texts": {
+ "Permission:DocumentManagement": "Upravljanje dokumentima",
+ "Permission:Projects": "Projekti",
+ "Permission:Edit": "Uredi",
+ "Permission:Delete": "Izbrisati",
+ "Permission:Create": "Stvoriti",
+ "Permission:Documents": "Dokumenti",
+ "Menu:Documents": "Dokumenti",
+ "Menu:DocumentManagement": "Dokumenti",
+ "Menu:ProjectManagement": "Projekti",
+ "CreateANewProject": "Stvorite novi projekt",
+ "Edit": "Uredi",
+ "Create": "Stvoriti",
+ "Pull": "Vuci",
+ "Projects": "Projekti",
+ "Name": "Ime",
+ "ShortName": "Kratko ime",
+ "DocumentStoreType": "Vrsta pohrane dokumenata",
+ "Format": "Format",
+ "ShortNameInfoText": "Koristit će se za jedinstveni URL.",
+ "DisplayName:Name": "Ime",
+ "DisplayName:ShortName": "Kratko ime",
+ "DisplayName:Format": "Format",
+ "DisplayName:DefaultDocumentName": "Zadani naziv dokumenta",
+ "DisplayName:NavigationDocumentName": "Naziv navigacijskog dokumenta",
+ "DisplayName:MinimumVersion": "Minimalna verzija",
+ "DisplayName:MainWebsiteUrl": "Glavni URL web stranice",
+ "DisplayName:LatestVersionBranchName": "Naziv grane najnovije verzije",
+ "DisplayName:GitHubRootUrl": "GitHub korijenski URL",
+ "DisplayName:GitHubAccessToken": "GitHub pristupni token",
+ "DisplayName:GitHubUserAgent": "GitHub korisnički agent",
+ "DisplayName:GithubVersionProviderSource": "Izvor dobavljača GitHub verzije",
+ "DisplayName:VersionBranchPrefix": "Prefiks grane verzije",
+ "DisplayName:All": "Povuci sve",
+ "DisplayName:LanguageCode": "Jezični kod",
+ "DisplayName:Version": "Verzija",
+ "Documents": "Dokumenti",
+ "RemoveFromCache": "Ukloni iz predmemorije",
+ "Reindex": "Ponovno indeksiranje",
+ "ReindexCompleted": "Ponovno indeksiranje dovršeno",
+ "RemovedFromCache": "Uklonjeno iz predmemorije",
+ "RemoveFromCacheConfirmation": "Jeste li sigurni da želite ukloniti ovu stavku iz predmemorije?",
+ "ReIndexDocumentConfirmation": "Jeste li sigurni da želite ponovno indeksirati ovu stavku?",
+ "DeleteFromDatabase": "Izbriši iz baze podataka",
+ "Deleted": "Izbrisano",
+ "Search": "Pretraga",
+ "StartDate": "Početni datum",
+ "EndDate": "Krajnji datum",
+ "CreationTime": "Vrijeme stvaranja",
+ "LastUpdateTime": "Zadnje ažuriranje",
+ "LastSignificantUpdateTime": "Zadnje značajno ažuriranje",
+ "Version": "Verzija",
+ "LanguageCode": "Jezični kod",
+ "FileName": "Naziv datoteke",
+ "LastCachedTime": "Vrijeme predmemorije",
+ "Project": "Projekt",
+ "AdvancedFilters": "Napredni filtri"
+ }
+}
diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/hr.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/hr.json
new file mode 100644
index 0000000000..707088d110
--- /dev/null
+++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/hr.json
@@ -0,0 +1,41 @@
+{
+ "culture": "hr",
+ "texts": {
+ "Documents": "Dokumenti",
+ "BackToWebsite": "Povratak na web stranicu",
+ "Contributors": "Suradnici",
+ "ShareOn": "Podijeli na",
+ "Version": "Verzija",
+ "Edit": "Uredi",
+ "LastEditTime": "Zadnje uređivanje",
+ "Delete": "Izbrisati",
+ "ClearCache": "Očisti predmemoriju",
+ "ClearCacheConfirmationMessage": "Jeste li sigurni da želite izbrisati sve iz predmemorije za projekt \"{0}\"",
+ "ReIndexAllProjects": "Ponovno indeksirajte sve projekte",
+ "ReIndexProject": "Ponovno indeksiranje projekta",
+ "ReIndexProjectConfirmationMessage": "Jeste li sigurni da ponovno indeksirate za projekt \"{0}\"",
+ "SuccessfullyReIndexProject": "Uspješno ponovno indeksirano:\"{0}\"",
+ "ReIndexAllProjectConfirmationMessage": "Jeste li sigurni da ćete ponovno indeksirati sve projekte?",
+ "SuccessfullyReIndexAllProject": "Uspješno reindeksirani svi projekti",
+ "InThisDocument": "U ovom dokumentu",
+ "GoToTop": "Idi na vrh",
+ "Projects": "Projekti",
+ "NoProjectWarning": "Još nema projekata!",
+ "DocumentNotFound": "Ups, traženi dokument nije pronađen!",
+ "ProjectNotFound": "Ups, traženi projekt nije pronađen!",
+ "NavigationDocumentNotFound": "Ova verzija nema navigacijski dokument!",
+ "DocumentNotFoundInSelectedLanguage": "Dokument na željenom jeziku nije pronađen. Prikazuje se dokument na zadanom jeziku.",
+ "FilterTopics": "Filtrirajte teme",
+ "FullSearch": "Traži u dokumentima",
+ "Volo.Docs.Domain:010001": "Elastic search nije omogućen.",
+ "MultipleVersionDocumentInfo": "Postoji više verzija ovog dokumenta. Odaberite opcije koje vam najbolje odgovaraju.",
+ "New": "Novi",
+ "Upd": "Upd",
+ "NewExplanation": "Stvoreno u posljednja dva tjedna.",
+ "UpdatedExplanation": "Ažurirano u posljednja dva tjedna.",
+ "Volo.Docs.Domain:010002": "Nadimak {ShortName} već postoji.",
+ "Preview": "Pretpregled",
+ "Search": "Pretraga",
+ "SearchResults": "Rezultati pretrage"
+ }
+}
diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/hr.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/hr.json
new file mode 100644
index 0000000000..d54797121b
--- /dev/null
+++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain.Shared/Volo/Abp/FeatureManagement/Localization/Domain/hr.json
@@ -0,0 +1,15 @@
+{
+ "culture": "hr",
+ "texts": {
+ "Features": "Značajke",
+ "NoFeatureFoundMessage": "Ne postoji nijedna dostupna značajka.",
+ "ManageHostFeatures": "Upravljanje značajkama domaćina",
+ "Permission:FeatureManagement": "Upravljanje značajkama",
+ "Permission:FeatureManagement.ManageHostFeatures": "Upravljanje značajkama domaćina",
+ "Volo.Abp.FeatureManagement:InvalidFeatureValue": "Vrijednost značajke {0} nije važeća!",
+ "Menu:FeatureManagement": "Upravljanje značajkama",
+ "ResetToDefault": "Vrati na zadano",
+ "ResetedToDefault": "Vraćeno na zadano",
+ "AreYouSureToResetToDefault": "Jeste li sigurni da želite vratiti na zadane postavke?"
+ }
+}
diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hr.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hr.json
new file mode 100644
index 0000000000..75b349405a
--- /dev/null
+++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/hr.json
@@ -0,0 +1,113 @@
+{
+ "culture": "hr",
+ "texts": {
+ "Menu:IdentityManagement": "Upravljanje identitetom",
+ "Users": "Users",
+ "NewUser": "Novi korisnik",
+ "UserName": "Korisničko ime",
+ "Surname": "Prezime",
+ "EmailAddress": "Email adresa",
+ "PhoneNumber": "Broj telefona",
+ "UserInformations": "Informacije o korisniku",
+ "DisplayName:IsDefault": "Zadano",
+ "DisplayName:IsStatic": "Je statično",
+ "DisplayName:IsPublic": "Je javno",
+ "Roles": "Uloge",
+ "Password": "Lozinka",
+ "PersonalInfo": "Moj profil",
+ "PersonalSettings": "Osobne postavke",
+ "UserDeletionConfirmationMessage": "Korisnik '{0}' bit će izbrisan. Potvrđujete li to?",
+ "RoleDeletionConfirmationMessage": "Uloga '{0}' bit će izbrisana. Potvrđujete li to?",
+ "DisplayName:RoleName": "Naziv uloge",
+ "DisplayName:UserName": "Korisničko ime",
+ "DisplayName:Name": "Ime",
+ "DisplayName:Surname": "Prezime",
+ "DisplayName:Password": "Lozinka",
+ "DisplayName:Email": "Email adresa",
+ "DisplayName:PhoneNumber": "Broj telefona",
+ "DisplayName:TwoFactorEnabled": "Two factor verifikacija",
+ "DisplayName:IsActive": "Aktivan",
+ "DisplayName:LockoutEnabled": "Zaključaj račun nakon neuspjelih pokušaja prijave",
+ "NewRole": "Nova uloga",
+ "RoleName": "Naziv uloge",
+ "CreationTime": "Vrijeme stvaranja",
+ "Permissions": "Dozvole",
+ "DisplayName:CurrentPassword": "Trenutna lozinka",
+ "DisplayName:NewPassword": "Nova lozinka",
+ "DisplayName:NewPasswordConfirm": "Potvrdi novu lozinku",
+ "PasswordChangedMessage": "Vaša lozinka je uspješno promijenjena.",
+ "PersonalSettingsSavedMessage": "Vaše osobne postavke su uspješno spremljene.",
+ "Volo.Abp.Identity:DefaultError": "Došlo je do neočekivane greške.",
+ "Volo.Abp.Identity:ConcurrencyFailure": "Provjera optimisti�ne paralelnosti nije uspjela. Entitet na kojem radite izmijenio je drugi korisnik. Molimo odbacite promjene i pokušajte ponovno.",
+ "Volo.Abp.Identity:DuplicateEmail": "Email '{0}' je već zauzet.",
+ "Volo.Abp.Identity:DuplicateRoleName": "Naziv uloge '{0}' već je zauzet.",
+ "Volo.Abp.Identity:DuplicateUserName": "Korisničko ime '{0}' je već zauzeto.",
+ "Volo.Abp.Identity:InvalidEmail": "E-pošta '{0}' nije važeća.",
+ "Volo.Abp.Identity:InvalidPasswordHasherCompatibilityMode": "Navedeni PasswordHasherCompatibilityMode je nevažeći.",
+ "Volo.Abp.Identity:InvalidPasswordHasherIterationCount": "Broj ponavljanja mora biti pozitivan cijeli broj.",
+ "Volo.Abp.Identity:InvalidRoleName": "Naziv uloge '{0}' nije valjan.",
+ "Volo.Abp.Identity:InvalidToken": "Pogrešan token.",
+ "Volo.Abp.Identity:InvalidUserName": "Korisničko ime '{0}' nije važeće, može sadržavati samo slova ili znamenke.",
+ "Volo.Abp.Identity:LoginAlreadyAssociated": "Korisnik s ovom prijavom već postoji.",
+ "Volo.Abp.Identity:PasswordMismatch": "Netočna lozinka.",
+ "Volo.Abp.Identity:PasswordRequiresDigit": "Lozinke moraju imati najmanje jednu znamenku ('0'-'9').",
+ "Volo.Abp.Identity:PasswordRequiresLower": "Zaporke moraju imati barem jedno malo slovo ('a'-'z').",
+ "Volo.Abp.Identity:PasswordRequiresNonAlphanumeric": "Lozinke moraju imati barem jedan znak koji nije alfanumerički.",
+ "Volo.Abp.Identity:PasswordRequiresUpper": "Lozinke moraju imati barem jedno veliko slovo ('A'-'Z').",
+ "Volo.Abp.Identity:PasswordTooShort": "Zaporke moraju imati najmanje {0} znakova.",
+ "Volo.Abp.Identity:RoleNotFound": "Uloga {0} ne postoji.",
+ "Volo.Abp.Identity:UserAlreadyHasPassword": "Korisnik već ima postavljenu lozinku.",
+ "Volo.Abp.Identity:UserAlreadyInRole": "Korisnik je već u ulozi '{0}'.",
+ "Volo.Abp.Identity:UserLockedOut": "Korisnik je zaključan.",
+ "Volo.Abp.Identity:UserLockoutNotEnabled": "Zaključavanje nije omogućeno za ovog korisnika.",
+ "Volo.Abp.Identity:UserNameNotFound": "Korisnik {0} ne postoji.",
+ "Volo.Abp.Identity:UserNotInRole": "Korisnik nije u ulozi '{0}'.",
+ "Volo.Abp.Identity:PasswordConfirmationFailed": "Lozinka ne odgovara lozinci za potvrdu.",
+ "Volo.Abp.Identity:010001": "Ne možete izbrisati vlastiti račun!",
+ "Volo.Abp.Identity:010002": "Ne možete postaviti više od {MaxUserMembershipCount} organizacijske jedinice za korisnika!",
+ "Volo.Abp.Identity:010003": "Nije moguće promijeniti lozinku eksterno prijavljenog korisnika!",
+ "Volo.Abp.Identity:010004": "Već postoji organizacijska jedinica s imenom {0}. Dvije jedinice s istim imenom ne mogu se stvoriti na istoj razini.",
+ "Volo.Abp.Identity:010005": "Statičke uloge nije moguće preimenovati.",
+ "Volo.Abp.Identity:010006": "Statičke uloge nije moguće izbrisati.",
+ "Volo.Abp.Identity:010007": "Ne možete promijeniti postavku dva faktora.",
+ "Volo.Abp.Identity:010008": "Nije dopušteno mijenjati postavke dvofaktorske autentifikacije.",
+ "Identity.OrganizationUnit.MaxUserMembershipCount": "Maksimalni dopušteni broj članstva u organizacijskoj jedinici za korisnika",
+ "ThisUserIsNotActiveMessage": "Ovaj korisnik nije aktivan.",
+ "Permission:IdentityManagement": "Upravljanje identitetom",
+ "Permission:RoleManagement": "Upravljanje ulogama",
+ "Permission:Create": "Stvoriti",
+ "Permission:Edit": "Uredi",
+ "Permission:Delete": "Izbrisati",
+ "Permission:ChangePermissions": "Promjena dopuštenja",
+ "Permission:UserManagement": "Upravljanje korisnicima",
+ "Permission:UserLookup": "Traženje korisnika",
+ "DisplayName:Abp.Identity.Password.RequiredLength": "Potrebna dužina",
+ "DisplayName:Abp.Identity.Password.RequiredUniqueChars": "Potreban broj jedinstvenih znakova",
+ "DisplayName:Abp.Identity.Password.RequireNonAlphanumeric": "Potreban znak koji nije alfanumerički",
+ "DisplayName:Abp.Identity.Password.RequireLowercase": "Obavezno malo slovo",
+ "DisplayName:Abp.Identity.Password.RequireUppercase": "Obavezno veliko slovo",
+ "DisplayName:Abp.Identity.Password.RequireDigit": "Obavezna znamenka",
+ "DisplayName:Abp.Identity.Lockout.AllowedForNewUsers": "Omogućeno za nove korisnike",
+ "DisplayName:Abp.Identity.Lockout.LockoutDuration": "Trajanje zaključavanja (sekunde)",
+ "DisplayName:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Maksimalan broj neuspjelih pokušaja pristupa",
+ "DisplayName:Abp.Identity.SignIn.RequireConfirmedEmail": "Zahtijeva potvrđenu e-poštu",
+ "DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Dopusti korisnicima da potvrde svoj telefonski broj",
+ "DisplayName:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Zahtijeva potvrđen telefonski broj",
+ "DisplayName:Abp.Identity.User.IsUserNameUpdateEnabled": "Dopusti korisnicima promjenu korisničkih imena",
+ "DisplayName:Abp.Identity.User.IsEmailUpdateEnabled": "Dopustite korisnicima da mijenjaju svoje adrese e-pošte",
+ "Description:Abp.Identity.Password.RequiredLength": "Minimalna duljina lozinke.",
+ "Description:Abp.Identity.Password.RequiredUniqueChars": "Najmanji broj jedinstvenih znakova koje lozinka mora sadržavati.",
+ "Description:Abp.Identity.Password.RequireNonAlphanumeric": "Ako lozinke moraju sadržavati nealfanumerički znak.",
+ "Description:Abp.Identity.Password.RequireLowercase": "Ako lozinke moraju sadržavati mali ASCII znak.",
+ "Description:Abp.Identity.Password.RequireUppercase": "Ako lozinke moraju sadržavati veliki ASCII znak.",
+ "Description:Abp.Identity.Password.RequireDigit": "Ako lozinke moraju sadržavati znamenku.",
+ "Description:Abp.Identity.Lockout.AllowedForNewUsers": "Može li se novi korisnik zaključati.",
+ "Description:Abp.Identity.Lockout.LockoutDuration": "Trajanje koliko je korisnik zaključan kada dođe do zaključavanja.",
+ "Description:Abp.Identity.Lockout.MaxFailedAccessAttempts": "Broj dopuštenih neuspjelih pokušaja pristupa prije nego što se korisnik zaključa, pod pretpostavkom da je zaključavanje omogućeno.",
+ "Description:Abp.Identity.SignIn.RequireConfirmedEmail": "Je li za prijavu potrebna potvrđena adresa e-pošte.",
+ "Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "Može li korisnik potvrditi telefonski broj.",
+ "Description:Abp.Identity.SignIn.RequireConfirmedPhoneNumber": "Je li za prijavu potreban potvrđeni telefonski broj.",
+ "Description:Abp.Identity.User.IsUserNameUpdateEnabled": "Može li korisnik ažurirati korisničko ime.",
+ "Description:Abp.Identity.User.IsEmailUpdateEnabled": "Može li korisnik ažurirati e-poštu."
+ }
+}
diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/EntityFrameworkCore/ServerDataSeedContributor.cs b/modules/openiddict/app/OpenIddict.Demo.Server/EntityFrameworkCore/ServerDataSeedContributor.cs
index bd94e16f9e..bf6a9cdb15 100644
--- a/modules/openiddict/app/OpenIddict.Demo.Server/EntityFrameworkCore/ServerDataSeedContributor.cs
+++ b/modules/openiddict/app/OpenIddict.Demo.Server/EntityFrameworkCore/ServerDataSeedContributor.cs
@@ -1,5 +1,6 @@
using System.Globalization;
using OpenIddict.Abstractions;
+using OpenIddict.Demo.Server.ExtensionGrants;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
@@ -75,6 +76,7 @@ public class ServerDataSeedContributor : IDataSeedContributor, ITransientDepende
OpenIddictConstants.Permissions.GrantTypes.RefreshToken,
OpenIddictConstants.Permissions.GrantTypes.DeviceCode,
OpenIddictConstants.Permissions.GrantTypes.ClientCredentials,
+ OpenIddictConstants.Permissions.Prefixes.GrantType + MyTokenExtensionGrant.ExtensionGrantName,
OpenIddictConstants.Permissions.ResponseTypes.Code,
OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken,
diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/ExtensionGrants/MyTokenExtensionGrant.cs b/modules/openiddict/app/OpenIddict.Demo.Server/ExtensionGrants/MyTokenExtensionGrant.cs
new file mode 100644
index 0000000000..62e4cba0b3
--- /dev/null
+++ b/modules/openiddict/app/OpenIddict.Demo.Server/ExtensionGrants/MyTokenExtensionGrant.cs
@@ -0,0 +1,99 @@
+using System.Collections.Immutable;
+using System.Security.Principal;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.AspNetCore.Mvc;
+using OpenIddict.Abstractions;
+using OpenIddict.Server;
+using OpenIddict.Server.AspNetCore;
+using Volo.Abp.Identity;
+using Volo.Abp.OpenIddict;
+using Volo.Abp.OpenIddict.ExtensionGrantTypes;
+using IdentityUser = Volo.Abp.Identity.IdentityUser;
+using SignInResult = Microsoft.AspNetCore.Mvc.SignInResult;
+
+namespace OpenIddict.Demo.Server.ExtensionGrants;
+
+public class MyTokenExtensionGrant : ITokenExtensionGrant
+{
+ public const string ExtensionGrantName = "MyTokenExtensionGrant";
+
+ public string Name => ExtensionGrantName;
+ public async Task HandleAsync(ExtensionGrantContext context)
+ {
+ var userToken = context.Request.GetParameter("token").ToString();
+
+ if (string.IsNullOrEmpty(userToken))
+ {
+ return new ForbidResult(
+ new[] {OpenIddictServerAspNetCoreDefaults.AuthenticationScheme},
+ properties: new AuthenticationProperties(new Dictionary
+ {
+ [OpenIddictServerAspNetCoreConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidRequest
+ }!));
+ }
+
+ var transaction = await context.HttpContext.RequestServices.GetRequiredService().CreateTransactionAsync();
+ transaction.EndpointType = OpenIddictServerEndpointType.Introspection;
+ transaction.Request = new OpenIddictRequest
+ {
+ ClientId = context.Request.ClientId,
+ ClientSecret = context.Request.ClientSecret,
+ Token = userToken
+ };
+
+ var notification = new OpenIddictServerEvents.ProcessAuthenticationContext(transaction);
+ var dispatcher = context.HttpContext.RequestServices.GetRequiredService();
+ await dispatcher.DispatchAsync(notification);
+
+ if (notification.IsRejected)
+ {
+ return new ForbidResult(
+ new []{ OpenIddictServerAspNetCoreDefaults.AuthenticationScheme },
+ properties: new AuthenticationProperties(new Dictionary
+ {
+ [OpenIddictServerAspNetCoreConstants.Properties.Error] = notification.Error ?? OpenIddictConstants.Errors.InvalidRequest,
+ [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = notification.ErrorDescription,
+ [OpenIddictServerAspNetCoreConstants.Properties.ErrorUri] = notification.ErrorUri
+ }));
+ }
+
+ var principal = notification.GenericTokenPrincipal;
+ if (principal == null)
+ {
+ return new ForbidResult(
+ new []{ OpenIddictServerAspNetCoreDefaults.AuthenticationScheme },
+ properties: new AuthenticationProperties(new Dictionary
+ {
+ [OpenIddictServerAspNetCoreConstants.Properties.Error] = notification.Error ?? OpenIddictConstants.Errors.InvalidRequest,
+ [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = notification.ErrorDescription,
+ [OpenIddictServerAspNetCoreConstants.Properties.ErrorUri] = notification.ErrorUri
+ }));
+ }
+
+ var userId = principal.FindUserId();
+ var userManager = context.HttpContext.RequestServices.GetRequiredService();
+ var user = await userManager.GetByIdAsync(userId.Value);
+ var userClaimsPrincipalFactory = context.HttpContext.RequestServices.GetRequiredService>();
+ var claimsPrincipal = await userClaimsPrincipalFactory.CreateAsync(user);
+ claimsPrincipal.SetScopes(principal.GetScopes());
+ claimsPrincipal.SetResources(await GetResourcesAsync(context, principal.GetScopes()));
+ await context.HttpContext.RequestServices.GetRequiredService().SetAsync(principal);
+ return new SignInResult(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, claimsPrincipal);
+ }
+
+ private async Task> GetResourcesAsync(ExtensionGrantContext context, ImmutableArray scopes)
+ {
+ var resources = new List();
+ if (!scopes.Any())
+ {
+ return resources;
+ }
+
+ await foreach (var resource in context.HttpContext.RequestServices.GetRequiredService().ListResourcesAsync(scopes))
+ {
+ resources.Add(resource);
+ }
+ return resources;
+ }
+}
diff --git a/modules/openiddict/app/OpenIddict.Demo.Server/OpenIddictServerModule.cs b/modules/openiddict/app/OpenIddict.Demo.Server/OpenIddictServerModule.cs
index 51a2dc81a9..9b20fc9674 100644
--- a/modules/openiddict/app/OpenIddict.Demo.Server/OpenIddictServerModule.cs
+++ b/modules/openiddict/app/OpenIddict.Demo.Server/OpenIddictServerModule.cs
@@ -2,6 +2,7 @@
using System.Security.Cryptography.X509Certificates;
using Microsoft.EntityFrameworkCore;
using OpenIddict.Demo.Server.EntityFrameworkCore;
+using OpenIddict.Demo.Server.ExtensionGrants;
using Volo.Abp;
using Volo.Abp.Account;
using Volo.Abp.Account.Web;
@@ -21,6 +22,7 @@ using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.OpenIddict;
using Volo.Abp.OpenIddict.EntityFrameworkCore;
+using Volo.Abp.OpenIddict.ExtensionGrantTypes;
using Volo.Abp.OpenIddict.WildcardDomains;
using Volo.Abp.PermissionManagement;
using Volo.Abp.PermissionManagement.EntityFrameworkCore;
@@ -104,6 +106,11 @@ public class OpenIddictServerModule : AbpModule
var certificate = request.CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddYears(2));
builder.AddEncryptionCertificate(certificate);
}
+
+ builder.Configure(openIddictServerOptions =>
+ {
+ openIddictServerOptions.GrantTypes.Add(MyTokenExtensionGrant.ExtensionGrantName);
+ });
});
PreConfigure(options =>
@@ -141,6 +148,11 @@ public class OpenIddictServerModule : AbpModule
{
options.IsEnabled = true;
});
+
+ Configure(options =>
+ {
+ options.Grants.Add(MyTokenExtensionGrant.ExtensionGrantName, new MyTokenExtensionGrant());
+ });
}
public async override Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo.Abp.OpenIddict.AspNetCore.csproj b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo.Abp.OpenIddict.AspNetCore.csproj
index ea725aa21f..ba52af22a5 100644
--- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo.Abp.OpenIddict.AspNetCore.csproj
+++ b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo.Abp.OpenIddict.AspNetCore.csproj
@@ -20,8 +20,8 @@
-
-
-
+
+
+
diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain.Shared/Volo.Abp.OpenIddict.Domain.Shared.csproj b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain.Shared/Volo.Abp.OpenIddict.Domain.Shared.csproj
index 040d7a986f..68b3f23d58 100644
--- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain.Shared/Volo.Abp.OpenIddict.Domain.Shared.csproj
+++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain.Shared/Volo.Abp.OpenIddict.Domain.Shared.csproj
@@ -14,7 +14,7 @@
-
+
diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo.Abp.OpenIddict.Domain.csproj b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo.Abp.OpenIddict.Domain.csproj
index 3da97bf272..9d638a566f 100644
--- a/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo.Abp.OpenIddict.Domain.csproj
+++ b/modules/openiddict/src/Volo.Abp.OpenIddict.Domain/Volo.Abp.OpenIddict.Domain.csproj
@@ -17,7 +17,7 @@
-
+
diff --git a/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/hr.json b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/hr.json
new file mode 100644
index 0000000000..a222bc5e0e
--- /dev/null
+++ b/modules/permission-management/src/Volo.Abp.PermissionManagement.Domain.Shared/Volo/Abp/PermissionManagement/Localization/Domain/hr.json
@@ -0,0 +1,11 @@
+{
+ "culture": "hr",
+ "texts": {
+ "Permissions": "Dozvole",
+ "OnlyProviderPermissons": "Samo ovaj pružatelj usluga",
+ "All": "Svi",
+ "SelectAllInAllTabs": "Dodijelite sva dopuštenja",
+ "SelectAllInThisTab": "Odaberi sve",
+ "SaveWithoutAnyPermissionsWarningMessage": "Jeste li sigurni da želite spremiti bez ikakvih dopuštenja?"
+ }
+}
diff --git a/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hr.json b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hr.json
new file mode 100644
index 0000000000..cd45f2339d
--- /dev/null
+++ b/modules/setting-management/src/Volo.Abp.SettingManagement.Domain.Shared/Volo/Abp/SettingManagement/Localization/Resources/AbpSettingManagement/hr.json
@@ -0,0 +1,34 @@
+{
+ "culture": "hr",
+ "texts": {
+ "Settings": "Postavke",
+ "SuccessfullySaved": "Uspješno spremljeno",
+ "Permission:SettingManagement": "Upravljanje postavkama",
+ "Permission:Emailing": "Slanje e-poštom",
+ "Permission:EmailingTest": "Test slanja e-pošte",
+ "SendTestEmail": "Po�alji probnu e-poštu",
+ "SenderEmailAddress": "Adresa e-pošte pošiljatelja",
+ "TargetEmailAddress": "Ciljana adresa e-pošte",
+ "Subject": "Predmet",
+ "Body": "Tijelo",
+ "TestEmailSubject": "Probna e-pošta {0}",
+ "TestEmailBody": "Testirajte tijelo poruke e-pošte ovdje",
+ "SuccessfullySent": "Uspješno poslano",
+ "Send": "Poslati",
+ "Menu:Emailing": "Slanje e-poštom",
+ "SmtpHost": "Domaćin",
+ "SmtpPort": "Port",
+ "SmtpUserName": "Korisničko ime",
+ "SmtpPassword": "Zaporka",
+ "SmtpDomain": "Domena",
+ "SmtpEnableSsl": "Omogući ssl",
+ "SmtpUseDefaultCredentials": "Koristite zadane vjerodajnice",
+ "DefaultFromAddress": "Zadana adresa",
+ "DefaultFromDisplayName": "Zadano iz imena za prikaz",
+ "Feature:SettingManagementGroup": "Upravljanje postavkama",
+ "Feature:SettingManagementEnable": "Omogući upravljanje postavkama",
+ "Feature:SettingManagementEnableDescription": "Omogućite sustav upravljanja postavkama u aplikaciji.",
+ "Feature:AllowChangingEmailSettings": "Dopusti promjenu postavki e-pošte.",
+ "Feature:AllowChangingEmailSettingsDescription": "Dopusti promjenu postavki e-pošte."
+ }
+}
diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/hr.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/hr.json
new file mode 100644
index 0000000000..7ca876277f
--- /dev/null
+++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Domain.Shared/Volo/Abp/TenantManagement/Localization/Resources/hr.json
@@ -0,0 +1,23 @@
+{
+ "culture": "hr",
+ "texts": {
+ "Volo.Abp.TenantManagement:DuplicateTenantName": "Ime stanara već postoji: {Name}",
+ "Menu:TenantManagement": "Upravljanje stanarima",
+ "Tenants": "Stanari",
+ "NewTenant": "Novi stanar",
+ "TenantName": "Ime Tenant-a",
+ "DisplayName:TenantName": "Ime Tenant-a",
+ "TenantDeletionConfirmationMessage": "Tenant '{0}' bit će izbrisan. Potvrđujete li to?",
+ "ConnectionStrings": "Veze na bazu podataka",
+ "DisplayName:DefaultConnectionString": "Zadana veza na bazu podataka",
+ "DisplayName:UseSharedDatabase": "Koristite dijeljenu bazu podataka",
+ "Permission:TenantManagement": "Upravljanje tenant-ima",
+ "Permission:Create": "Stvoriti",
+ "Permission:Edit": "Uredi",
+ "Permission:Delete": "Izbrisati",
+ "Permission:ManageConnectionStrings": "Upravljanje vezom na bazu podataka",
+ "Permission:ManageFeatures": "Upravljanje značajkama",
+ "DisplayName:AdminEmailAddress": "Adresa e-pošte administratora",
+ "DisplayName:AdminPassword": "Administratorska lozinka"
+ }
+}
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/hr.json b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/hr.json
new file mode 100644
index 0000000000..fa8efab322
--- /dev/null
+++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/hr.json
@@ -0,0 +1,8 @@
+{
+ "culture": "hr",
+ "texts": {
+ "Menu:Home": "Početna",
+ "Welcome": "Dobrodošli",
+ "LongWelcomeMessage": "Dobrodošli u aplikaciju. Ovo je startup projekt temeljen na ABP framework-u. Za više informacija posjetite abp.io."
+ }
+}
diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/MyProjectNameDomainModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/MyProjectNameDomainModule.cs
index 2dbf50dcfc..14c8a14148 100644
--- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/MyProjectNameDomainModule.cs
+++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/MyProjectNameDomainModule.cs
@@ -41,6 +41,7 @@ public class MyProjectNameDomainModule : AbpModule
options.Languages.Add(new LanguageInfo("en", "en", "English", "gb"));
options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)"));
options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar"));
+ options.Languages.Add(new LanguageInfo("hr", "hr", "Croatian"));
options.Languages.Add(new LanguageInfo("fi", "fi", "Finnish", "fi"));
options.Languages.Add(new LanguageInfo("fr", "fr", "Français", "fr"));
options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi", "in"));