C# 基于Json文件的多语言翻译功能简单实现

大致思路

将Json文件系列化储存在Dictionary中,再通过遍历指定控件及其子控件进行匹配替换。
注意:特殊需求(如:String中只局部翻译)以及个别控件(如:ToolStrip)需要自行添加处理方法,后续会详细讲解怎样去遍历特殊控件。。

具体实现及演示:

1、准备工作:
1.1 添加Json配置,网上有很多关于Json配置相关的文章不做详细讲解

        C#使用json
        点击工具 - NuGet包管理器 - 程序包管理控制台,输入下面命令: 
        Install-Package Newtonsoft.Json 
        即可使用Newtonsoft.Json 包进行json操作 
        PM> Install-Package Newtonsoft.Json

在这里插入图片描述
1.2 对应的Json文件的编辑 :key翻译为value
英译中 Json配置
{
“Test”:“测试”,
“Language”:“语言”,
“Set”:“设置”,
“Chinese (default)”:“中文(默认)”,
“English”:“英文”
}

中译英 Json配置
{
“测试”:“Test”,
“语言”:“Language”,
“设置”:“Set”,
“中文(默认)”: “Chinese (default)”,
“英文”:“English”,
“英语”:“English”
}

在这里插入图片描述

1.3 向窗体放置各种常用控件以及对其相应文本进行编辑如图
在这里插入图片描述

2、自定义翻译类库

using Newtonsoft.Json;                               //Json文件序列化
using System.Windows.Forms;                   //控件遍历所需
using System.Text.RegularExpressions;      //String处理

namespace Interpret
{
	public class InterpretBase
	{
        //下文代码
  	}
}

2.1 现有的资源加载方法

   //定义字典用于储存Json配置文件资源
    static Dictionary<string, string> resources = new Dictionary<string, string>();

    /// <summary>
    /// 当前项目文件夹Debug\Language\参数文件夹
    /// </summary>
    /// <param name="language">配置文件所在文件夹名</param>
    public static void LoadLanguage(string language = "")
    {
        if (string.IsNullOrEmpty(language))
        {
            language = System.Threading.Thread.CurrentThread.CurrentUICulture.Name;
        }

        resources = new Dictionary<string, string>();

        string dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, string.Format("Language/{0}", language));
        if (Directory.Exists(dir))
        {
            var jaonFile = Directory.GetFiles(dir, "*.json", SearchOption.AllDirectories);
            foreach (string file in jaonFile)
            {
                LoadFile(file);
            }
        }
    }

    /// <summary>
    /// 配置文件加载
    /// </summary>
    /// <param name="path">配置文件绝对路径(包括文件本身)</param>
    public static void LoadFile(string path)
    {
        var content = File.ReadAllText(path, Encoding.UTF8);
        if (!string.IsNullOrEmpty(content))
        {
            var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(content);
            foreach (string key in dict.Keys)
            {

                if (!resources.ContainsKey(key))
                {
                    resources.Add(key, dict[key]);
                }
                else
                    resources[key] = dict[key];
            }
        }
    }

2.2 普通控件的遍历(因为涉及其他相关 不能一一列举控件遍历,这里按Combox遍历,其他控件思路也是一样的)

    /// <summary>
    /// 遍历翻译 窗体或控件及其子控件
    /// </summary>
    /// <param name="control">需要翻译的控件或窗体</param>
    public static void InitLanguage(Control control)
    {
        SetControlLanguage(control);
        foreach (Control ctrl in control.Controls)
        {
            InitLanguage(ctrl);
        }

        //工具栏或者菜单动态构建窗体或者控件的时候,重新对子控件进行处理
        control.ControlAdded += (sender, e) =>
        {
            InitLanguage(e.Control);
        };
    }

    /// <summary>
    /// 控件及子控件翻译
    /// </summary>
    /// <param name="control">需要翻译的控件</param>
    public static void SetControlLanguage(Control control)
    {
        if (control is ComboBox)
        {
            ComboBox combox = control as ComboBox;
            string[] NewItems = new string[combox.Items.Count];
            for (int i = 0; i < combox.Items.Count; i++)
            {
                if (resources.ContainsKey(combox.Items[i].ToString()))
                {
                    NewItems[i] = resources[combox.Items[i].ToString()];
                }
                else
                    NewItems[i] = combox.Items[i].ToString();
            }

            combox.Text = (resources.ContainsKey(combox.Text)) ? resources[combox.Text] : combox.Text;

            combox.Items.Clear();
            combox.Items.AddRange(NewItems);
        }
        //control is 其他控件或者特殊控件 如:TreeView
        else if (control is TreeView)
        {
            //TreeView treeView = control as TreeView;
            //if (treeView.Nodes !=null)
            //{
                //TreeViewNodes(treeView.Nodes);
           //}
        }
       else
        {
            control.Text = (resources.ContainsKey(control.Text)) ? resources[control.Text] : control.Text;
        }
    }

