Browse Source

add support static localization persistence

pull/765/head
cKey 3 years ago
parent
commit
58d1c734c5
  1. 21
      aspnet-core/LINGYUN.MicroService.All.sln
  2. 174
      aspnet-core/migrations/LY.MicroService.LocalizationManagement.DbMigrator/Migrations/20230110091142_Add-Default-Culture-Name-With-Resource-Record.Designer.cs
  3. 30
      aspnet-core/migrations/LY.MicroService.LocalizationManagement.DbMigrator/Migrations/20230110091142_Add-Default-Culture-Name-With-Resource-Record.cs
  4. 5
      aspnet-core/migrations/LY.MicroService.LocalizationManagement.DbMigrator/Migrations/LocalizationManagementMigrationsDbContextModelSnapshot.cs
  5. 3
      aspnet-core/modules/localization/LINGYUN.Abp.Localization.Persistence/FodyWeavers.xml
  6. 30
      aspnet-core/modules/localization/LINGYUN.Abp.Localization.Persistence/FodyWeavers.xsd
  7. 16
      aspnet-core/modules/localization/LINGYUN.Abp.Localization.Persistence/LINGYUN.Abp.Localization.Persistence.csproj
  8. 15
      aspnet-core/modules/localization/LINGYUN.Abp.Localization.Persistence/LINGYUN/Abp/Localization/Persistence/AbpLocalizationPersistenceModule.cs
  9. 35
      aspnet-core/modules/localization/LINGYUN.Abp.Localization.Persistence/LINGYUN/Abp/Localization/Persistence/AbpLocalizationPersistenceOptions.cs
  10. 8
      aspnet-core/modules/localization/LINGYUN.Abp.Localization.Persistence/LINGYUN/Abp/Localization/Persistence/IStaticLocalizationSaver.cs
  11. 28
      aspnet-core/modules/localization/LINGYUN.Abp.Localization.Persistence/LINGYUN/Abp/Localization/Persistence/StaticLocalizationSaverHostService.cs
  12. 41
      aspnet-core/modules/localization/LINGYUN.Abp.Localization.Persistence/README.md
  13. 19
      aspnet-core/modules/localization/LINGYUN.Abp.Localization/LINGYUN.Abp.Localization.csproj
  14. 1
      aspnet-core/modules/lt/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN/Abp/LocalizationManagement/ResourceConsts.cs
  15. 3
      aspnet-core/modules/lt/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN.Abp.LocalizationManagement.Domain.csproj
  16. 16
      aspnet-core/modules/lt/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/AbpLocalizationManagementDomainModule.cs
  17. 6
      aspnet-core/modules/lt/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/ITextRepository.cs
  18. 92
      aspnet-core/modules/lt/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/LocalizationManagementExternalContributor.cs
  19. 11
      aspnet-core/modules/lt/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/Resource.cs
  20. 124
      aspnet-core/modules/lt/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/StaticLocalizationSaver.cs
  21. 15
      aspnet-core/modules/lt/LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore/LINGYUN/Abp/LocalizationManagement/EntityFrameworkCore/EfCoreTextRepository.cs
  22. 3
      aspnet-core/modules/lt/LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore/LINGYUN/Abp/LocalizationManagement/EntityFrameworkCore/LocalizationDbContextModelBuilderExtensions.cs
  23. 2
      aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/LocalizationManagementHttpApiHostModule.Configure.cs
  24. 12
      aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/appsettings.Development.json

21
aspnet-core/LINGYUN.MicroService.All.sln

@ -521,7 +521,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "platform", "platform", "{F2
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "realtime-message", "realtime-message", "{B1AC656F-8F4C-43D5-B5A0-CCF5F119EA44}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LY.MicroService.BackendAdmin.DbMigrator", "migrations\LY.MicroService.BackendAdmin.DbMigrator\LY.MicroService.BackendAdmin.DbMigrator.csproj", "{EA144C64-CE14-40DF-A876-5D302A4FC208}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LY.MicroService.BackendAdmin.DbMigrator", "migrations\LY.MicroService.BackendAdmin.DbMigrator\LY.MicroService.BackendAdmin.DbMigrator.csproj", "{EA144C64-CE14-40DF-A876-5D302A4FC208}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LY.MicroService.AuthServer.DbMigrator", "migrations\LY.MicroService.AuthServer.DbMigrator\LY.MicroService.AuthServer.DbMigrator.csproj", "{D25156E6-532F-4BCC-8EE0-8A3F1986E10E}"
EndProject
@ -535,17 +535,19 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LY.MicroService.RealtimeMes
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "notifications", "notifications", "{1A23BB7F-1839-4204-88C5-7E9A6C9FBF1E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Notifications.Domain.Shared", "modules\notifications\LINGYUN.Abp.Notifications.Domain.Shared\LINGYUN.Abp.Notifications.Domain.Shared.csproj", "{4CF6F78C-22BE-46C4-BC9B-824E8FEEF719}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Domain.Shared", "modules\notifications\LINGYUN.Abp.Notifications.Domain.Shared\LINGYUN.Abp.Notifications.Domain.Shared.csproj", "{4CF6F78C-22BE-46C4-BC9B-824E8FEEF719}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Notifications.Domain", "modules\notifications\LINGYUN.Abp.Notifications.Domain\LINGYUN.Abp.Notifications.Domain.csproj", "{CDD4CC0F-5493-40C2-B889-3670263888D8}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Domain", "modules\notifications\LINGYUN.Abp.Notifications.Domain\LINGYUN.Abp.Notifications.Domain.csproj", "{CDD4CC0F-5493-40C2-B889-3670263888D8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Notifications.EntityFrameworkCore", "modules\notifications\LINGYUN.Abp.Notifications.EntityFrameworkCore\LINGYUN.Abp.Notifications.EntityFrameworkCore.csproj", "{F74AAE01-7B87-44CA-85ED-9A6307D51504}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.EntityFrameworkCore", "modules\notifications\LINGYUN.Abp.Notifications.EntityFrameworkCore\LINGYUN.Abp.Notifications.EntityFrameworkCore.csproj", "{F74AAE01-7B87-44CA-85ED-9A6307D51504}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Notifications.Application.Contracts", "modules\notifications\LINGYUN.Abp.Notifications.Application.Contracts\LINGYUN.Abp.Notifications.Application.Contracts.csproj", "{E3F010C7-6C96-4EEA-B5FA-BF80515E195F}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Application.Contracts", "modules\notifications\LINGYUN.Abp.Notifications.Application.Contracts\LINGYUN.Abp.Notifications.Application.Contracts.csproj", "{E3F010C7-6C96-4EEA-B5FA-BF80515E195F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Notifications.Application", "modules\notifications\LINGYUN.Abp.Notifications.Application\LINGYUN.Abp.Notifications.Application.csproj", "{B153F98A-7DA9-4A12-A1D7-105BE9408FA1}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Application", "modules\notifications\LINGYUN.Abp.Notifications.Application\LINGYUN.Abp.Notifications.Application.csproj", "{B153F98A-7DA9-4A12-A1D7-105BE9408FA1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Notifications.HttpApi", "modules\notifications\LINGYUN.Abp.Notifications.HttpApi\LINGYUN.Abp.Notifications.HttpApi.csproj", "{EFC5C34F-81A1-4EFC-966F-50B646C54FA6}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.HttpApi", "modules\notifications\LINGYUN.Abp.Notifications.HttpApi\LINGYUN.Abp.Notifications.HttpApi.csproj", "{EFC5C34F-81A1-4EFC-966F-50B646C54FA6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Localization.Persistence", "modules\localization\LINGYUN.Abp.Localization.Persistence\LINGYUN.Abp.Localization.Persistence.csproj", "{42A0FC3F-C38E-4FF4-B78A-5ED29DF144BF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -1397,6 +1399,10 @@ Global
{EFC5C34F-81A1-4EFC-966F-50B646C54FA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EFC5C34F-81A1-4EFC-966F-50B646C54FA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EFC5C34F-81A1-4EFC-966F-50B646C54FA6}.Release|Any CPU.Build.0 = Release|Any CPU
{42A0FC3F-C38E-4FF4-B78A-5ED29DF144BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{42A0FC3F-C38E-4FF4-B78A-5ED29DF144BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{42A0FC3F-C38E-4FF4-B78A-5ED29DF144BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{42A0FC3F-C38E-4FF4-B78A-5ED29DF144BF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -1663,6 +1669,7 @@ Global
{E3F010C7-6C96-4EEA-B5FA-BF80515E195F} = {1A23BB7F-1839-4204-88C5-7E9A6C9FBF1E}
{B153F98A-7DA9-4A12-A1D7-105BE9408FA1} = {1A23BB7F-1839-4204-88C5-7E9A6C9FBF1E}
{EFC5C34F-81A1-4EFC-966F-50B646C54FA6} = {1A23BB7F-1839-4204-88C5-7E9A6C9FBF1E}
{42A0FC3F-C38E-4FF4-B78A-5ED29DF144BF} = {90E88EAC-4291-4406-8D88-EFDF61B11292}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C95FDF91-16F2-4A8B-A4BE-0E62D1B66718}

174
aspnet-core/migrations/LY.MicroService.LocalizationManagement.DbMigrator/Migrations/20230110091142_Add-Default-Culture-Name-With-Resource-Record.Designer.cs

@ -0,0 +1,174 @@
// <auto-generated />
using System;
using LY.MicroService.LocalizationManagement.DbMigrator.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Volo.Abp.EntityFrameworkCore;
#nullable disable
namespace LY.MicroService.LocalizationManagement.DbMigrator.Migrations
{
[DbContext(typeof(LocalizationManagementMigrationsDbContext))]
[Migration("20230110091142_Add-Default-Culture-Name-With-Resource-Record")]
partial class AddDefaultCultureNameWithResourceRecord
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.MySql)
.HasAnnotation("ProductVersion", "7.0.1")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("LINGYUN.Abp.LocalizationManagement.Language", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<string>("CultureName")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)")
.HasColumnName("CultureName");
b.Property<string>("DisplayName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("varchar(64)")
.HasColumnName("DisplayName");
b.Property<bool>("Enable")
.ValueGeneratedOnAdd()
.HasColumnType("tinyint(1)")
.HasDefaultValue(true);
b.Property<string>("FlagIcon")
.HasMaxLength(30)
.HasColumnType("varchar(30)")
.HasColumnName("FlagIcon");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime(6)")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("char(36)")
.HasColumnName("LastModifierId");
b.Property<string>("UiCultureName")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)")
.HasColumnName("UiCultureName");
b.HasKey("Id");
b.HasIndex("CultureName");
b.ToTable("AbpLocalizationLanguages", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.LocalizationManagement.Resource", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<string>("DefaultCultureName")
.HasMaxLength(64)
.HasColumnType("varchar(64)")
.HasColumnName("DefaultCultureName");
b.Property<string>("Description")
.HasMaxLength(64)
.HasColumnType("varchar(64)")
.HasColumnName("Description");
b.Property<string>("DisplayName")
.HasMaxLength(64)
.HasColumnType("varchar(64)")
.HasColumnName("DisplayName");
b.Property<bool>("Enable")
.ValueGeneratedOnAdd()
.HasColumnType("tinyint(1)")
.HasDefaultValue(true);
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime(6)")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("char(36)")
.HasColumnName("LastModifierId");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("varchar(50)")
.HasColumnName("Name");
b.HasKey("Id");
b.HasIndex("Name");
b.ToTable("AbpLocalizationResources", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.LocalizationManagement.Text", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("CultureName")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)")
.HasColumnName("CultureName");
b.Property<string>("Key")
.IsRequired()
.HasMaxLength(512)
.HasColumnType("varchar(512)")
.HasColumnName("Key");
b.Property<string>("ResourceName")
.HasColumnType("longtext");
b.Property<string>("Value")
.HasMaxLength(2048)
.HasColumnType("varchar(2048)")
.HasColumnName("Value");
b.HasKey("Id");
b.HasIndex("Key");
b.ToTable("AbpLocalizationTexts", (string)null);
});
#pragma warning restore 612, 618
}
}
}

30
aspnet-core/migrations/LY.MicroService.LocalizationManagement.DbMigrator/Migrations/20230110091142_Add-Default-Culture-Name-With-Resource-Record.cs

@ -0,0 +1,30 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace LY.MicroService.LocalizationManagement.DbMigrator.Migrations
{
/// <inheritdoc />
public partial class AddDefaultCultureNameWithResourceRecord : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "DefaultCultureName",
table: "AbpLocalizationResources",
type: "varchar(64)",
maxLength: 64,
nullable: true)
.Annotation("MySql:CharSet", "utf8mb4");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "DefaultCultureName",
table: "AbpLocalizationResources");
}
}
}

5
aspnet-core/migrations/LY.MicroService.LocalizationManagement.DbMigrator/Migrations/LocalizationManagementMigrationsDbContextModelSnapshot.cs

@ -92,6 +92,11 @@ namespace LY.MicroService.LocalizationManagement.DbMigrator.Migrations
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<string>("DefaultCultureName")
.HasMaxLength(64)
.HasColumnType("varchar(64)")
.HasColumnName("DefaultCultureName");
b.Property<string>("Description")
.HasMaxLength(64)
.HasColumnType("varchar(64)")

3
aspnet-core/modules/localization/LINGYUN.Abp.Localization.Persistence/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
aspnet-core/modules/localization/LINGYUN.Abp.Localization.Persistence/FodyWeavers.xsd

@ -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>

16
aspnet-core/modules/localization/LINGYUN.Abp.Localization.Persistence/LINGYUN.Abp.Localization.Persistence.csproj

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Localization" Version="$(VoloAbpPackageVersion)" />
<PackageReference Include="Polly" Version="$(PollyPackageVersion)" />
</ItemGroup>
</Project>

15
aspnet-core/modules/localization/LINGYUN.Abp.Localization.Persistence/LINGYUN/Abp/Localization/Persistence/AbpLocalizationPersistenceModule.cs

@ -0,0 +1,15 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Localization.Persistence;
[DependsOn(
typeof(AbpLocalizationModule))]
public class AbpLocalizationPersistenceModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddHostedService<StaticLocalizationSaverHostService>();
}
}

35
aspnet-core/modules/localization/LINGYUN.Abp.Localization.Persistence/LINGYUN/Abp/Localization/Persistence/AbpLocalizationPersistenceOptions.cs

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using Volo.Abp.Localization;
namespace LINGYUN.Abp.Localization.Persistence;
public class AbpLocalizationPersistenceOptions
{
public bool SaveStaticLocalizationsToPersistence { get; set; }
public HashSet<string> SaveToPersistenceResources { get; }
public AbpLocalizationPersistenceOptions()
{
SaveStaticLocalizationsToPersistence = true;
SaveToPersistenceResources = new HashSet<string>();
}
public void AddPersistenceResource<TResource>()
{
AddPersistenceResource(typeof(TResource));
}
public void AddPersistenceResource(Type resourceType)
{
var resourceName = LocalizationResourceNameAttribute.GetName(resourceType);
if (SaveToPersistenceResources.Contains(resourceName))
{
return;
}
SaveToPersistenceResources.Add(resourceName);
}
}

8
aspnet-core/modules/localization/LINGYUN.Abp.Localization.Persistence/LINGYUN/Abp/Localization/Persistence/IStaticLocalizationSaver.cs

@ -0,0 +1,8 @@
using System.Threading.Tasks;
namespace LINGYUN.Abp.Localization.Persistence;
public interface IStaticLocalizationSaver
{
Task SaveAsync();
}

28
aspnet-core/modules/localization/LINGYUN.Abp.Localization.Persistence/LINGYUN/Abp/Localization/Persistence/StaticLocalizationSaverHostService.cs

@ -0,0 +1,28 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using System.Threading;
using System.Threading.Tasks;
namespace LINGYUN.Abp.Localization.Persistence;
public class StaticLocalizationSaverHostService : BackgroundService
{
private readonly AbpLocalizationPersistenceOptions _options;
private readonly IStaticLocalizationSaver _staticLocalizationSaver;
public StaticLocalizationSaverHostService(
IOptions<AbpLocalizationPersistenceOptions> options,
IStaticLocalizationSaver staticLocalizationSaver)
{
_options = options.Value;
_staticLocalizationSaver = staticLocalizationSaver;
}
protected async override Task ExecuteAsync(CancellationToken stoppingToken)
{
if (_options.SaveStaticLocalizationsToPersistence)
{
await _staticLocalizationSaver.SaveAsync();
}
}
}

41
aspnet-core/modules/localization/LINGYUN.Abp.Localization.Persistence/README.md

@ -0,0 +1,41 @@
# LINGYUN.Abp.Localization.Persistence
## 模块说明
本地化组件持久层模块, 引用模块可将需要的本地化文档持久化到存储设施
### 基础模块
### 高阶模块
### 权限定义
### 功能定义
### 配置定义
### 如何使用
```csharp
[DependsOn(
typeof(AbpLocalizationPersistenceModule))]
public class YouProjectModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpLocalizationPersistenceOptions>(options =>
{
// 启用持久化设施
options.SaveStaticLocalizationsToPersistence = true;
// 指定你的本地化资源类型, 此类型下定义的静态文档将被持久化到存储设施
options.AddPersistenceResource<YouProjectResource>();
});
}
}
```
### 更新日志

19
aspnet-core/modules/localization/LINGYUN.Abp.Localization/LINGYUN.Abp.Localization.csproj

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Localization" Version="$(VoloAbpPackageVersion)" />
</ItemGroup>
<ItemGroup>
<Folder Include="LINGYUN\Abp\Localization\" />
</ItemGroup>
</Project>

1
aspnet-core/modules/lt/LINGYUN.Abp.LocalizationManagement.Domain.Shared/LINGYUN/Abp/LocalizationManagement/ResourceConsts.cs

@ -5,5 +5,6 @@
public static int MaxNameLength { get; set; } = 50;
public static int MaxDisplayNameLength { get; set; } = 64;
public static int MaxDescriptionLength { get; set; } = 64;
public static int MaxDefaultCultureNameLength { get; set; } = 64;
}
}

3
aspnet-core/modules/lt/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN.Abp.LocalizationManagement.Domain.csproj

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
@ -14,6 +14,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\localization\LINGYUN.Abp.Localization.Persistence\LINGYUN.Abp.Localization.Persistence.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.LocalizationManagement.Domain.Shared\LINGYUN.Abp.LocalizationManagement.Domain.Shared.csproj" />
</ItemGroup>

16
aspnet-core/modules/lt/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/AbpLocalizationManagementDomainModule.cs

@ -1,13 +1,17 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AutoMapper;
using Volo.Abp.Domain;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using LINGYUN.Abp.Localization.Persistence;
using LINGYUN.Abp.LocalizationManagement.Localization;
namespace LINGYUN.Abp.LocalizationManagement
{
[DependsOn(
typeof(AbpAutoMapperModule),
typeof(AbpDddDomainModule),
typeof(AbpLocalizationPersistenceModule),
typeof(AbpLocalizationManagementDomainSharedModule))]
public class AbpLocalizationManagementDomainModule : AbpModule
{
@ -20,6 +24,16 @@ namespace LINGYUN.Abp.LocalizationManagement
options.AddProfile<LocalizationManagementDomainMapperProfile>(validate: true);
});
Configure<AbpLocalizationOptions>(options =>
{
options.GlobalContributors.Add<LocalizationManagementExternalContributor>();
});
Configure<AbpLocalizationPersistenceOptions>(options =>
{
options.AddPersistenceResource<LocalizationManagementResource>();
});
// 分布式事件
//Configure<AbpDistributedEntityEventOptions>(options =>
//{

