前段时间跟同事吹水聊天时,吐槽一个话题,就是公司项目都需要做多语言,前端后端都需要做。
而且是需要支持8国语言翻译,每次弄起来都特麻烦,每加一个Key就需要去翻译其他7个语言出来添加,每新增一个项目就需要弄一遍多语言资源,重复且枯燥费时的体力活。
本项目主打一个一处配置多语言,多处使用的想法。助力项目方便快捷实现国际化(多语言)。
主要解决的问题:
目前主要功能如下(目前还只是雏形,不算完善):
可配关联项目,主项目关联其他项目即可获取其他项目的多语言资源,相同Key则优先取主项目中的资源(即覆盖)
批量导入已存在项目多语言资源(目前只支持JSON格式)
多语言配置导出(目前支持json,toml,messages.properties, xml格式)
可配置自动翻译其他语言的资源(目前接入百度翻译和有道翻译API,冷门地区语言翻译暂不支持,翻译不准确时可手动修改)
API/SignalR接入
界面管理
.NET SDK 接入 (其他语言待开发)
测试环境欢迎体验并给点意见或提提ISSUE,当然欢迎PR一起完善项目。
http://47.119.20.111/Projects
http://47.119.20.111/swagger/index.html
项目地址:
https://github.com/fanslead/LinguaNex
通过API/SDK拉取多语言资源加载,可选WebSocket对接实现即时更新多语言资源。
请求地址:/api/OpenApi/Resources/{ProjectId}?cultureName=&all=
响应结构如下:
[ { "cultureName": "zh-Hans", "resources": { "Hello": "你好" } }, { "cultureName": "en", "resources": { "Hello": "Hello" } } ]
var connection = new HubConnectionBuilder() .WithUrl($"{linguaNexApiUrl}/hubs/LinguaNex?project={project}", Microsoft.AspNetCore.Http.Connections.HttpTransportType.WebSockets) .AddJsonProtocol() .WithAutomaticReconnect() .Build(); connection.On<LinguaNexResources>("CreateOrUpdateResource", obj => { if (_resourcesCache.TryGetValue(obj.CultureName, out var value)) { foreach (var resource in obj.Resources) { value[resource.Key] = resource.Value; } _resourcesCache[obj.CultureName] = value; }else { _resourcesCache[obj.CultureName] = new ConcurrentDictionary<string, string>(obj.Resources); } }); connection.StartAsync(); //拉取资源 参数跟OpenApi接口一致 connection.InvokeAsync<List<LinguaNexResources>>("GetResources", projectId, cultureName,all);
需要引用LinguaNex.Localization.Net包。
在依赖注入中添加如下代码即可:
builder.Services.AddLinguaNexLocalization(options => { options.LinguaNexApiUrl = builder.Configuration["LinguaNex:ApiUrl"]; options.Project = builder.Configuration["LinguaNex:Project"]; options.UseWebSocket = true; });
.NET SDK是通过实现IStringLocalizer接口对接的。所以可以无缝衔接已有多语言的项目切换。
本项目自身已使用SDK对接自己。
测试效果
由于目前还没时间完事前端界面的多语言配置。但是之前试过使用antd design pro接入过ABP的后端多语言的配置。
接入流程是一致的。这里提供下参考代码:
import { addLocale, getLocale } from 'umi'; import { Locale } from 'antd/es/locale'; let locale = getLocale() as string; let antdLocale = {} as Locale const applicationLocalization = await getApplicationLocalization(); // 这里可以实现接入后端API获取资源 const resources = applicationLocalization.resources const allText = {} for(let key in resources) { if(resources[key]){ Object.assign(allText, resources[key].texts) } } locale = getLocale() as string; addLocale( locale, allText, { momentLocale: antdLocale.locale, antd: antdLocale, }