2.3 特殊控件的遍历思路(思路基本能满足绝大多数控件,由于详细涉及其他不能完整上传 深表歉意)

特殊控件的遍历思路其实跟普通控件的遍历是一样的 只是需要根据特殊控件不同情况去遍历的特殊属性进行判断翻译就行了(按TreeView为列讲解)
注:特殊控件不知道该遍历什么属性时可以去 InitializeComponent();窗体设计器生成的代码里查找 如图下

在这里插入图片描述
遍历datagridview的列
for (int i = 0; i < datagridview.ColumnCount; i++)
从而的到每一列,便可以对列头以及列头提示进行编辑
datagridview.Columns[i].HeaderText,
datagridview.Columns[i].ToolTipText
单元格遍历遇上雷同

下图为上文中 对其他控件或者特殊控件 TreeView的遍历

    public static void TreeViewNodes(TreeNodeCollection Nodes)
    {
        for (int i = 0; i < Nodes.Count; i++)
        {
            if (Nodes[i].Text != null)
                Nodes[i].Text = (resources.ContainsKey(Nodes[i].Text)) ?
                      resources[Nodes[i].Text] : Nodes[i].Text;

            if (Nodes[i].Nodes != null)
            {
                TreeViewNodes(Nodes[i].Nodes);
            }
        }
    }

以上便是对特殊控件的遍历,找到相应的属性,遍历在替换文本

2.4 添加特殊方法 供后文用

     /// <summary>
    /// 局部匹配翻译,不存在则不翻译
    /// </summary>
    /// <param name="text">需要翻译的正则公式</param>
    public static void PartInterpret(ref string text)
    {
        if (resources.Keys == null && resources.Keys.Count == 0)
        {
            MessageBox.Show("未添加资源文件,请及时确认或与工作人员联系", "提示!!");
            return;
        }
        foreach (var item in resources)
        {
            if (text.Contains(item.Key))
            {
                text = text.Replace(item.Key, item.Value);
            }
        }
    }

在这里插入图片描述

3 调用方式及特殊情况 结果展示

using IPret = Interpret.InterpretBase;//添加引用

    string lang,oldLang;
    //语言设置  自行设置
    private void button_Click(object sender, EventArgs e)
    {
        oldLang = lang;//用于判断当前语言是否与所需要语言一致 ,避免
        lang = comboBox1.Text.ToString();//需要设置的语言
        switch (lang)
        {
            case "中文(默认)":
            case "Chinese (default)":
                lang = "zh-CN";
                break;

            case "英文":
            case "English":
                lang = "en-US";
                break;

            default:
                lang = "zh-CN";
                break;
        }

        if (oldLang != lang)
        {
            System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(lang);

            IPret.LoadLanguage(lang);
            IPret.InitLanguage(contextMenuStrip1);
            IPret.InitLanguage(this);

            #region ***********局部特殊内容翻译************
            string s = label_Test.Text;
            IPret.PartInterpret(ref s);
            label_Test.Text = s;
            oldLang = lang;
            #endregion
        }
    }

实际效果图:
翻译前
在这里插入图片描述
翻译后
在这里插入图片描述

感谢阅览,第一次发文 若有不足之处,还望指出

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值