6
aspnet-core/modules/lt/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/ITextRepository.cs

@ -7,6 +7,12 @@ namespace LINGYUN.Abp.LocalizationManagement
{
public interface ITextRepository : IRepository<Text, int>
{
Task<List<string>> GetExistsKeysAsync(
string resourceName,
string cultureName,
IEnumerable<string> keys,
CancellationToken cancellationToken = default);
Task<Text> GetByCultureKeyAsync(
string resourceName,
string cultureName,

92
aspnet-core/modules/lt/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/LocalizationManagementExternalContributor.cs

@ -0,0 +1,92 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Localization;
namespace LINGYUN.Abp.LocalizationManagement;
public class LocalizationManagementExternalContributor : ILocalizationResourceContributor
{
public bool IsDynamic => true;
private LocalizationResourceBase _resource;
private ITextRepository _textRepository;
private IResourceRepository _resourceRepository;
private ILanguageRepository _languageRepository;
public void Initialize(LocalizationResourceInitializationContext context)
{
_resource = context.Resource;
_textRepository = context.ServiceProvider.GetRequiredService<ITextRepository>();
_resourceRepository = context.ServiceProvider.GetRequiredService<IResourceRepository>();
_languageRepository = context.ServiceProvider.GetRequiredService<ILanguageRepository>();
}
public virtual void Fill(string cultureName, Dictionary<string, LocalizedString> dictionary)
{
FillInternalAsync(_resource.ResourceName, cultureName, dictionary).GetAwaiter().GetResult();
}
public async virtual Task FillAsync(string cultureName, Dictionary<string, LocalizedString> dictionary)
{
await FillInternalAsync(_resource.ResourceName, cultureName, dictionary);
}
public virtual LocalizedString GetOrNull(string cultureName, string name)
{
return GetOrNullInternal(_resource.ResourceName, cultureName, name);
}
protected virtual LocalizedString GetOrNullInternal(string resourceName, string cultureName, string name)
{
var resource = GetResourceOrNullAsync(name).GetAwaiter().GetResult();
if (resource == null)
{
return null;
}
var text = _textRepository.GetByCultureKeyAsync(resourceName, cultureName, name).GetAwaiter().GetResult();
if (text != null)
{
return new LocalizedString(name, text.Value);
}
return null;
}
public async virtual Task<IEnumerable<string>> GetSupportedCulturesAsync()
{
var languages = await _languageRepository.GetActivedListAsync();
return languages
.Select(x => x.CultureName)
.ToList();
}
protected async virtual Task FillInternalAsync(string resourceName, string cultureName, Dictionary<string, LocalizedString> dictionary)
{
var resource = await GetResourceOrNullAsync(resourceName);
if (resource == null)
{
return;
}
var texts = await GetTextListByResourceAsync(resourceName, cultureName);
foreach (var text in texts)
{
dictionary[text.Key] = new LocalizedString(text.Key, text.Value);
}
}
protected async virtual Task<Resource> GetResourceOrNullAsync(string resourceName)
{
return await _resourceRepository.FindByNameAsync(resourceName);
}
protected async virtual Task<List<Text>> GetTextListByResourceAsync(string resourceName, string cultureName = null)
{
return await _textRepository.GetListAsync(resourceName, cultureName);
}
}

11
aspnet-core/modules/lt/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/Resource.cs

@ -11,18 +11,21 @@ namespace LINGYUN.Abp.LocalizationManagement
public virtual string Name { get; set; }
public virtual string DisplayName { get; set; }
public virtual string Description { get; set; }
public virtual string DefaultCultureName { get; set; }
protected Resource() { }
public Resource(
[NotNull] string name,
[CanBeNull] string displayName = null,
[CanBeNull] string description = null)
[CanBeNull] string description = null,
[CanBeNull] string defaultCultureName = null)
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name), ResourceConsts.MaxNameLength);
DisplayName = displayName ?? Name;
Description = description;
DisplayName = Check.Length(displayName ?? Name, nameof(displayName), ResourceConsts.MaxDisplayNameLength);;
Description = Check.Length(description, nameof(description), ResourceConsts.MaxDescriptionLength);
DefaultCultureName = Check.Length(defaultCultureName, nameof(defaultCultureName), ResourceConsts.MaxDefaultCultureNameLength);
Enable = true;
Enable = true;
}
}
}

