mirror of https://github.com/abpframework/abp.git
102 changed files with 689 additions and 240 deletions
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 26 KiB |
@ -0,0 +1,88 @@ |
|||
# How to override localization strings of depending modules |
|||
|
|||
## Source Code |
|||
|
|||
You can find the source of the example solution used in this article [here](https://github.com/abpframework/abp-samples/tree/master/DocumentationSamples/ExtendLocalizationResource). |
|||
|
|||
## Getting Started |
|||
|
|||
This example is based on the following document |
|||
https://docs.abp.io/en/abp/latest/Localization#extending-existing-resource |
|||
|
|||
We will change the default `DisplayName:Abp.Timing.Timezone` and `Description:Abp.Timing.Timezone` of [`AbpTimingResource`](https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/AbpTimingResource.cs) and add localized text in [Russian language(`ru`)](https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.Timing/Volo/Abp/Timing/Localization/en.json). |
|||
|
|||
I created the `AbpTiming` folder in the `Localization` directory of the `ExtendLocalizationResource.Domain.Shared` project. |
|||
|
|||
Create `en.json` and `ru.json` in its directory. |
|||
|
|||
`en.json` |
|||
```json |
|||
{ |
|||
"culture": "en", |
|||
"texts": { |
|||
"DisplayName:Abp.Timing.Timezone": "My Time zone", |
|||
"Description:Abp.Timing.Timezone": "My Application time zone" |
|||
} |
|||
} |
|||
``` |
|||
|
|||
`ru.json` |
|||
```json |
|||
{ |
|||
"culture": "ru", |
|||
"texts": { |
|||
"DisplayName:Abp.Timing.Timezone": "Часовой пояс", |
|||
"Description:Abp.Timing.Timezone": "Часовой пояс приложения" |
|||
} |
|||
} |
|||
``` |
|||
|
|||
 |
|||
|
|||
We have below content in `ExtendLocalizationResource.Domain.Shared.csproj` file, See [Virtual-File-System](https://docs.abp.io/en/abp/latest/Virtual-File-System#working-with-the-embedded-files) understand how it works. |
|||
|
|||
```xml |
|||
<ItemGroup> |
|||
<EmbeddedResource Include="Localization\ExtendLocalizationResource\*.json" /> |
|||
<Content Remove="Localization\ExtendLocalizationResource\*.json" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="5.0.*" /> |
|||
</ItemGroup> |
|||
``` |
|||
|
|||
Change the code of the `ConfigureServices` method in `ExtendLocalizationResourceDomainSharedModule`. |
|||
|
|||
```cs |
|||
Configure<AbpLocalizationOptions>(options => |
|||
{ |
|||
options.Resources |
|||
.Add<ExtendLocalizationResourceResource>("en") |
|||
.AddBaseTypes(typeof(AbpValidationResource)) |
|||
.AddVirtualJson("/Localization/ExtendLocalizationResource"); |
|||
|
|||
//add following code |
|||
options.Resources |
|||
.Get<AbpTimingResource>() |
|||
.AddVirtualJson("/Localization/AbpTiming"); |
|||
|
|||
options.DefaultResourceType = typeof(ExtendLocalizationResourceResource); |
|||
}); |
|||
``` |
|||
|
|||
Execute `ExtendLocalizationResource.DbMigrator` to migrate the database and run `ExtendLocalizationResource.Web`. |
|||
|
|||
We have changed the English localization text and added Russian localization. |
|||
|
|||
### Index page |
|||
|
|||
```cs |
|||
<p>@AbpTimingResource["DisplayName:Abp.Timing.Timezone"]</p> |
|||
@using(CultureHelper.Use("ru")) |
|||
{ |
|||
<p>@AbpTimingResource["DisplayName:Abp.Timing.Timezone"]</p> |
|||
} |
|||
``` |
|||
|
|||
 |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,25 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk.Web"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net6.0</TargetFramework> |
|||
<AssemblyName>Volo.Abp.Http.Client.Web</AssemblyName> |
|||
<PackageId>Volo.Abp.Http.Client.Web</PackageId> |
|||
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> |
|||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
|||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
|||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
|||
<IsPackable>true</IsPackable> |
|||
<OutputType>Library</OutputType> |
|||
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc\Volo.Abp.AspNetCore.Mvc.csproj" /> |
|||
<ProjectReference Include="..\Volo.Abp.Http.Client\Volo.Abp.Http.Client.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,42 @@ |
|||
using System.Linq; |
|||
using Microsoft.AspNetCore.Mvc.ApplicationParts; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.DependencyInjection.Extensions; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc.Conventions; |
|||
using Volo.Abp.Http.Client.Web.Conventions; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.Http.Client.Web |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpAspNetCoreMvcModule), |
|||
typeof(AbpHttpClientModule) |
|||
)] |
|||
public class AbpHttpClientWebModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.Replace(ServiceDescriptor.Transient<IAbpServiceConvention, AbpHttpClientProxyServiceConvention>()); |
|||
context.Services.AddTransient<AbpHttpClientProxyServiceConvention>(); |
|||
|
|||
var partManager = context.Services.GetSingletonInstance<ApplicationPartManager>(); |
|||
partManager.FeatureProviders.Add(new AbpHttpClientProxyControllerFeatureProvider()); |
|||
} |
|||
|
|||
public override void OnApplicationInitialization(ApplicationInitializationContext context) |
|||
{ |
|||
var partManager = context.ServiceProvider.GetRequiredService<ApplicationPartManager>(); |
|||
foreach (var moduleAssembly in context |
|||
.ServiceProvider |
|||
.GetRequiredService<IModuleContainer>() |
|||
.Modules |
|||
.Select(m => m.Type.Assembly) |
|||
.Where(a => a.GetTypes().Any(AbpHttpClientProxyHelper.IsClientProxyService)) |
|||
.Distinct()) |
|||
{ |
|||
partManager.ApplicationParts.AddIfNotContains(moduleAssembly); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using System.Reflection; |
|||
using Microsoft.AspNetCore.Mvc.Controllers; |
|||
|
|||
namespace Volo.Abp.Http.Client.Web.Conventions |
|||
{ |
|||
public class AbpHttpClientProxyControllerFeatureProvider : ControllerFeatureProvider |
|||
{ |
|||
protected override bool IsController(TypeInfo typeInfo) |
|||
{ |
|||
return AbpHttpClientProxyHelper.IsClientProxyService(typeInfo); |
|||
} |
|||
} |
|||
} |
|||
@ -1,13 +0,0 @@ |
|||
using System.Reflection; |
|||
using Microsoft.AspNetCore.Mvc.Controllers; |
|||
|
|||
namespace Volo.Abp.Swashbuckle.Conventions |
|||
{ |
|||
public class AbpSwaggerClientProxyControllerFeatureProvider : ControllerFeatureProvider |
|||
{ |
|||
protected override bool IsController(TypeInfo typeInfo) |
|||
{ |
|||
return AbpSwaggerClientProxyHelper.IsClientProxyService(typeInfo); |
|||
} |
|||
} |
|||
} |
|||
@ -1,12 +0,0 @@ |
|||
namespace Volo.Abp.Swashbuckle.Conventions |
|||
{ |
|||
public class AbpSwaggerClientProxyOptions |
|||
{ |
|||
public bool IsEnabled { get; set; } |
|||
|
|||
public AbpSwaggerClientProxyOptions() |
|||
{ |
|||
IsEnabled = true; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,70 @@ |
|||
using Shouldly; |
|||
using Volo.Abp.Cli.ProjectModification; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.Cli |
|||
{ |
|||
public class ProjectVersionParse_Tests |
|||
{ |
|||
[Fact] |
|||
public void Find_Abp_Version() |
|||
{ |
|||
const string csprojContent = "<Project Sdk=\"Microsoft.NET.Sdk\">" + |
|||
"<Import Project=\"..\\..\\common.props\" />" + |
|||
"<PropertyGroup>" + |
|||
"<TargetFramework>net5.0</TargetFramework>" + |
|||
"<RootNamespace>Blazoor.EfCore07062034</RootNamespace>" + |
|||
"</PropertyGroup>" + |
|||
"<ItemGroup>" + |
|||
"<ProjectReference Include=\"..\\Blazoor.EfCore07062034.Domain.Shared\\Blazoor.EfCore07062034.Domain.Shared.csproj\" />" + |
|||
"</ItemGroup>" + |
|||
"<ItemGroup>" + |
|||
"< PackageReference Include = \"Volo.Abp.Emailing\" Version = \"4.4.0-rc.1\" />" + |
|||
"<PackageReference Include= \"Volo.Abp.PermissionManagement.Domain.Identity\" Version= \"4.4.0-rc.1\" />" + |
|||
"<PackageReference Include=\"Volo.Abp.IdentityServer.Domain\" Version=\"4.4.0-rc.1\" />" + |
|||
"<PackageReference Include=\"Volo.Abp.PermissionManagement.Domain.IdentityServer\" Version=\"4.4.0-rc.1\" />" + |
|||
"<PackageReference Include=\"Volo.Abp.BackgroundJobs.Domain\" Version=\"4.4.0-rc.1\" />" + |
|||
"<PackageReference Include=\"Volo.Abp.AuditLogging.Domain\" Version=\"4.4.0-rc.1\" />" + |
|||
"<PackageReference Include=\"Volo.Abp.FeatureManagement.Domain\" Version=\"4.4.0-rc.1\" />" + |
|||
"<PackageReference Include=\"Volo.Abp.SettingManagement.Domain\" Version=\"4.4.0-rc.1\" />" + |
|||
"<PackageReference Include=\"Volo.Abp.BlobStoring.Database.Domain\" Version=\"4.4.0-rc.1\" />" + |
|||
"<PackageReference Include=\"Volo.Abp.Identity.Pro.Domain\" Version=\"4.4.0-rc.1\" />" + |
|||
"<PackageReference Include=\"Volo.Abp.LanguageManagement.Domain\" Version=\"4.4.0-rc.1\" />" + |
|||
"<PackageReference Include=\"Volo.Abp.LeptonTheme.Management.Domain\" Version=\"4.4.0-rc.1\" />" + |
|||
"<PackageReference Include=\"Volo.Saas.Domain\" Version=\"4.4.0-rc.1\" />" + |
|||
"<PackageReference Include=\"Volo.Abp.TextTemplateManagement.Domain\" Version=\"4.4.0-rc.1\" />" + |
|||
"</ItemGroup>" + |
|||
"</Project>"; |
|||
|
|||
var success = SolutionAbpVersionFinder.TryParseVersionFromCsprojFile(csprojContent, out var version); |
|||
success.ShouldBe(true); |
|||
version.ShouldBe("4.4.0-rc.1"); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Find_Abp_Semantic_Version() |
|||
{ |
|||
const string csprojContent = "<Project Sdk=\"Microsoft.NET.Sdk\">" + |
|||
"<Import Project=\"..\\..\\common.props\" />" + |
|||
"<PropertyGroup>" + |
|||
"<TargetFramework>net5.0</TargetFramework>" + |
|||
"<RootNamespace>Blazoor.EfCore07062034</RootNamespace>" + |
|||
"</PropertyGroup>" + |
|||
"<ItemGroup>" + |
|||
"<ProjectReference Include=\"..\\Blazoor.EfCore07062034.Domain.Shared\\Blazoor.EfCore07062034.Domain.Shared.csproj\" />" + |
|||
"</ItemGroup>" + |
|||
"<ItemGroup>" + |
|||
"< PackageReference Include = \"Volo.Abp.Emailing\" Version= \"12.8.3-beta.1\" />" + |
|||
"</ItemGroup>" + |
|||
"</Project>"; |
|||
|
|||
var success = SolutionAbpVersionFinder.TryParseSemanticVersionFromCsprojFile(csprojContent, out var version); |
|||
success.ShouldBe(true); |
|||
version.Major.ShouldBe(12); |
|||
version.Minor.ShouldBe(8); |
|||
version.Patch.ShouldBe(3); |
|||
version.Release.ShouldBe("beta.1"); |
|||
} |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
import { ConfigStateService, featuresFactory, noop } from '@abp/ng.core'; |
|||
import { APP_INITIALIZER, inject, InjectionToken } from '@angular/core'; |
|||
import { Observable } from 'rxjs'; |
|||
import { map } from 'rxjs/operators'; |
|||
|
|||
export const SETTING_MANAGEMENT_FEATURES = new InjectionToken<Observable<{ enable: boolean }>>( |
|||
'SETTING_MANAGEMENT_FEATURES', |
|||
{ |
|||
providedIn: 'root', |
|||
factory: () => { |
|||
const configState = inject(ConfigStateService); |
|||
const featureKey = 'SettingManagement.Enable'; |
|||
const mapFn = features => ({ |
|||
enable: features[featureKey].toLowerCase() !== 'false', |
|||
}); |
|||
return featuresFactory(configState, [featureKey], mapFn); |
|||
}, |
|||
}, |
|||
); |
|||
|
|||
export const SETTING_MANAGEMENT_ROUTE_VISIBILITY = new InjectionToken<Observable<boolean>>( |
|||
'SETTING_MANAGEMENT_ROUTE_VISIBILITY', |
|||
{ |
|||
providedIn: 'root', |
|||
factory: () => { |
|||
const stream = inject(SETTING_MANAGEMENT_FEATURES); |
|||
return stream.pipe(map(features => features.enable)); |
|||
}, |
|||
}, |
|||
); |
|||
|
|||
export const SETTING_MANAGEMENT_FEATURES_PROVIDERS = [ |
|||
{ |
|||
provide: APP_INITIALIZER, |
|||
useFactory: noop, |
|||
deps: [SETTING_MANAGEMENT_ROUTE_VISIBILITY], |
|||
multi: true, |
|||
}, |
|||
]; |
|||
@ -1,2 +1,3 @@ |
|||
export * from './route.provider'; |
|||
export * from './setting-tab.provider'; |
|||
export * from './visible.provider'; |
|||
|
|||
@ -0,0 +1,30 @@ |
|||
import { APP_INITIALIZER, Injector } from '@angular/core'; |
|||
import { combineLatest } from 'rxjs'; |
|||
import { RoutesService } from '@abp/ng.core'; |
|||
import { SETTING_MANAGEMENT_HAS_SETTING } from './route.provider'; |
|||
import { SETTING_MANAGEMENT_ROUTE_VISIBILITY } from './features.token'; |
|||
import { eSettingManagementRouteNames } from '../enums'; |
|||
|
|||
export const SETTING_MANAGEMENT_VISIBLE_PROVIDERS = [ |
|||
{ |
|||
provide: APP_INITIALIZER, |
|||
useFactory: setSettingManagementVisibility, |
|||
deps: [Injector], |
|||
multi: true, |
|||
}, |
|||
]; |
|||
|
|||
export function setSettingManagementVisibility(injector: Injector) { |
|||
return () => { |
|||
const settingManagementHasSetting$ = injector.get(SETTING_MANAGEMENT_HAS_SETTING); |
|||
const isSettingManagementFeatureEnable$ = injector.get(SETTING_MANAGEMENT_ROUTE_VISIBILITY); |
|||
const routes = injector.get(RoutesService); |
|||
combineLatest([settingManagementHasSetting$, isSettingManagementFeatureEnable$]).subscribe( |
|||
([settingManagementHasSetting, isSettingManagementFeatureEnable]) => { |
|||
routes.patch(eSettingManagementRouteNames.Settings, { |
|||
invisible: !(settingManagementHasSetting && isSettingManagementFeatureEnable), |
|||
}); |
|||
}, |
|||
); |
|||
}; |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue