Godot 学习笔记(5):国际化多语言翻译,包含常用10种语言机翻!

前言

为了面向更大的市场,国际化是肯定的。我想如果我开发游戏,至少要支持两种语言,英语和中文简体。

国际化

翻译Api选择

在这里插入图片描述
国内Api也有三种选择,百度,有道和小牛。我这里就选小牛了,比较便宜。

小牛测试

小牛翻译平台

使用PostMan测试成功
在这里插入图片描述

语言选择

在这里插入图片描述
在这里插入图片描述

首先,作为中文为母语,所以我至少支持三种语言。简中,繁中和英语。下面附上小牛的对应参数表

语言参数
简中zh
繁中cht
英语en
德语de
法语fr
西班牙语es
意大利语it
葡萄牙语pt
俄语ru
日语ja
韩语ko

吐槽一下,写了这么多,我都快认不清这个【语】字是什么意思了。

原文选择我这里选择英语作为原文,因为这样可以顺便学一下英语。

代码逻辑

这里使用了MiniExcel
在这里插入图片描述
Json化方式
在这里插入图片描述

实体对象

public class TranslateModel
{
    public TranslateModel() { }

    public TranslateModel(string scene,string key,string en) {
        Scene = scene;
        Key = key;
        EN = en;
    }
    public string Scene { get; set; }

    public string Key { get; set; }

    /// <summary>
    /// 英语
    /// </summary>
    public string EN { get; set; }

    /// <summary>
    /// 简体中文
    /// </summary>
    public string ZH { get; set; }

    


    /// <summary>
    /// 繁体中文
    /// </summary>
    public string CHT { get; set; }


    /// <summary>
    /// 德语
    /// </summary>
    public string DE { get; set; }


    /// <summary>
    /// 法语
    /// </summary>
    public string FR { get; set; }


    /// <summary>
    /// 西班牙语
    /// </summary>
    public string ES { get; set; }


    /// <summary>
    /// 意大利语
    /// </summary>
    public string IT { get; set; }

    /// <summary>
    /// 葡萄牙语
    /// </summary>
    public string PT { get; set; }

    /// <summary>
    /// 俄语
    /// </summary>
    public string RU { get; set; }


    /// <summary>
    /// 日语
    /// </summary>
    public string JA { get; set; }

    /// <summary>
    /// 韩语
    /// </summary>
    public string KO { get; set; }
}

翻译帮助类

public class TranslateHelper
{


/// <summary>
/// 存放读取的数据
/// </summary>
public IEnumerable<TranslateModel> Translates { get; private set; }

            /// <summary>
        /// 模板路径
        /// </summary>
        public readonly string TemplateUrl = "Assests/translate_template.xlsx";

        /// <summary>
        /// 读取路径
        /// </summary>
        public readonly string ReadUrl = "Assests/translate_read.xlsx";

        /// <summary>
        /// 翻译导出路径
        /// </summary>

        public readonly string WriteUrl = "Assests/translate_read.xlsx";

    public TranslateHelper()
    {

    }


}
导出模板
/// <summary>
/// 导出模板,如果文件存在则跳过
/// </summary>
public void CreateTemplate()
{
    if (!File.Exists(TemplateUrl))
    {
        var config = new OpenXmlConfiguration()
        {
            TableStyles = TableStyles.None
        };
        var saveTemplate = new List<TranslateModel>();
        saveTemplate.Add(new TranslateModel("Main", "Hello", "Hello World!"));

        MiniExcel.SaveAs(TemplateUrl, saveTemplate,configuration: config);
    }
}

在这里插入图片描述

读取文件

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

翻译

这里用一下我的封装

C# HttpClient Get Post简单封装

先来一个Hello world!翻译

在这里插入图片描述

public class TranslateHelper
{

    public enum Language { zh, cht, en, de, fr, es, it, pt, ru, ja, ko }