124
aspnet-core/modules/lt/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/StaticLocalizationSaver.cs

@ -0,0 +1,124 @@
using LINGYUN.Abp.Localization.Persistence;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Localization;
using Volo.Abp.Uow;
namespace LINGYUN.Abp.LocalizationManagement;
[Dependency(ReplaceServices = true)]
public class StaticLocalizationSaver : IStaticLocalizationSaver, ITransientDependency
{
protected ILanguageRepository LanguageRepository { get; }
protected ITextRepository TextRepository { get; }
protected IResourceRepository ResourceRepository { get; }
protected IStringLocalizerFactory StringLocalizerFactory { get; }
protected AbpLocalizationOptions LocalizationOptions { get; }
protected IServiceProvider ServiceProvider { get; }
protected AbpLocalizationPersistenceOptions LocalizationPersistenceOptions { get; }
public StaticLocalizationSaver(
IServiceProvider serviceProvider,
ILanguageRepository languageRepository,
ITextRepository textRepository,
IResourceRepository resourceRepository,
IStringLocalizerFactory stringLocalizerFactory,
IOptions<AbpLocalizationOptions> localizationOptions,
IOptions<AbpLocalizationPersistenceOptions> localizationPersistenceOptions)
{
ServiceProvider = serviceProvider;
LanguageRepository = languageRepository;
TextRepository = textRepository;
ResourceRepository = resourceRepository;
StringLocalizerFactory = stringLocalizerFactory;
LocalizationOptions = localizationOptions.Value;
LocalizationPersistenceOptions = localizationPersistenceOptions.Value;
}
[UnitOfWork]
public async virtual Task SaveAsync()
{
var insertNewTexts = new List<Text>();
foreach (var language in LocalizationOptions.Languages)
{
if (await LanguageRepository.FindByCultureNameAsync(language.CultureName) == null)
{
await LanguageRepository.InsertAsync(
new Language(
language.CultureName,
language.UiCultureName,
language.DisplayName,
language.FlagIcon));
}
foreach (var resource in LocalizationPersistenceOptions.SaveToPersistenceResources)
{
using (CultureHelper.Use(language.CultureName, language.UiCultureName))
{
var localizationResource = LocalizationOptions.Resources.GetOrDefault(resource);
if (localizationResource == null)
{
continue;
}
var context = new LocalizationResourceInitializationContext(localizationResource, ServiceProvider);
if (await ResourceRepository.FindByNameAsync(localizationResource.ResourceName) == null)
{
await ResourceRepository.InsertAsync(
new Resource(
localizationResource.ResourceName,
localizationResource.ResourceName,
localizationResource.ResourceName,
localizationResource.DefaultCultureName));
}
foreach (var contributor in localizationResource.Contributors)
{
if (contributor.IsDynamic)
{
continue;
}
contributor.Initialize(context);
var fillTexts = new Dictionary<string, LocalizedString>();
await contributor.FillAsync(language.CultureName, fillTexts);
var existsKeys = await TextRepository.GetExistsKeysAsync(
localizationResource.ResourceName,
language.CultureName,
fillTexts.Values.Select(x => x.Name));
var notExistsKeys = fillTexts.Values.Where(x => !existsKeys.Contains(x.Name));
notExistsKeys = notExistsKeys.Where(x => !insertNewTexts.Any(t => t.Key == x.Name));
foreach (var notExistsKey in notExistsKeys)
{
if (!insertNewTexts.Any(x => x.CultureName == language.CultureName && x.Key == notExistsKey.Name))
{
insertNewTexts.Add(
new Text(
localizationResource.ResourceName,
language.CultureName,
notExistsKey.Name,
notExistsKey.Value));
}
}
}
}
}
}
if (insertNewTexts.Any())
{
await TextRepository.InsertManyAsync(insertNewTexts);
}
}
}

