winform项目实现国际化(语言切换)功能

方法一:使用资源文件和本地化

  1. 创建资源文件

    • 为每种语言创建一个资源文件(通常是.resx文件)。例如,可以创建"Strings.en.resx"用于存储英文字符串,创建"Strings.zh.resx"用于存储中文字符串。
  2. 加载和切换资源文件

    • 在代码中,通过ResourceManager类来加载和切换资源文件。可以根据用户的选择来动态设置当前的文化信息(CultureInfo),然后应用相应的资源文件。
  3. 应用资源到控件

    • 遍历窗体上的控件,根据控件的名称从资源文件中获取对应的字符串,并设置控件的Text属性。
  4. 优点

    • 支持多种资源类型,如字符串、图片、字体等。
    • 易于管理和维护,因为每种语言的资源都存储在单独的文件中。
  5. 缺点

    • 当窗体控件很多时,需要遍历所有控件并应用资源,可能会稍微增加一些性能开销。

方法二:使用全局变量和配置文件

  1. 定义全局变量

    • 在项目的某个公共类中定义全局变量来存储当前的语言设置。
  2. 创建配置文件

    • 创建一个配置文件(如XML或JSON文件),用于存储不同语言的字符串。
  3. 加载配置文件

    • 在程序启动时,根据当前的语言设置加载相应的配置文件。
  4. 应用配置到控件

    • 遍历窗体上的控件,根据控件的名称从配置文件中获取对应的字符串,并设置控件的Text属性。
  5. 优点

    • 灵活性较高,可以方便地添加或修改语言字符串。
    • 不需要为每个语言创建单独的资源文件。
  6. 缺点

    • 需要手动管理配置文件的加载和解析。
    • 当语言字符串较多时,配置文件可能会变得庞大且难以维护。

上面两种方法个人感觉不太适合体量大的项目,项目中的控件过多的话手动添加XML或者本地化操作会很臃肿

在网上了解到可以调用翻译接口去实现这个功能

翻译API地址:

http://api.fanyi.baidu.com/api/trans/vip/translate

我的软件框架版本是.net8

数据库SqliteDAL.cs中的代码通过递归去获取窗体控件的text

