文章目录
- 一、前言
- 二、思路
- [三、语言的存储 cache.XML](#三、语言的存储 cache.XML)
-
- 1、建cache.xml
- [2、读写Helper CacheHelper.cs](#2、读写Helper CacheHelper.cs)
- 四、双语实现
-
- 1、建JSON
- [2、建读取 LangHelper.cs](#2、建读取 LangHelper.cs)
- 五、调用
-
- [1、Program.cs 缓存语言](#1、Program.cs 缓存语言)
- 2、frmMain中
- 总结:
一、前言
好久没写了,记录一个winform双语实现。

之前使用Winform自带的 resx 实现双语,出现 控件跑位、各版本部对齐、翻译好的文本莫名丢失的情况。 一怒之下自己写了个实现。
二、思路
1、中文、英文两个Josn文件
2、读取helper
3、Form_Load里 给控制Text初始化
4、Program.cs里 先初始化 语言类型
发现少了一个存语言的,建一个cache.XML
三、语言的存储 cache.XML
1、建cache.xml
csharp
<?xml version="1.0" encoding="utf-8"?>
<SystemConfigure>
<Language>zh-CN</Language>
</SystemConfigure>
2、读写Helper CacheHelper.cs
csharp
using Org.BouncyCastle.Ocsp;
using System;
using System.Diagnostics;
using System.Net.NetworkInformation;
using System.Xml;
/// <summary>
/// 配置状态缓存 读写类
/// </summary>
public class CacheHelper
{
// 你的XML文件路径(按实际修改)
private static readonly string XmlPath = Path.Combine(
AppDomain.CurrentDomain.BaseDirectory,
"LocalCache.xml"
);
public static string ReadLgg()
{
return ReadData("Language");
}
/// <summary>
/// 修改并保存 FileSrcs 节点
/// </summary>
public static bool WriteLgg(string req)
{
return WriteData("Language", req);
}
/// <summary>
/// 读取 节点
/// </summary>
public static string ReadData(string key)
{
try
{
XmlDocument doc = new XmlDocument();
doc.Load(XmlPath);
return doc.SelectSingleNode("SystemConfigure/" + key).InnerText;
}
catch
{
return "";
}
}
/// <summary>
/// 修改并保存 节点
/// </summary>
public static bool WriteData(string key, string value)
{
try
{
XmlDocument doc = new XmlDocument();
doc.Load(XmlPath);
doc.SelectSingleNode("SystemConfigure/" + key).InnerText = value;
doc.Save(XmlPath);
return true;
}
catch
{
return false;
}
}
}
切换语言的缓存:
CacheHelper.WriteLgg("zh-CN");
CacheHelper.WriteLgg("en-US");
四、双语实现

1、建JSON
csharp
//lang.en-US.json
{
"main": {
"Text": "MainForm",
"button1": "CN/EN",
"label1": "This is a test",
},
"setting": {
"Text": "Testfrom",
}
}
//lang.zh-CN.json
{
"main": {
"Text": "主窗体",
"button1": "中文 / English",
"label1": "这是个测试",
},
"setting": {
"Text": "测试窗体",
}
}
2、建读取 LangHelper.cs
csharp
using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
public static class Lang
{
// 顶级是main/setting,每个里面都是键值对,最简单的结构
private static Dictionary<string, Dictionary<string, string>> _lang;
public static string CurrentLang { get; private set; } = "zh-CN";
public static void LoadLang(string langCode)
{
try
{
CurrentLang = langCode;
string langFile = (langCode.ToLower().Contains("zh") ? "lang.zh-CN.json" : "lang.en-US.json");
string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Language", langFile);
// 用Newtonsoft.Json反序列化,最稳妥,不会有任何坑
string json = File.ReadAllText(path);
_lang = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>(json);
}
catch(Exception ex)
{
_lang = new Dictionary<string, Dictionary<string, string>>();
}
}
public static string T(string key)
{
if (_lang == null || string.IsNullOrEmpty(key))
return key;
try
{
string[] parts = key.Split('.');
if (parts.Length == 2 && _lang.TryGetValue(parts[0], out var section))
{
if (section.TryGetValue(parts[1], out var value))
return value;
}
return key;
}
catch
{
return key;
}
}
}
五、调用
1、Program.cs 缓存语言
csharp
static void Main()
{
ApplicationConfiguration.Initialize();
// 读取本地保存的语言
string lang = CacheHelper.ReadLgg();
Lang.LoadLang(lang);
//-end
Application.Run(new frmMain());
}
2、frmMain中
csharp
//刷新语言
private void RefreshLang()
{
// 窗体标题
this.Text = Lang.T("main.Text");
// 按钮
button1.Text = Lang.T("main.button1");
// 标签
label1.Text = Lang.T("main.label1");
}
//窗体控件 文本初始化
//记得在窗体事件里绑定Main_Load: Load += frmMain_Load;
private void frmMain_Load(object sender, EventArgs e)
{
//初始化
RefreshLang();
}
//中英切换事件
private void button1_Click(object sender, EventArgs e)
{
string lgg = CacheHelper.ReadLgg();
if (lgg == "zh-CN") lgg = "en-US";
else lgg = "zh-CN";
CacheHelper.WriteLgg(lgg);
Lang.LoadLang(lgg);
RefreshLang();
}
总结:
切换还是很丝滑的,没有VUE的 i18n 那么方便,但resx是真的坑。