English 简体中文 繁體中文 한국 사람 日本語 Deutsch русский بالعربية TÜRKÇE português คนไทย french
查看: 0|回复: 0

另类方式实现.Net下的多语言

[复制链接]
查看: 0|回复: 0

另类方式实现.Net下的多语言

[复制链接]
查看: 0|回复: 0

233

主题

0

回帖

709

积分

高级会员

积分
709
8DMfE0oYzHQE

233

主题

0

回帖

709

积分

高级会员

积分
709
2025-2-24 00:41:10 | 显示全部楼层 |阅读模式
前言

关于.Net下的多语言方案已经有很多成熟的方案,例如:# Avalonia 国际化之路:Resx 资源文件的深度应用与探索,或者# Avalonia使用XML文件实现国际化,基本都围绕官方的Satellite Assembly方案来实现。实际上,我们可以使用非常原始的方式来实现多语言。
步骤

1. resources资源文件生成

创建如下文本文件(假设为rex.txt)
Greeting=Hello将ResGen.exe从framework的工具目录(使用everything找下就可以看到)拷贝到当前目录,执行如下命令
PS D:\workSpace\Code\测试\resx> .\ResGen.exe .\rex.txtRead in 1 resources from ".\rex.txt"Writing resource file...  Done.就可以得到我们第一步的rex.resources。
说明:
ResGen.exe工具同样支持resx文件,具体使用与文件格式参考https://learn.microsoft.com/en-us/dotnet/framework/tools/resgen-exe-resource-file-generator 官方文档,事实上,这也是我们使用的IDE编辑时msbuild背后调用的工具。
2. Dll文件生成

有了resources资源文件,我们就可以通过链接器(al.exe,同样在framework的工具目录中)将resources资源文件链接成动态链接库。
PS D:\workSpace\Code\测试\resx> .\al.exe -target:lib -embed:.\rex.resources -out:Res.dllMicrosoft(R) Assembly Linker 版本 14.7.2053.0Copyright (C) Microsoft Corporation. All rights reserved.说明:

  • -target:lib代表产物为类库
  • -embed:.\rex.resources代表嵌入刚刚第一步的生成资源文件
  • -out:Res.dll 代表生成物名称
  • 使用ilspy打开就可以看到嵌入的资源文件。
  • 注意我们这里并没有指定-culture:zh-Hans参数,而官方文档说这个参数必须传(https://learn.microsoft.com/en-us/dotnet/core/extensions/create-satellite-assemblies) 是因为我们完全没使用.net的语言资源机制,也完全不用遵从其hub-and-spoke模型(指的是轮子的中心和车轮的辐条的关系模型,也就是主dll和卫星资源dll的位置关系模型)
  • 这里要对.Net下dll的结构有一定认识,大家可以参考前面链接中的图片。
  • 也可以使用-template:Example.dll来指定生成dll的元数据模版,不然生成的dll在ilspy中元数据表的TypeDef会显示<Module>这样未命名的记录。
  • 我们这里用的是链接器,其实也能用编译器(.net core下就是这样),参考前面的链接。
3. 使用

创建控制台应用,代码如下:
using System;using System.Globalization;using System.Reflection;using System.Resources;using System.Threading;namespace ConsoleApp1{    internal class Program    {        static void Main(string[] args)        {           // 手动加载刚刚链接器生成的程序集           Assembly ass = Assembly.LoadFile(@"D:\workSpace\Code\测试\resx\Res.dll");           // 第一个参数"rex"即为我们嵌入的rex.resources的文件名,第二个参数为应用程序集           ResourceManager rm = new ResourceManager("rex", ass);            var s = rm.GetString("Greeting");            Console.WriteLine(s);        }    }}输出为:
HelloD:\workSpace\Code\测试\resx\ConsoleApp1\bin\Debug\ConsoleApp1.exe (进程 5184)已退出,代码为 0 (0x0)。按任意键关闭此窗口. . .就能拿到我们定义的语言资源啦。
说明:

  • 由于我们这里是纯手工加载,Thread.CurrentThread.CurrentCulture = new CultureInfo("en-us");这样是完全没影响的,同样, 链接器的cultrue参数也不影响,大家可以自行测试。
How to:

看完这个和文章中的参考资料,应该对大家理解.Net的多语言有很大帮助。接下来就是我的方案(也许是胡说)
如果想统一在一个文件中管理整个sln的语言资源(举例一下特殊需求),可以通过msbuild自定义Task的方式(大家可以类比下编辑的Grpc的proto文件自动生成代码的过程,实际上谷歌也是这么干的),(或者结合下T4模版?)直接生成所有语言的ResourceManager字典。封装方法返回对应语言的资源,有特殊需求的可以自行尝试,如果不行就当我是胡说。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

233

主题

0

回帖

709

积分

高级会员

积分
709

QQ|智能设备 | 粤ICP备2024353841号-1

GMT+8, 2025-3-12 13:25 , Processed in 0.953520 second(s), 28 queries .

Powered by 智能设备

©2025

|网站地图