cs 复制代码
 /// <summary>
 /// 递归得到窗体中的控件TexT翻译后,插入到sqlite中
 /// </summary>
 /// <param name="form"></param>
 public void SaveControlTextsToDatabase(Form form)
 {
     //查询Report数据报表是否存在
     string checkReport = @"SELECT COUNT(1) FROM sqlite_master WHERE type='table' AND name='ControlTexts'";
     var Reportresult = SQLiteConnections.GetSingleResult(checkReport);
     if (Reportresult is long count1 && count1 == 0)
     {
         string createControlTexts = @" CREATE TABLE  ControlTexts (
                 Id INTEGER PRIMARY KEY AUTOINCREMENT,
                 ControlName TEXT NOT NULL,
                 OriginalText TEXT NOT NULL,
                 TranslatedText TEXT
                             )";
         SQLiteConnections.createProgramTable(createControlTexts, "ControlTexts");
     }


     // 遍历控件并插入数据
     InsertControlTexts(form);

 }
 private async void InsertControlTexts(Control parent)
 {
     foreach (Control control in parent.Controls)
     {
         // 只处理有Text属性的控件
         //if (control is Label || control is Button || control is MenuStrip || control is StatusStrip)
         //{
         string controlName = control.Name;
         string originalText = control.Text;
         FeedbackResult TEnglish = await TranslateUtil.TranslatePost(originalText, Language.中文, Language.英语);
         if (originalText != null)
         {
             try
             {
                 var jsonDocument = JsonDocument.Parse(TEnglish.ResponseJson!);
                 var root = jsonDocument.RootElement;

                 // 检查是否包含错误码
                 if (root.TryGetProperty("error_code", out var errorCode))
                 {
                     string errorMsg = root.GetProperty("error_msg").GetString()!;
                     Console.WriteLine($"Error: {errorCode.GetString()}, Message: {errorMsg}");
                 }
                 else if (root.TryGetProperty("trans_result", out var transResult))
                 {
                     // 提取 dst 值
                     string dst = transResult[0].GetProperty("dst").GetString()!;

                     // 查询是否存在记录
                     string selectQuery = $@"
                                             SELECT COUNT(*) 
                                             FROM ControlTexts 
                                             WHERE ControlName = '{controlName}' AND OriginalText = '{originalText}'
                                         ";

                     // 执行查询
                     var recordCount = SQLiteConnections.GetSingleResult(selectQuery);

                     if (recordCount is long count1 && count1 > 0)
                     {
                         // 如果存在,更新 TranslatedText
                         string updateQuery = $@"
                                                 UPDATE ControlTexts
                                                 SET TranslatedText = '{dst}'
                                                 WHERE ControlName = '{controlName}' AND OriginalText = '{originalText}'
                                             ";
                         SQLiteConnections.Update(updateQuery);
                     }
                     else
                     {
                         // 如果不存在,插入新记录
                         string insertQuery = $@"
                                                 INSERT INTO ControlTexts (ControlName, OriginalText, TranslatedText)
                                                 VALUES ('{controlName}', '{originalText}', '{dst}')
                                             ";
                         SQLiteConnections.Update(insertQuery);
                     }

                     // 递归处理子控件
                     if (control.HasChildren)
                     {
                         InsertControlTexts(control);
                     }
                 }
                 else
                 {
                     AddLog.Info("Unexpected JSON structure.");
                 }

             }
             catch (Exception ex)
             {

                 AddLog.Error($"Exception occurred: {ex.Message}");
             }
         }
         else
         {
             // 查询是否存在记录
             string selectQuery = $@"
                                             SELECT COUNT(*) 
                                             FROM ControlTexts 
                                             WHERE ControlName = '{controlName}' AND OriginalText = '{originalText}'
                                         ";

             // 执行查询
             var recordCount = SQLiteConnections.GetSingleResult(selectQuery);

             if (recordCount is long count1 && count1 > 0)
             {
                 break;
             }
             else
             {
                 // 如果不存在,插入新记录
                 string insertQuery = $@"
                                                 INSERT INTO ControlTexts (ControlName, OriginalText)
                                                 VALUES ('{controlName}', '{originalText}')
                                             ";
                 SQLiteConnections.Update(insertQuery);
             }

             // 递归处理子控件
             if (control.HasChildren)
             {
                 InsertControlTexts(control);
             }
         }

     }
 }
 /// <summary>
 /// 替换当前窗体控件的 Text 属性为数据库中的 TranslatedText
 /// </summary>
 /// <param name="form">需要替换文本的窗体</param>
 public void ReplaceControlTextsFromDatabase(Form form)
 {
     if (form == null)
     {
         return; // 防止空引用
     }
     // 遍历窗体内所有控件
     foreach (Control control in form!.Controls)
     {
         string controlName = control.Name;
         string query = $@"
     SELECT TranslatedText 
     FROM ControlTexts 
     WHERE ControlName = '{controlName}'
 ";

         // 查询数据库获取翻译后的文本
         var result = SQLiteConnections.GetSingleResult(query);

         if (result != null && result is string translatedText && !string.IsNullOrEmpty(translatedText))
         {
             // 替换控件文本
             control.Text = translatedText;
         }

         // 如果控件包含子控件,递归处理
         if (control.HasChildren)
         {
             ReplaceControlTextsFromDatabase(control as Form);
         }
     }
 }
 /// <summary>
 /// 替换当前窗体控件的 Text 属性为数据库中的 TranslatedText
 /// </summary>
 /// <param name="form">需要替换文本的窗体</param>
 public void ReplaceControlTextsFromChinese(Form form)
 {
     if (form == null)
     {
         return; // 防止空引用
     }
     // 遍历窗体内所有控件
     foreach (Control control in form!.Controls)
     {
         string controlName = control.Name;
         string query = $@"
     SELECT OriginalText 
     FROM ControlTexts 
     WHERE ControlName = '{controlName}'
 ";

         // 查询数据库获取翻译后的文本
         var result = SQLiteConnections.GetSingleResult(query);

         if (result != null && result is string translatedText && !string.IsNullOrEmpty(translatedText))
         {
             // 替换控件文本
             control.Text = translatedText;
         }

         // 如果控件包含子控件,递归处理
         if (control.HasChildren)
         {
             ReplaceControlTextsFromDatabase(control as Form);
         }
     }
 }