    /// <summary>
    /// 存放读取的数据
    /// </summary>
    public IEnumerable<TranslateModel> Translates { get; private set; }

    /// <summary>
    /// 模板路径
    /// </summary>
    public const string TemplateUrl = "Assests/translate_template.xlsx";

    /// <summary>
    /// 读取路径
    /// </summary>
    public const string ReadUrl = "Assests/translate_read.xlsx";

    /// <summary>
    /// 翻译导出路径
    /// </summary>

    public const string WriteUrl = "Assests/translate_read.xlsx";


    public const string API_KEY = "你的key";

    public const string APPID = "你的ip";

    public const string API_URL = "https://api.niutrans.com/NiuTransServer/translation";

    public TranslateHelper()
    {

    }
    /// <summary>
    /// 导出模板,如果文件存在则跳过
    /// </summary>
    public void CreateTemplate()
    {
        if (!File.Exists(TemplateUrl))
        {
            var config = new OpenXmlConfiguration()
            {
                TableStyles = TableStyles.None
            };
            var saveTemplate = new List<TranslateModel>();
            saveTemplate.Add(new TranslateModel("Main", "Hello", "Hello World!"));

            MiniExcel.SaveAs(TemplateUrl, saveTemplate, configuration: config);
        }
    }



    public void Read()
    {
        Translates = MiniExcel.Query<TranslateModel>(ReadUrl);

    }


    public async Task<string> TranslateFromEN(string en, Language language)
    {
    //这个是我自己封装的,你也可以用微软官方的原生httpclient
        var httpHelper = new MyHttpHelper(API_URL);
        var data = new
        {
            src_text = en,
            from = "en",
            to = language.ToString(),
            apikey = API_KEY,
        };
        var res = await httpHelper.JsonHttpPost<Dictionary<string,string>>("", data, null);

        var str = res["tgt_text"];
        return str;
    }


}
测试
        static void Main(string[] args)
        {
            var helper = new TranslateHelper();
            helper.CreateTemplate();
            Console.WriteLine("开始!");

            Task.Run(async () =>
            {
                var res = await helper.TranslateFromEN("Hello world!", TranslateHelper.Language.zh);
                Console.WriteLine(res);
            });

            Console.WriteLine("结束!");
            Console.ReadKey();
        }

在这里插入图片描述

多语言测试
Task.Run(async () =>
{
    var res = "";
    res = await helper.TranslateFromEN("Hello world!", TranslateHelper.Language.zh);
    Console.WriteLine(res);
    res = await helper.TranslateFromEN("Hello world!", TranslateHelper.Language.cht);
    Console.WriteLine(res);

    res = await helper.TranslateFromEN("Hello world!", TranslateHelper.Language.de);
    Console.WriteLine(res);
    res = await helper.TranslateFromEN("Hello world!", TranslateHelper.Language.fr);
    Console.WriteLine(res);
    res = await helper.TranslateFromEN("Hello world!", TranslateHelper.Language.es);
    Console.WriteLine(res);
    res = await helper.TranslateFromEN("Hello world!", TranslateHelper.Language.it);
    Console.WriteLine(res);
    res = await helper.TranslateFromEN("Hello world!", TranslateHelper.Language.pt);
    Console.WriteLine(res);
    res = await helper.TranslateFromEN("Hello world!", TranslateHelper.Language.ru);
    Console.WriteLine(res);
    res = await helper.TranslateFromEN("Hello world!", TranslateHelper.Language.ja);
    Console.WriteLine(res);
    res = await helper.TranslateFromEN("Hello world!", TranslateHelper.Language.ko);
    Console.WriteLine(res);
});

在这里插入图片描述

