我是如何实现站点多语言?
9/19/2024
3
首先,站点默认语言使用英语(EN),支持(中文)CN->EN,EN->CN切换;所以我创建了一个枚举类,如下:
csharp
public enum SupportLanguage
{
/// <summary>
/// 未设置
/// </summary>
NONE = 0,
/// <summary>
/// 中文简体
/// </summary>
[Description("中文")]
[Label("中文")]
CN = 1,
/// <summary>
/// 英文
/// </summary>
[Description("英文")]
[Label("English")]
EN = 2
}
站点默认语言也可以根据客户端地区来,这样是真正的全球化。可以通过请求的header中accept-language获取,也可以通过前端传客户端时区进行识别。
我通过客户端ip作为标识,将用户设置的语种写入缓存,每次多语言应用时调用索引器显示,这里有个本地化核心接口:
csharp
/// <summary>
/// 单例模式注入
/// </summary>
public interface ILocalization
{
/// <summary>
/// 获取默认语种
/// </summary>
/// <param name="ip">客户端IP</param>
/// <returns></returns>
SupportLanguage GetDefaultLanguage(string? ip = default);
/// <summary>
/// 用户设置语言
/// </summary>
/// <param name="lan">语种value</param>
/// <returns></returns>
void SetUserLanguage(int lan);
/// <summary>
/// 获取当前语种对应翻译
/// </summary>
/// <param name="key">多语言KEY,唯一</param>
/// <param name="defaultContent">默认内容</param>
/// <param name="args">占位符参数</param>
/// <returns></returns>
string this[string key, string? defaultContent = default, params string[] args] { get; }
/// <summary>
/// 初始化
/// </summary>
void Initialization();
}
在程序一启动时,我使用后台服务,初始化了ILocalization.Initialization();
,这个初始化方法将多语言配置json加载到冻结字典(FrozenDictionary
)中,这样就能快速读取;代码:
csharp
public void Initialization()
{
if (_keyValuePairs == null)
{
lock (_lockObj)
{
_keyValuePairs ??= new ConcurrentDictionary<string, string>();
}
}
var dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Localization");
if (Directory.Exists(dir))
{
var strs = Directory.GetFiles(dir);
foreach (var item in strs)
{
var file = new FileInfo(item);
if (File.Exists(item))
{
var suffix = Path.GetExtension(item);
var lan = file.Name.Replace(suffix, "").ToUpper();
using var stream = file.OpenRead();
try
{
var map = JsonSerializer.Deserialize<Dictionary<string, string>>(stream);
if (map != null)
{
foreach (var mapItem in map)
{
var key = string.Concat(mapItem.Key, "_", lan);
_keyValuePairs.TryAdd(key, mapItem.Value);
}
}
}
catch (Exception) { }
}
}
_readMap = _keyValuePairs.ToFrozenDictionary();
}
}
多语言文件:
多语言示例:
EN.json
json
{
"Home": "Home",
"Posts": "Posts",
"Archive": "Archive",
"About": "About",
"Title": "Cracker"
}
CN.json
json
{
"Home": "首页",
"Posts": "帖子",
"Archive": "归档",
"About": "关于",
"Title": "潜心驿站"
}
json的key,value对应刚好是字典的key,value;只不过字典的key后面拼了语种"_CN"或"_EN"
翻译中可能需要占位符,所以我设计了读取方法有参数;避免key可能不存在导致的空显示,我还增加了默认内容
完全所有功能后,我们再去替换需要多语言的地方,如:
razor
<h5 class="mb-4">@localization["MyProjects","My Projects"]</h5>
综上所述,适合适合个人网站,公司官网的多语言/全球化功能就轻松实现了;如果我们要新增语种,只需要新加枚举,新加语种json翻译文件即可,代码简单,性能好。
Comments