接口实现

cs 复制代码
/// <summary>
/// 翻译过程
/// </summary>
public class TranslateUtil
{
    private static readonly HttpClient _httpClient = new HttpClient();
    /// <summary>
    /// 使用Get的方式调用百度API进行翻译
    /// </summary>
    /// <param name="content">要转化的文本</param>
    /// <param name="languageFrom">要转化的语言</param>
    /// <param name="languageTo">目标语言</param>
    /// <returns></returns>
    public static async Task<FeedbackResult> TranslateGet(string content, string languageFrom, string languageTo)
    {
        string appId = "你的账户ID";
        string passWord = "你的账号密码";
        string randomNum = new Random().Next().ToString();
        string md5Sign = GenerateMD5Hash(appId + content + randomNum + passWord).ToLower();
        //q:请求翻译query
        //form:翻译源语言
        //to:翻译目标语言
        //appid是appid登陆账号或者用户名
        //salt:随机数
        //sign:签名
        string FullRequest = "http://api.fanyi.baidu.com/api/trans/vip/translate?q=" + content + "&from=" + languageFrom + "&to=" + languageTo + "&appid=" + appId + "&salt=" + randomNum + "&sign=" + md5Sign;
        try
        {
            string resultContent = await _httpClient.GetStringAsync(FullRequest);
            FeedbackResult feedbackResult = JsonSerializer.Deserialize<FeedbackResult>(resultContent)!;
            feedbackResult!.ResponseJson = resultContent;
            return feedbackResult;
        }
        catch (Exception ex)
        {
            System.Windows.Forms.MessageBox.Show(ex.Message);
            // 返回错误信息
            return new FeedbackResult()
            {
                Error_code = "-1",
                Error_msg = ex.Message
            };
        }
    }

    /// <summary>
    /// 使用Post的方式调用百度API进行翻译
    /// </summary>
    /// <param name="content">要转化的文本</param>
    /// <param name="languageFrom">要转化的语言</param>
    /// <param name="languageTo">目标语言</param>
    /// <returns></returns>
    public static async Task<FeedbackResult> TranslatePost(string content, string languageFrom, string languageTo)
    {
        string appId = "你的账户ID";
        string passWord = "你的账号密码";
        string randomNum = new Random().Next().ToString();

        #region 获取MD5加密编码后的小写格式文本
        // 计算 MD5 签名
        string md5Sign = GenerateMD5Hash(appId + content + randomNum + passWord);

        // 构建 POST 数据
        var postData = new Dictionary<string, string>
    {
        { "q", content },
        { "from", languageFrom },
        { "to", languageTo },
        { "appid", appId },
        { "salt", randomNum },
        { "sign", md5Sign }
    };
        #endregion

        try
        {
            string apiUrl = "http://api.fanyi.baidu.com/api/trans/vip/translate";
            var response = await _httpClient.PostAsync(apiUrl, new FormUrlEncodedContent(postData));
            // 确保响应成功
            response.EnsureSuccessStatusCode();
            // 解析 JSON 响应
            string resultContent = await response.Content.ReadAsStringAsync();
            // 解析 JSON 响应
            FeedbackResult feedbackResult = JsonSerializer.Deserialize<FeedbackResult>(resultContent)!;
            feedbackResult.ResponseJson = resultContent;

            return feedbackResult;
        }
        catch (Exception ex)
        {
            System.Windows.Forms.MessageBox.Show(ex.Message);
            return new FeedbackResult()
            {
                Error_code = "-1",
                Error_msg = ex.Message
            };
        }
    }
    public static string GenerateMD5Hash(string input)
    {
        using (var md5 = MD5.Create())
        {
            byte[] inputBytes = Encoding.UTF8.GetBytes(input);
            byte[] hashBytes = md5.ComputeHash(inputBytes);

            // 将字节数组转换为十六进制字符串
            StringBuilder sb = new StringBuilder();
            foreach (byte b in hashBytes)
            {
                sb.Append(b.ToString("x2")); // 小写的十六进制
            }

            return sb.ToString();
        }
    }

}