综合翻译
/// <summary>
/// 读取并写入机翻结果
/// </summary>
/// <returns></returns>
public async Task ReadAndWrite()
{
    if(!File.Exists(ReadUrl))
    {
        Console.WriteLine($"[{ReadUrl}]文件不存在,读取失败");
        return;
    }
    else
    {
        Translates = MiniExcel.Query<TranslateModel>(ReadUrl).ToArray();
    }

    if (File.Exists(WriteUrl))
    {
        Console.WriteLine($"[{WriteUrl}]文件已存在,跳过翻译");
        return ;

    }
    else
    {
        for(var i = 0;i< Translates.Count();i++)
        {
            Console.WriteLine($"翻译进度:[{i}/{Translates.Count()}]");

            Translates[i] = await TranslateAllFromEN(Translates[i]);
        }
        //将数据保留
        MiniExcel.SaveAs(WriteUrl, Translates);
    }
    
}

/// <summary>
/// 从EN翻译全部
/// </summary>
/// <returns></returns>
public async Task<TranslateModel> TranslateAllFromEN(TranslateModel translateModel)
{
    if (translateModel.EN != null && translateModel.EN != "")
    {
        
        var en = translateModel.EN;
        translateModel.ZH = await TranslateFromEN(en, Language.zh);
        translateModel.CHT = await TranslateFromEN(en, Language.cht);
        translateModel.DE = await TranslateFromEN(en, Language.de);
        translateModel.FR = await TranslateFromEN(en, Language.fr);
        translateModel.ES = await TranslateFromEN(en, Language.es);
        translateModel.IT = await TranslateFromEN(en, Language.it);
        translateModel.PT = await TranslateFromEN(en, Language.pt);
        translateModel.RU = await TranslateFromEN(en, Language.ru);
        translateModel.JA = await TranslateFromEN(en, Language.ja);
        translateModel.KO = await TranslateFromEN(en, Language.ko);
        Console.WriteLine(JsonConvert.SerializeObject(translateModel));
    }
    else
    {
        Console.WriteLine($"Scene[{translateModel.Scene}],Key[{translateModel.Key}]的EN为空");
    }

    return translateModel;
    
}

/// <summary>
/// EN单独翻译
/// </summary>
/// <param name="en"></param>
/// <param name="language"></param>
/// <returns></returns>
public async Task<string> TranslateFromEN(string en, Language language)
{
    //防止请求过快,小牛API并发有限制
    await Task.Delay(100);
    //Console.WriteLine(language.ToString());
    var httpHelper = new MyHttpHelper(API_URL);
    var data = new
    {
        src_text = en,
        from = "en",
        to = language.ToString(),
        apikey = API_KEY,
    };
    var res = await httpHelper.JsonHttpPost<Dictionary<string,string>>("", data, null);

    var str = res["tgt_text"];
    return str;
}
文件准备

在这里插入图片描述

在这里插入图片描述

测试代码
Task.Run(async () =>
{
    await helper.ReadAndWrite();
  
});
测试结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

完整代码

实体类

public class TranslateModel
{
    public TranslateModel() { }

    public TranslateModel(string scene,string key,string en) {
        Scene = scene;
        Key = key;
        EN = en;
    }
    public string Scene { get; set; }

    public string Key { get; set; }

    /// <summary>
    /// 英语
    /// </summary>
    public string EN { get; set; }

    /// <summary>
    /// 简体中文
    /// </summary>
    public string ZH { get; set; }

    


    /// <summary>
    /// 繁体中文
    /// </summary>
    public string CHT { get; set; }


    /// <summary>
    /// 德语
    /// </summary>
    public string DE { get; set; }


    /// <summary>
    /// 法语
    /// </summary>
    public string FR { get; set; }


    /// <summary>
    /// 西班牙语
    /// </summary>
    public string ES { get; set; }


    /// <summary>
    /// 意大利语
    /// </summary>
    public string IT { get; set; }

    /// <summary>
    /// 葡萄牙语
    /// </summary>
    public string PT { get; set; }

    /// <summary>
    /// 俄语
    /// </summary>
    public string RU { get; set; }


    /// <summary>
    /// 日语
    /// </summary>
    public string JA { get; set; }