15
aspnet-core/modules/lt/LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore/LINGYUN/Abp/LocalizationManagement/EntityFrameworkCore/EfCoreTextRepository.cs

@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
@ -18,6 +19,20 @@ namespace LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore
{
}
public async virtual Task<List<string>> GetExistsKeysAsync(
string resourceName,
string cultureName,
IEnumerable<string> keys,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.Where(x => x.ResourceName.Equals(resourceName) && x.CultureName.Equals(cultureName)
&& keys.Contains(x.Key))
.Select(x => x.Key)
.Distinct()
.ToListAsync(GetCancellationToken(cancellationToken));
}
public async virtual Task<Text> GetByCultureKeyAsync(
string resourceName,
string cultureName,

3
aspnet-core/modules/lt/LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore/LINGYUN/Abp/LocalizationManagement/EntityFrameworkCore/LocalizationDbContextModelBuilderExtensions.cs

@ -65,6 +65,9 @@ namespace LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore
x.Property(p => p.Description)
.HasMaxLength(ResourceConsts.MaxDescriptionLength)
.HasColumnName(nameof(Resource.Description));
x.Property(p => p.DefaultCultureName)
.HasMaxLength(ResourceConsts.MaxDefaultCultureNameLength)
.HasColumnName(nameof(Resource.DefaultCultureName));
x.Property(p => p.Enable)
.HasDefaultValue(true);

2
aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/LocalizationManagementHttpApiHostModule.Configure.cs

@ -258,7 +258,7 @@ public partial class LocalizationManagementHttpApiHostModule
if (isDevelopment)
{
// services.AddAlwaysAllowAuthorization();
services.AddAlwaysAllowAuthorization();
}
if (!isDevelopment)

12
aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/appsettings.Development.json

@ -1,6 +1,6 @@
{
"AgileConfig": {
"IsEnabled": true,
"IsEnabled": false,
"env": "DEV",
"appId": "LINGYUN.Abp.Localization",
"secret": "1q2w3E*",
@ -23,11 +23,11 @@
}
},
"ConnectionStrings": {
"Default": "Server=127.0.0.1;Database=Platform;User Id=root;Password=123456",
"AbpSaas": "Server=127.0.0.1;Database=Platform;User Id=root;Password=123456",
"AbpSettingManagement": "Server=127.0.0.1;Database=Platform;User Id=root;Password=123456",
"AbpPermissionManagement": "Server=127.0.0.1;Database=Platform;User Id=root;Password=123456",
"AbpLocalizationManagement": "Server=127.0.0.1;Database=Platform;User Id=root;Password=123456"
"Default": "Server=127.0.0.1;Database=Platform-v70;User Id=root;Password=123456",
"AbpSaas": "Server=127.0.0.1;Database=Platform-v70;User Id=root;Password=123456",
"AbpSettingManagement": "Server=127.0.0.1;Database=Platform-v70;User Id=root;Password=123456",
"AbpPermissionManagement": "Server=127.0.0.1;Database=Platform-v70;User Id=root;Password=123456",
"AbpLocalizationManagement": "Server=127.0.0.1;Database=Platform-v70;User Id=root;Password=123456"
},
"CAP": {
"EventBus": {

Loading…
Cancel
Save