/// <summary>
/// 反馈结果类
/// </summary>
public class FeedbackResult
{
    /// <summary>
    /// 错误号,翻译出错时有此项,翻译成功时该项为null
    /// </summary>
    public string? Error_code { set; get; }
    /// <summary>
    /// 错误消息,翻译出错时代表出错信息,翻译成功时该项为null
    /// </summary>
    public string? Error_msg { set; get; }
    /// <summary>
    /// 起始语言
    /// </summary>
    public string? From { set; get; }
    /// <summary>
    /// 目标语言
    /// </summary>
    public string? To { set; get; }
    /// <summary>
    /// 响应的源Json字符串,自定义项
    /// </summary>
    public string? ResponseJson { set; get; }
    /// <summary>
    /// 翻译结果,翻译失败时该项为null,翻译成功时按照换行符"\n"来分割的数组,元组数据
    /// </summary>
    public TranslateResult[]? Trans_result { set; get; }
}

/// <summary>
/// 翻译结果类
/// </summary>
public class TranslateResult
{
    /// <summary>
    /// 源文本 Source
    /// </summary>
    public string? Src { set; get; }
    /// <summary>
    /// 翻译后的文本 Destination
    /// </summary>
    public string? Dst { set; get; }
}

/// <summary>
/// 语言枚举常数
/// </summary>
public class Language
{
    public const string 自动检测 = "auto";
    public const string 中文 = "zh";
    public const string 英语 = "en";
    public const string 粤语 = "yue";
    public const string 文言文 = "wyw";
    public const string 日语 = "jp";
    public const string 韩语 = "kor";
    public const string 法语 = "fra";
    public const string 西班牙语 = "spa";
    public const string 泰语 = "th";
    public const string 阿拉伯语 = "ara";
    public const string 俄语 = "ru";
    public const string 葡萄牙语 = "pt";
    public const string 德语 = "de";
    public const string 意大利语 = "it";
    public const string 希腊语 = "el";
    public const string 荷兰语 = "nl";
    public const string 波兰语 = "pl";
    public const string 保加利亚语 = "bul";
    public const string 爱沙尼亚语 = "est";
    public const string 丹麦语 = "dan";
    public const string 芬兰语 = "fin";
    public const string 捷克语 = "cs";
    public const string 罗马尼亚语 = "rom";
    public const string 斯洛文尼亚语 = "slo";
    public const string 瑞典语 = "swe";
    public const string 匈牙利语 = "hu";
    public const string 繁体中文 = "cht";
    public const string 越南语 = "vie";
}

这里是替换语言的部分,被注释掉的部分是因为我已经执行过把数据翻译保存到数据库中的就不再继续执行

没有账号的**【需要到百度上申请开发者账号appId和密码password】**

https://api.fanyi.baidu.com/

注册完毕后需要选择通用文本翻译

点击立即使用去注册,注册完成后就可以根据接入文档去操作了

下面是实现完毕的效果图

博客参考:C#调用百度翻译API自动将中文转化为英文,按行转换_c# 翻译-CSDN博客

相关推荐
热爱编程的小曾8 分钟前
sqli-labs靶场 less 8
前端·数据库·less
gongzemin20 分钟前
React 和 Vue3 在事件传递的区别
前端·vue.js·react.js
Apifox33 分钟前
如何在 Apifox 中通过 Runner 运行包含云端数据库连接配置的测试场景
前端·后端·ci/cd
树上有只程序猿1 小时前
后端思维之高并发处理方案
前端
AI.NET 极客圈1 小时前
AI与.NET技术实操系列(四):使用 Semantic Kernel 和 DeepSeek 构建AI应用
人工智能·.net
庸俗今天不摸鱼2 小时前
【万字总结】前端全方位性能优化指南(十)——自适应优化系统、遗传算法调参、Service Worker智能降级方案
前端·性能优化·webassembly
黄毛火烧雪下2 小时前
React Context API 用于在组件树中共享全局状态
前端·javascript·react.js
Apifox2 小时前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员
一张假钞2 小时前
Firefox默认在新标签页打开收藏栏链接
前端·firefox
高达可以过山车不行2 小时前
Firefox账号同步书签不一致(火狐浏览器书签同步不一致)
前端·firefox