    /// <summary>
    /// 韩语
    /// </summary>
    public string KO { get; set; }
}

翻译帮助类

public class TranslateHelper
{

    public enum Language { zh, cht, en, de, fr, es, it, pt, ru, ja, ko }

    /// <summary>
    /// 存放读取的数据
    /// </summary>
    public TranslateModel[] Translates { get; private set; }

    /// <summary>
    /// 模板路径
    /// </summary>
    public const string TemplateUrl = "Assests/translate_template.xlsx";

    /// <summary>
    /// 读取路径
    /// </summary>
    public const string ReadUrl = "Assests/translate_read.xlsx";

    /// <summary>
    /// 翻译导出路径
    /// </summary>

    public const string WriteUrl = "Assests/translate_write.xlsx";


    public const string API_KEY = "你的key";

    public const string APPID = "你的appid";

    public const string API_URL = "https://api.niutrans.com/NiuTransServer/translation";

    public TranslateHelper()
    {

    }
    /// <summary>
    /// 导出模板,如果文件存在则跳过
    /// </summary>
    public void CreateTemplate()
    {
        if (!File.Exists(TemplateUrl))
        {
            var config = new OpenXmlConfiguration()
            {
                TableStyles = TableStyles.None
            };
            var saveTemplate = new List<TranslateModel>();
            saveTemplate.Add(new TranslateModel("Main", "Hello", "Hello World!"));

            MiniExcel.SaveAs(TemplateUrl, saveTemplate, configuration: config);
        }
        else
        {
            Console.WriteLine($"[{TemplateUrl}]文件已存在,跳过创建");
        }
    }


    /// <summary>
    /// 读取并写入机翻结果
    /// </summary>
    /// <returns></returns>
    public async Task ReadAndWrite()
    {
        if(!File.Exists(ReadUrl))
        {
            Console.WriteLine($"[{ReadUrl}]文件不存在,读取失败");
            return;
        }
        else
        {
            Translates = MiniExcel.Query<TranslateModel>(ReadUrl).ToArray();
        }

        if (File.Exists(WriteUrl))
        {
            Console.WriteLine($"[{WriteUrl}]文件已存在,跳过翻译");
            return ;

        }
        else
        {
            for(var i = 0;i< Translates.Count();i++)
            {
                Console.WriteLine($"翻译进度:[{i+1}/{Translates.Count()}]");

                Translates[i] = await TranslateAllFromEN(Translates[i]);
            }
            var config = new OpenXmlConfiguration()
            {
                TableStyles = TableStyles.None
            };
            //将数据保留
            MiniExcel.SaveAs(WriteUrl, Translates,configuration:config);
        }
        
    }

    /// <summary>
    /// 从EN翻译全部
    /// </summary>
    /// <returns></returns>
    public async Task<TranslateModel> TranslateAllFromEN(TranslateModel translateModel)
    {
        if (translateModel.EN != null && translateModel.EN != "")
        {
            
            var en = translateModel.EN;
            translateModel.ZH = await TranslateFromEN(en, Language.zh);
            translateModel.CHT = await TranslateFromEN(en, Language.cht);
            translateModel.DE = await TranslateFromEN(en, Language.de);
            translateModel.FR = await TranslateFromEN(en, Language.fr);
            translateModel.ES = await TranslateFromEN(en, Language.es);
            translateModel.IT = await TranslateFromEN(en, Language.it);
            translateModel.PT = await TranslateFromEN(en, Language.pt);
            translateModel.RU = await TranslateFromEN(en, Language.ru);
            translateModel.JA = await TranslateFromEN(en, Language.ja);
            translateModel.KO = await TranslateFromEN(en, Language.ko);
            Console.WriteLine(JsonConvert.SerializeObject(translateModel));
        }
        else
        {
            Console.WriteLine($"Scene[{translateModel.Scene}],Key[{translateModel.Key}]的EN为空");
        }

        return translateModel;
        
    }

    /// <summary>
    /// EN单独翻译
    /// </summary>
    /// <param name="en"></param>
    /// <param name="language"></param>
    /// <returns></returns>
    public async Task<string> TranslateFromEN(string en, Language language)
    {
        //防止请求过快,小牛API并发有限制
        await Task.Delay(100);
        //Console.WriteLine(language.ToString());
        var httpHelper = new MyHttpHelper(API_URL);
        var data = new
        {
            src_text = en,
            from = "en",
            to = language.ToString(),
            apikey = API_KEY,
        };
        var res = await httpHelper.JsonHttpPost<Dictionary<string,string>>("", data, null);

        var str = res["tgt_text"];
        return str;
    }


}

网络帮助类

public class MyHttpHelper
{

    private string baseUrl;


    /// <summary>
    /// 基础Api
    /// </summary>
    public string BaseUrl
    {
        get
        {
            return baseUrl;
        }

        set
        {
            baseUrl = value;
            MyHttpClient = new HttpClient()
            {
                BaseAddress = new Uri(baseUrl)
            };
        }
    }


    public HttpClient MyHttpClient { get; set; }
    public MyHttpHelper()
    {

    }

    public MyHttpHelper(string baseUrl)
    {
        BaseUrl = baseUrl;
    }

    /// <summary>
    /// 序列化返回值
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="api"></param>
    /// <param name="strParams"></param>
    /// <returns></returns>
    public async Task<T> JsonHttpGet<T>(string api, Dictionary<string, string> strParams)
    {
        var res = await MyHttpGet(api, strParams);
        return await res.Content.ReadFromJsonAsync<T>();
    }


    /// <summary>
    /// 序列化返回值
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="api"></param>
    /// <param name="value"></param>
    /// <param name="strParams"></param>
    /// <returns></returns>
    public async Task<T> JsonHttpPost<T>(string api, object value, Dictionary<string, string> strParams)
    {
        var res = await MyHttpPost(api, value, strParams);
        return await res.Content.ReadFromJsonAsync<T>();
    }

    /// <summary>
    /// 序列化请求
    /// </summary>
    /// <param name="api"></param>
    /// <param name="param"></param>
    /// <returns></returns>
    public async Task<HttpResponseMessage> MyHttpGet(string api, Dictionary<string, string> param)
    {
        string paramStr = DictionaryToParams(param);
        return await MyHttpClient.GetAsync(api + paramStr);
    }

    /// <summary>
    /// 自定义的转发功能
    /// </summary>
    /// <param name="api"></param>
    /// <param name="dataname"></param>
    /// <param name="value"></param>
    /// <returns></returns>
    public Task<HttpResponseMessage> MyHttpPost(string api, object value, Dictionary<string, string> strParams)
    {
        return MyHttpClient.PostAsync(api + DictionaryToParams(strParams), new StringContent(JsonConvert.SerializeObject(value), Encoding.UTF8, "application/json"));
    }

    /// <summary>
    /// 字典转参数
    /// </summary>
    /// <param name="param"></param>
    /// <returns></returns>
    public string DictionaryToParams(Dictionary<string, string> param)
    {
        var res = "";
        if (param != null)
        {
            var list = param.ToList();
            if (list.Count != 0)
            {
                for (var i = 0; i < list.Count; i++)
                {

                    if (i != 0)
                    {
                        res += "&";
                    }
                    res += $"{list[i].Key}={list[i].Value}";
                }
                res = "?" + res;
            }

        }
        return res;
    }
}

最终效果

翻译前

在这里插入图片描述

翻译中

在这里插入图片描述

翻译后

在这里插入图片描述

总结

多语言发布,这样可以让我们的游戏在更多的国家用户使用。虽然我暂时没有这个需求,但是说不定也有别的项目需要多语言的本地化接入。

  • 26
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值