国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【Unity編輯器擴(kuò)展】語言國際化工具,生成多語言Excel自動翻譯并導(dǎo)出多語言表

這篇具有很好參考價(jià)值的文章主要介紹了【Unity編輯器擴(kuò)展】語言國際化工具,生成多語言Excel自動翻譯并導(dǎo)出多語言表。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

工具效果如圖:

unity 多語言插件,Unity,Unity游戲框架,unity,游戲引擎,百度翻譯,接入百度翻譯

?多語言是個(gè)非常簡單且常用的功能。但是重復(fù)工作量大,程序手動把多語言Key配置到多語言表經(jīng)常會出現(xiàn)錯(cuò)漏,或者幾經(jīng)改版,有些Key已經(jīng)不用卻沒有剔除,久而久之造成冗余。這中簡單且重復(fù)的工作必須讓工具來完成。

功能設(shè)計(jì):

多語言通過Key,Value的形式保存,通過多語言API GF.Localization.GetText(Key)獲取當(dāng)前語言對應(yīng)的Value值。

1. 一鍵掃描多語言文本。掃描prefab資源、excel數(shù)據(jù)表以及代碼里的多語言文本,這里掃描的就是多語言的Key。

2. 多語言列表(添加到此列表即為支持該語言)。點(diǎn)擊"+"號彈出未添加的語言列表,點(diǎn)擊對應(yīng)語言添加到語言列表。多語言列表的第一項(xiàng)記為“母語”,其它語言以“母語”為基準(zhǔn)翻譯為對應(yīng)語言。

3. 一鍵翻譯。由于ChatGPT請求次數(shù)有限制,Google翻譯需要魔法上網(wǎng)。最終為了體驗(yàn)選擇了接入百度翻譯。我們只需要把“母語”的Value填寫好,其它語言直接通過百度翻譯生成Value。

4. 由于機(jī)器翻譯結(jié)果還需要人工審核修正。為了方便,工具先生成多語言Excel文件,方便交給其它部門翻譯。項(xiàng)目真正使用的多語言文件是工具將多語言Excel導(dǎo)出的json文件。

5. 多語言工具以列表的形式顯示“母語”,可以手動修改Key,Value值。

6. 細(xì)節(jié)體驗(yàn)優(yōu)化。由于每次掃描結(jié)果會覆蓋原多語言文件,可以通過勾選【鎖定】強(qiáng)制保留該行。同時(shí)也在Excel的第一列生成了【鎖定】勾選框方便策劃操作。

unity 多語言插件,Unity,Unity游戲框架,unity,游戲引擎,百度翻譯,接入百度翻譯
多語言”母語“
unity 多語言插件,Unity,Unity游戲框架,unity,游戲引擎,百度翻譯,接入百度翻譯
基于”母語“自動生成/翻譯的其它語言

?7. 由于百度翻譯免費(fèi)翻譯字節(jié)數(shù)有上限,為了節(jié)省翻譯字節(jié)。一鍵翻譯默認(rèn)只翻譯Value值為空白的行,如果想強(qiáng)制翻譯所有行可以通過一鍵翻譯的下拉按鈕強(qiáng)制翻譯全部行。

unity 多語言插件,Unity,Unity游戲框架,unity,游戲引擎,百度翻譯,接入百度翻譯

unity 多語言插件,Unity,Unity游戲框架,unity,游戲引擎,百度翻譯,接入百度翻譯
一鍵生成的多語言Excel
unity 多語言插件,Unity,Unity游戲框架,unity,游戲引擎,百度翻譯,接入百度翻譯
自動導(dǎo)出多語言Excel為json文件

功能實(shí)現(xiàn):

1. 一鍵掃描多語言文本:

①掃描Prefab資源上的多語言文本:

GameFramework框架提供了UIStringKey專門用來填寫多語言文本Key, 所以只需要從所有Prefab上獲取UIStringKey腳本上填寫的Key即可。

unity 多語言插件,Unity,Unity游戲框架,unity,游戲引擎,百度翻譯,接入百度翻譯

?掃描prefab上的多語言Key:

/// <summary>
        /// 掃描Prefab中的國際化語言
        /// </summary>
        public static List<string> ScanLocalizationTextFromPrefab(Action<string, int, int> onProgressUpdate = null)
        {
            var assetGUIDs = AssetDatabase.FindAssets("t:Prefab", ConstEditor.PrefabsPath);
            List<string> keyList = new List<string>();
            int totalCount = assetGUIDs.Length;
            for (int i = 0; i < totalCount; i++)
            {
                string path = AssetDatabase.GUIDToAssetPath(assetGUIDs[i]);
                var pfb = AssetDatabase.LoadAssetAtPath<GameObject>(path);
                onProgressUpdate?.Invoke(path, totalCount, i);
                var keyArr = pfb.GetComponentsInChildren<UnityGameFramework.Runtime.UIStringKey>(true);
                foreach (var newKey in keyArr)
                {
                    if (string.IsNullOrWhiteSpace(newKey.Key) || keyList.Contains(newKey.Key)) continue;
                    keyList.Add(newKey.Key);
                }
            }
            return keyList;
        }

② 掃描數(shù)據(jù)表Excel中的多語言文本:

首先需要標(biāo)記數(shù)據(jù)表多語言列,在數(shù)據(jù)表備注行用”i18n“標(biāo)識,程序就自動掃描添加標(biāo)識的列:

unity 多語言插件,Unity,Unity游戲框架,unity,游戲引擎,百度翻譯,接入百度翻譯

?掃描excel中的多語言文本:

/// <summary>
        /// 從DataTable Excel文件掃描本地化文本
        /// </summary>
        /// <param name="onProgressUpdate"></param>
        /// <returns></returns>
        public static List<string> ScanLocalizationTextFromDataTables(Action<string, int, int> onProgressUpdate = null)
        {
            List<string> keyList = new List<string>();
            var appConfig = AppConfigs.GetInstanceEditor();
            var mainTbFullFiles = GameDataGenerator.GameDataExcelRelative2FullPath(GameDataType.DataTable, appConfig.DataTables);
            var tbFullFiles = GameDataGenerator.GetGameDataExcelWithABFiles(GameDataType.DataTable, mainTbFullFiles);//同時(shí)掃描AB測試表
            for (int i = 0; i < tbFullFiles.Length; i++)
            {
                var excelFile = tbFullFiles[i];
                var fileInfo = new FileInfo(excelFile);
                if (!fileInfo.Exists) continue;

                onProgressUpdate?.Invoke(excelFile, tbFullFiles.Length, i);
                string tmpExcelFile = UtilityBuiltin.ResPath.GetCombinePath(fileInfo.Directory.FullName, GameFramework.Utility.Text.Format("{0}.temp", fileInfo.Name));
                try
                {
                    File.Copy(excelFile, tmpExcelFile, true);
                    using (var excelPackage = new ExcelPackage(tmpExcelFile))
                    {
                        var excelSheet = excelPackage.Workbook.Worksheets.FirstOrDefault();
                        if (excelSheet.Dimension.End.Row >= 4)
                        {
                            for (int colIndex = excelSheet.Dimension.Start.Column; colIndex <= excelSheet.Dimension.End.Column; colIndex++)
                            {
                                if (excelSheet.GetValue<string>(4, colIndex)?.ToLower() != EXCEL_I18N_TAG)
                                {
                                    continue;
                                }
                                for (int rowIndex = 5; rowIndex <= excelSheet.Dimension.End.Row; rowIndex++)
                                {
                                    string langKey = excelSheet.GetValue<string>(rowIndex, colIndex);
                                    if (string.IsNullOrWhiteSpace(langKey) || keyList.Contains(langKey)) continue;
                                    keyList.Add(langKey);
                                }
                            }

                        }
                    }
                }
                catch (Exception e)
                {
                    Debug.LogError($"掃描數(shù)據(jù)表本地化文本失敗!文件:{excelFile}, Error:{e.Message}");
                }

                if (File.Exists(tmpExcelFile))
                {
                    File.Delete(tmpExcelFile);
                }
            }
            return keyList;
        }

③ 掃描代碼中的多語言文本:

原理:搜索代碼中所有調(diào)用國際化函數(shù)GF.Localization.GetText(string key)的地方,然后把調(diào)用時(shí)傳入?yún)?shù)key的字符串值掃描出來。

首先只能通過靜態(tài)解析cs代碼,獲取函數(shù)調(diào)用時(shí)傳入?yún)?shù)的值。這比想象中復(fù)雜得多,比如:

1. 如果傳入的是字符串常量很容易獲取,但如果傳入的是變量,就需要找到該變量的初始值賦值,變量又涉及到局部變量和全局變量。

2. 如果key中包含特殊字符會影響正則表達(dá)式的匹配,所以不能使用正則表達(dá)式。

3. 注釋的代碼不應(yīng)該掃描。

為了工具安全完善,最終選擇了用"高射炮打蚊子", 使用微軟Roslyn作為CSharp靜態(tài)解析庫。但是這個(gè)解析庫依賴dll太多直接導(dǎo)入U(xiǎn)nity會有各種沖突,為了Unity工程的兼容性索性寫個(gè)C#命令行程序,由Unity代碼調(diào)用命令行程序掃描代碼,把掃描結(jié)果存入緩存文件供Unity讀取使用。而且命令行程序可以發(fā)布跨平臺包,不用擔(dān)心跨平臺問題。

用Visual Studio新建C#命令行程序,為工程添加CodeAnalysis.CSharp庫:

unity 多語言插件,Unity,Unity游戲框架,unity,游戲引擎,百度翻譯,接入百度翻譯

?命令行程序代碼:

其中命令行args, 第一參數(shù)是cs代碼文件名(完整路徑),第二個(gè)參數(shù)是掃描結(jié)果輸出到的文件(通過文本追加的方式把掃描結(jié)果列表追加到文本文件),剩余參數(shù)是目標(biāo)函數(shù)名,因?yàn)楂@取國際化文本的函數(shù)可能有多個(gè)。

internal class Program
    {
        static int Main(string[] args)
        {
            try
            {
                string csFile = args[0];
                string outputFile = args[1];
                List<string> funcNames = new List<string>();
                for (int i = 2; i < args.Length; i++)
                {
                    funcNames.Add(args[i]);
                }
                List<string> resultList = new List<string>();
                if ((File.GetAttributes(csFile) & FileAttributes.Directory) == FileAttributes.Directory)
                {
                    //如果傳的是文件夾,掃描該文件夾下的所有cs文件
                    var csFiles = Directory.GetFiles(csFile, "*.cs", SearchOption.AllDirectories);
                    foreach (var item in csFiles)
                    {
                        var codeText = File.ReadAllText(item);
                        var strList = GetTextArgumentValues(codeText, funcNames);
                        if (strList.Count > 0)
                        {
                            resultList.AddRange(strList);
                        }
                    }

                }
                else
                {
                    if (File.Exists(csFile))
                    {
                        var codeText = File.ReadAllText(csFile);
                        var strList = GetTextArgumentValues(codeText, funcNames);
                        if (strList.Count > 0)
                        {
                            resultList.AddRange(strList);
                        }
                    }
                }

                resultList.Distinct();//去重
                resultList.RemoveAll(x => string.IsNullOrWhiteSpace(x));
                Console.WriteLine($"\n\n--------------Result List Count:{resultList.Count}--------------");
                for (int i = 0; i < resultList.Count; i++)
                {
                    var str = resultList[i];
                    Console.WriteLine($"{i + 1}.\t[{str}]");
                }
                Console.WriteLine("--------------Result List End--------------");
                if (resultList.Count > 0)
                {
                    File.AppendAllLines(outputFile, resultList);
                }
                return 0;
            }
            catch (Exception err)
            {
                Console.WriteLine($"Error:{err}");
            }
            return 1;
        }
        public static List<string> GetTextArgumentValues(string codeText, List<string> funcNames)
        {
            List<string> argumentValues = new List<string>();

            SyntaxTree tree = CSharpSyntaxTree.ParseText(codeText);

            var root = (CompilationUnitSyntax)tree.GetRoot();

            var methodCalls = root.DescendantNodes().OfType<InvocationExpressionSyntax>().Where(i =>
            {
                return funcNames.Contains(i.Expression.ToString());
            });
            var compilation = CSharpCompilation.Create(typeof(object).Assembly.FullName, new SyntaxTree[] { tree })
            .WithOptions(new CSharpCompilationOptions(OutputKind.ConsoleApplication))
            .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location));
            var semanticModel = compilation.GetSemanticModel(tree);


            var methodCallsArr = methodCalls.ToArray();
            for (int i = 0; i < methodCallsArr.Length; i++)
            {
                var call = methodCallsArr[i];
                var argumentList = call.ArgumentList;
                if (argumentList.Arguments.Count >= 1)
                {
                    var argExp = argumentList.Arguments[0].Expression;
                    if (argExp is LiteralExpressionSyntax literal)
                    {
                        Console.WriteLine($"{call} ------> {literal.Token.ValueText}");
                        argumentValues.Add(literal.Token.ValueText);
                    }
                    else if (argExp is IdentifierNameSyntax variable)
                    {
                        SymbolInfo symbolInfo = semanticModel.GetSymbolInfo(variable);
                        if (symbolInfo.Symbol is IFieldSymbol fieldSymbol)
                        {
                            if (fieldSymbol.HasConstantValue)
                            {
                                argumentValues.Add((string)fieldSymbol.ConstantValue);
                                Console.WriteLine($"{call} ------> {fieldSymbol.ConstantValue}");
                            }
                        }
                        else if (symbolInfo.Symbol is ILocalSymbol localSymbol)
                        {
                            var localVar = localSymbol.DeclaringSyntaxReferences.Last()?.GetSyntax() as VariableDeclaratorSyntax;
                            if (localVar != null && localVar.Initializer != null)
                            {
                                var localVarValue = semanticModel.GetConstantValue(localVar.Initializer.Value);
                                if (localVarValue.Value != null)
                                {
                                    argumentValues.Add((string)localVarValue.Value);
                                    Console.WriteLine($"{call} ------> {localVarValue.Value}");
                                }
                            }
                        }
                    }
                }
            }

            return argumentValues;
        }
    }

2.??接入百度翻譯開放API,實(shí)現(xiàn)一鍵翻譯多語言

百度翻譯官方接入文檔:百度翻譯開放平臺

?注冊后在開發(fā)者后臺可以看到App id和密鑰,用于發(fā)送翻譯WebRequest請求參數(shù)。

開發(fā)者實(shí)名認(rèn)證后可以變更為高級版,高級版每月可享受免費(fèi)翻譯100萬個(gè)字符,相當(dāng)于50萬個(gè)漢字。一次請求能翻譯6000個(gè)字符(3000漢字),每秒請求上限10次。

unity 多語言插件,Unity,Unity游戲框架,unity,游戲引擎,百度翻譯,接入百度翻譯

?以上限制就需要翻譯時(shí)需要一次性塞入多條待翻譯句子并且不能超過每次請求的上限字節(jié)。

比較坑的是百度翻譯以換行符拆分句子,如果國際化文本中包含換行符翻譯結(jié)果就不是我們想要的:

unity 多語言插件,Unity,Unity游戲框架,unity,游戲引擎,百度翻譯,接入百度翻譯

?所以我使用一個(gè)特殊字符"?"做為自己的多條句子之間的分割符,拿到翻譯結(jié)果再用"?"分割字符串得到句子數(shù)組。

百度翻譯上行字段:

var randomCode = System.DateTime.Now.Ticks.ToString();
var strBuilder = new StringBuilder();
            strBuilder.Append(BAIDU_TRANS_URL);
            strBuilder.AppendFormat("q={0}", UnityWebRequest.EscapeURL(srcText));
            strBuilder.AppendFormat("&from={0}", GetBaiduLanguage(srcLang) ?? "auto"); //自動識別源文字語言
            strBuilder.AppendFormat("&to={0}", GetBaiduLanguage(targetLang));//翻譯到目標(biāo)語言
            strBuilder.AppendFormat("&appid={0}", EditorToolSettings.Instance.BaiduTransAppId);
            strBuilder.AppendFormat("&salt={0}", randomCode);
            strBuilder.AppendFormat("&sign={0}", GenerateBaiduSign(srcText, randomCode));

生成簽名:

/// <summary>
        /// 生成百度翻譯請求簽名
        /// </summary>
        /// <param name="srcText"></param>
        /// <returns></returns>
        private static string GenerateBaiduSign(string srcText, string randomCode)
        {
            MD5 md5 = MD5.Create();
            var fullStr = GameFramework.Utility.Text.Format("{0}{1}{2}{3}", EditorToolSettings.Instance.BaiduTransAppId, srcText, randomCode, EditorToolSettings.Instance.BaiduTransSecretKey);
            byte[] byteOld = Encoding.UTF8.GetBytes(fullStr);
            byte[] byteNew = md5.ComputeHash(byteOld);
            StringBuilder sb = new StringBuilder();
            foreach (byte b in byteNew)
            {
                sb.Append(b.ToString("x2"));
            }
            return sb.ToString();
        }

百度翻譯語言代號獲取,用ChatGPT幫我生成函數(shù),結(jié)果只有幾種是對的,無奈只能人工找對照表修改代號:

中文首字母 名稱 代碼 語種檢測 名稱 代碼 語種檢測 名稱 代碼 語種檢測
A 阿拉伯語 ara 愛爾蘭語 gle 奧克語 oci
阿爾巴尼亞語 alb 阿爾及利亞阿拉伯語 arq 阿肯語 aka
阿拉貢語 arg 阿姆哈拉語 amh 阿薩姆語 asm
艾馬拉語 aym 阿塞拜疆語 aze 阿斯圖里亞斯語 ast
奧塞梯語 oss 愛沙尼亞語 est 奧杰布瓦語 oji
奧里亞語 ori 奧羅莫語 orm
B 波蘭語 pl 波斯語 per 布列塔尼語 bre
巴什基爾語 bak 巴斯克語 baq 巴西葡萄牙語 pot
白俄羅斯語 bel 柏柏爾語 ber 邦板牙語 pam
保加利亞語 bul 北方薩米語 sme 北索托語 ped
本巴語 bem 比林語 bli 比斯拉馬語 bis
俾路支語 bal 冰島語 ice 波斯尼亞語 bos
博杰普爾語 bho
C 楚瓦什語 chv 聰加語 tso
D 丹麥語 dan 德語 de 韃靼語 tat
撣語 sha 德頓語 tet 迪維希語 div
低地德語 log
E 俄語 ru
F 法語 fra 菲律賓語 fil 芬蘭語 fin
梵語 san 弗留利語 fri 富拉尼語 ful
法羅語 fao
G 蓋爾語 gla 剛果語 kon 高地索布語 ups
高棉語 hkm 格陵蘭語 kal 格魯吉亞語 geo
古吉拉特語 guj 古希臘語 gra 古英語 eno
瓜拉尼語 grn
H 韓語 kor 荷蘭語 nl 胡帕語 hup
哈卡欽語 hak 海地語 ht 黑山語 mot
豪薩語 hau
J 吉爾吉斯語 kir 加利西亞語 glg 加拿大法語 frn
加泰羅尼亞語 cat 捷克語 cs
K 卡拜爾語 kab 卡納達(dá)語 kan 卡努里語 kau
卡舒比語 kah 康瓦爾語 cor 科薩語 xho
科西嘉語 cos 克里克語 cre 克里米亞韃靼語 cri
克林貢語 kli 克羅地亞語 hrv 克丘亞語 que
克什米爾語 kas 孔卡尼語 kok 庫爾德語 kur
L 拉丁語 lat 老撾語 lao 羅馬尼亞語 rom
拉特加萊語 lag 拉脫維亞語 lav 林堡語 lim
林加拉語 lin 盧干達(dá)語 lug 盧森堡語 ltz
盧森尼亞語 ruy 盧旺達(dá)語 kin 立陶宛語 lit
羅曼什語 roh 羅姆語 ro 邏輯語 loj
M 馬來語 may 緬甸語 bur 馬拉地語 mar
馬拉加斯語 mg 馬拉雅拉姆語 mal 馬其頓語 mac
馬紹爾語 mah 邁蒂利語 mai 曼克斯語 glv
毛里求斯克里奧爾語 mau 毛利語 mao 孟加拉語 ben
馬耳他語 mlt 苗語 hmn
N 挪威語 nor 那不勒斯語 nea 南恩德貝萊語 nbl
南非荷蘭語 afr 南索托語 sot 尼泊爾語 nep
P 葡萄牙語 pt 旁遮普語 pan 帕皮阿門托語 pap
普什圖語 pus
Q 齊切瓦語 nya 契維語 twi 切羅基語 chr
R 日語 jp 瑞典語 swe
S 薩丁尼亞語 srd 薩摩亞語 sm 塞爾維亞-克羅地亞語 sec
塞爾維亞語 srp 桑海語 sol 僧伽羅語 sin
世界語 epo 書面挪威語 nob 斯洛伐克語 sk
斯洛文尼亞語 slo 斯瓦希里語 swa 塞爾維亞語(西里爾) src
索馬里語 som
T 泰語 th 土耳其語 tr 塔吉克語 tgk
泰米爾語 tam 他加祿語 tgl 提格利尼亞語 tir
泰盧固語 tel 突尼斯阿拉伯語 tua 土庫曼語 tuk
W 烏克蘭語 ukr 瓦隆語 wln 威爾士語 wel
文達(dá)語 ven 沃洛夫語 wol 烏爾都語 urd
X 西班牙語 spa 希伯來語 heb 希臘語 el
匈牙利語 hu 西弗里斯語 fry 西里西亞語 sil
希利蓋農(nóng)語 hil 下索布語 los 夏威夷語 haw
新挪威語 nno 西非書面語 nqo 信德語 snd
修納語 sna 宿務(wù)語 ceb 敘利亞語 syr
巽他語 sun
Y 英語 en 印地語 hi 印尼語 id
意大利語 it 越南語 vie 意第緒語 yid
因特語 ina 亞齊語 ach 印古什語 ing
伊博語 ibo 伊多語 ido 約魯巴語 yor
亞美尼亞語 arm 伊努克提圖特語 iku 伊朗語 ir
Z 中文(簡體) zh 中文(繁體) cht 中文(文言文) wyw
中文(粵語) yue 扎扎其語 zaz 中古法語 frm
祖魯語 zul 爪哇語 jav

無私獻(xiàn)上獲取百度翻譯語言代碼:

/// <summary>
        /// 根據(jù)語言類型返回對應(yīng)的百度語言縮寫
        /// </summary>
        /// <param name="lang"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public static string GetBaiduLanguage(Language lang)
        {
            switch (lang)
            {
                case Language.Afrikaans:
                    return "afr";
                case Language.Albanian:
                    return "alb";
                case Language.Arabic:
                    return "ara";
                case Language.Basque:
                    return "baq";
                case Language.Belarusian:
                    return "bel";
                case Language.Bulgarian:
                    return "bul";
                case Language.Catalan:
                    return "cat";
                case Language.ChineseSimplified:
                    return "zh";
                case Language.ChineseTraditional:
                    return "cht";
                case Language.Croatian:
                    return "hrv";
                case Language.Czech:
                    return "cs";
                case Language.Danish:
                    return "dan";
                case Language.Dutch:
                    return "nl";
                case Language.English:
                    return "en";
                case Language.Estonian:
                    return "est";
                case Language.Faroese:
                    return "fao";
                case Language.Finnish:
                    return "fin";
                case Language.French:
                    return "fra";
                case Language.Georgian:
                    return "geo";
                case Language.German:
                    return "de";
                case Language.Greek:
                    return "el";
                case Language.Hebrew:
                    return "heb";
                case Language.Hungarian:
                    return "hu";
                case Language.Icelandic:
                    return "ice";
                case Language.Indonesian:
                    return "id";
                case Language.Italian:
                    return "it";
                case Language.Japanese:
                    return "jp";
                case Language.Korean:
                    return "kor";
                case Language.Latvian:
                    return "lav";
                case Language.Lithuanian:
                    return "lit";
                case Language.Macedonian:
                    return "mac";
                case Language.Malayalam:
                    return "may";
                case Language.Norwegian:
                    return "nor";
                case Language.Persian:
                    return "per";
                case Language.Polish:
                    return "pl";
                case Language.PortugueseBrazil:
                    return "pt";
                case Language.PortuguesePortugal:
                    return "pt";
                case Language.Romanian:
                    return "rom";
                case Language.Russian:
                    return "ru";
                case Language.SerboCroatian:
                    return "sec";
                case Language.SerbianCyrillic:
                    return "src";
                case Language.SerbianLatin:
                    return "srp";
                case Language.Slovak:
                    return "sk";
                case Language.Slovenian:
                    return "slo";
                case Language.Spanish:
                    return "spa";
                case Language.Swedish:
                    return "swe";
                case Language.Thai:
                    return "th";
                case Language.Turkish:
                    return "tr";
                case Language.Ukrainian:
                    return "ukr";
                case Language.Vietnamese:
                    return "vie";
                default:
                    throw new NotSupportedException($"暫不支持該語言:{lang}");
            }
        }

接入百度翻譯示例代碼:文章來源地址http://www.zghlxwxcb.cn/news/detail-675811.html

private static void TranslateAndSave(List<LocalizationText> mainLangTexts, Language srcLang, List<LocalizationText> langTexts, Language targetLang, bool forceAll)
        {
            int curTransIdx = 0;
            while (curTransIdx < langTexts.Count)
            {
                string totalText = "";
                List<int> totalTextIdx = new List<int>();
                for (; curTransIdx < langTexts.Count; curTransIdx++)
                {
                    var text = langTexts[curTransIdx];
                    string srcText = "";
                    if (forceAll)
                    {
                        var mainText = mainLangTexts.FirstOrDefault(tmpItm => tmpItm.Key.CompareTo(text.Key) == 0);
                        if (mainText != null && !string.IsNullOrWhiteSpace(mainText.Value))
                        {
                            srcText = mainText.Value;
                        }
                    }
                    else
                    {
                        if (string.IsNullOrWhiteSpace(text.Value))
                        {
                            var mainText = mainLangTexts.FirstOrDefault(tmpItm => tmpItm.Key.CompareTo(text.Key) == 0);
                            if (mainText != null && !string.IsNullOrWhiteSpace(mainText.Value))
                            {
                                srcText = mainText.Value;
                            }
                        }
                    }
                    if (!string.IsNullOrWhiteSpace(srcText))
                    {
                        if ((totalText.Length + srcText.Length) > EditorToolSettings.Instance.BaiduTransMaxLength)
                        {
                            curTransIdx -= 1; //如果長度超了下個(gè)請求接著這行
                            break;
                        }
                        totalText += srcText + TRANS_SPLIT_TAG;
                        totalTextIdx.Add(curTransIdx);
                    }
                }
                if (string.IsNullOrWhiteSpace(totalText))
                {
                    curTransIdx++;//如果一行字?jǐn)?shù)就超過上限則跳過翻譯這行
                    continue;
                }
                totalText = totalText.Substring(0, totalText.Length - TRANS_SPLIT_TAG.Length);//去掉結(jié)分隔符
                TMP_EditorCoroutine.StartCoroutine(TranslateCoroutine(totalText, srcLang, targetLang, (success, trans, userDt) =>
                {
                    if (success)
                    {
                        ParseAndSaveTransResults(langTexts, targetLang, trans, userDt as int[]);
                    }
                }, totalTextIdx.ToArray()));
            }
        }
        /// <summary>
        /// 解析翻譯結(jié)果并保存到語言Excel
        /// </summary>
        /// <param name="targetTexts"></param>
        /// <param name="targetLang"></param>
        /// <param name="resultStr"></param>
        /// <param name="resultTextIdxArr"></param>
        private static void ParseAndSaveTransResults(List<LocalizationText> targetTexts, Language targetLang, TranslationResult trans, int[] resultTextIdxArr)
        {
            if (string.IsNullOrWhiteSpace(trans.dst) || resultTextIdxArr == null) return;
            var srcTexts = trans.src.Split(TRANS_SPLIT_TAG);
            var resultTexts = trans.dst.Split(TRANS_SPLIT_TAG);
            if (resultTexts.Length != resultTextIdxArr.Length || resultTexts.Length != srcTexts.Length)
            {
                Debug.LogError($"翻譯失敗, 翻譯結(jié)果數(shù)量和索引數(shù)不一致.result count:{resultTexts.Length}, but index count:{resultTextIdxArr.Length}\n 翻譯結(jié)果:{trans.dst}");
                return;
            }
            for (int i = 0; i < resultTextIdxArr.Length; i++)
            {
                var idx = resultTextIdxArr[i];
                var srcStr = srcTexts[i];
                var dstStr = resultTexts[i].Trim();
                int leadingSpaces = srcStr.Length - srcStr.TrimStart().Length;
                int trailingSpaces = srcStr.Length - srcStr.TrimEnd().Length;

                dstStr = dstStr.PadLeft(dstStr.Length + leadingSpaces);
                dstStr = dstStr.PadRight(dstStr.Length + trailingSpaces);
                targetTexts[idx].Value = dstStr;
            }

            SaveLanguage(targetLang, targetTexts);
        }
        private static IEnumerator TranslateCoroutine(string srcText, Language srcLang, Language targetLang, Action<bool, TranslationResult, object> onComplete, object userData)
        {
            var randomCode = System.DateTime.Now.Ticks.ToString();

            var strBuilder = new StringBuilder();
            strBuilder.Append(BAIDU_TRANS_URL);
            strBuilder.AppendFormat("q={0}", UnityWebRequest.EscapeURL(srcText));
            strBuilder.AppendFormat("&from={0}", GetBaiduLanguage(srcLang) ?? "auto"); //自動識別源文字語言
            strBuilder.AppendFormat("&to={0}", GetBaiduLanguage(targetLang));//翻譯到目標(biāo)語言
            strBuilder.AppendFormat("&appid={0}", EditorToolSettings.Instance.BaiduTransAppId);
            strBuilder.AppendFormat("&salt={0}", randomCode);
            strBuilder.AppendFormat("&sign={0}", GenerateBaiduSign(srcText, randomCode));

            //Debug.Log($"發(fā)送:{strBuilder}");
            // 發(fā)送請求
            using (var webRequest = UnityEngine.Networking.UnityWebRequest.Get(strBuilder.ToString()))
            {
                webRequest.SetRequestHeader("Content-Type", "text/html;charset=UTF-8");
                webRequest.certificateHandler = new WebRequestCertNoValidate();
                webRequest.SendWebRequest();
                while (!webRequest.isDone) yield return null;

                if (webRequest.result != UnityEngine.Networking.UnityWebRequest.Result.Success)
                {
                    Debug.LogError($"---------翻譯{targetLang}請求失敗:{webRequest.error}---------");
                    onComplete?.Invoke(false, null, userData);
                }
                else
                {
                    var json = webRequest.downloadHandler.text;
                    //Debug.Log($"接收:{json}");
                    try
                    {
                        var responseJson = UtilityBuiltin.Json.ToObject<JObject>(json);
                        if (responseJson.ContainsKey("trans_result"))
                        {
                            var resultArray = responseJson["trans_result"].ToObject<TranslationResult[]>();
                            if (resultArray != null && resultArray.Length > 0)
                            {
                                var resultTrans = resultArray[0];
                                onComplete?.Invoke(true, resultTrans, userData);
                            }
                            else
                            {
                                Debug.LogError($"---------翻譯{targetLang}失敗:{responseJson}---------");
                                onComplete?.Invoke(false, null, userData);
                            }
                        }
                        else
                        {
                            Debug.LogError($"---------翻譯{targetLang}失敗:{responseJson}---------");
                            onComplete?.Invoke(false, null, userData);
                        }
                    }
                    catch (System.Exception e)
                    {
                        Debug.LogError($"---------翻譯{targetLang}返回?cái)?shù)據(jù)解析失敗:{e.Message}---------");
                        onComplete?.Invoke(false, null, userData);
                    }
                }
            }

        }

internal class TranslationResult
    {
        public string src;
        public string dst;
    }

工具完整代碼參考:GitHub - sunsvip/GF_HybridCLR

到了這里,關(guān)于【Unity編輯器擴(kuò)展】語言國際化工具,生成多語言Excel自動翻譯并導(dǎo)出多語言表的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Unity編輯器擴(kuò)展之GenericMenu菜單擴(kuò)展

    Unity編輯器擴(kuò)展之GenericMenu菜單擴(kuò)展

    內(nèi)容將會持續(xù)更新,有錯(cuò)誤的地方歡迎指正,謝謝! ? Unity編輯器擴(kuò)展之GenericMenu自定義菜單 ? ? ? TechX 堅(jiān)持將創(chuàng)新的科技帶給世界! 擁有更好的學(xué)習(xí)體驗(yàn) —— 不斷努力,不斷進(jìn)步,不斷探索 TechX —— 心探索、心進(jìn)??! 助力快速掌握 GenericMenu 菜單擴(kuò)展 為初學(xué)者節(jié)省寶貴的

    2024年02月01日
    瀏覽(38)
  • 【Unity編輯器擴(kuò)展】| 頂部菜單欄擴(kuò)展 MenuItem
  • Unity 擴(kuò)展自定義編輯器窗口

    Unity 擴(kuò)展自定義編輯器窗口

    在Assets文件夾路徑下任意位置創(chuàng)建Editor文件夾,將擴(kuò)展編輯器的代碼放在Editor文件夾下 代碼中首先引用命名空間 然后將創(chuàng)建的類繼承自EditorWindow 然后通過擴(kuò)展編輯器菜單功能調(diào)用創(chuàng)建窗口的方法 要注意方法中泛型參數(shù)需要傳入的是自己代碼的類,這個(gè)功能是根據(jù)后面OnGUI方

    2024年04月27日
    瀏覽(19)
  • Unity 編輯器擴(kuò)展之 Attribute

    Unity 編輯器擴(kuò)展之 Attribute

    Unity內(nèi)置屬性[Attribute]是一種類似修飾功能的標(biāo)簽。可以對OnSceneGUI,InspectorGUI,MenuGUI,WindowGUI等實(shí)現(xiàn)各種各樣的GUI擴(kuò)展。用戶只要添加上特性標(biāo)簽,就能夠自由的使用這些擴(kuò)展功能。下面列出一些常用的標(biāo)簽: 隱藏屬性在Inspector面板上的顯示。在繼承了MonoBehaviour的類中,用

    2023年04月09日
    瀏覽(24)
  • Unity編輯擴(kuò)展:功能篇之Json數(shù)據(jù)編輯器

    Unity編輯擴(kuò)展:功能篇之Json數(shù)據(jù)編輯器

    前言 編輯器擴(kuò)展算是比較純粹的功能開發(fā),基本沒有什么理論知識,都是一些 Unity 相關(guān)接口的使用與數(shù)據(jù)類型的設(shè)計(jì)操作等。在本篇文章主要的文字描述基本都是在做代碼解釋,為了使內(nèi)容接受度更高,我會盡量描述到代碼結(jié)構(gòu)中的每個(gè)細(xì)節(jié)。如果有對此不太了解又很感興

    2024年02月06日
    瀏覽(25)
  • 【Unity編輯器擴(kuò)展】| Inspector監(jiān)視器面板擴(kuò)展

    【Unity編輯器擴(kuò)展】| Inspector監(jiān)視器面板擴(kuò)展

    前言 前面我們介紹了Unity中編輯器擴(kuò)展的一些基本概念及基礎(chǔ)知識,還有編輯器擴(kuò)展中用到的相關(guān)特性Attribute介紹。 后面就來針對Uniity編輯器擴(kuò)展中比較常用的模塊進(jìn)行學(xué)習(xí)介紹。 本文就來詳細(xì)介紹一下Unity編輯器擴(kuò)展中關(guān)于 Inspector面板 擴(kuò)展功能學(xué)習(xí)。

    2024年02月08日
    瀏覽(20)
  • 盤點(diǎn)Unity幾款編輯器擴(kuò)展工具

    盤點(diǎn)Unity幾款編輯器擴(kuò)展工具

    unity 編輯器一個(gè)不容忽視的強(qiáng)大之處就是非常易于自定義擴(kuò)展工具,來滿足各種各樣的美術(shù)、策劃及程序上的需求。今天為大家介紹Asset Store資源商店中幾款實(shí)用的編輯器擴(kuò)展工具,幫助大家直接在Unity編輯器中完成3D建模與調(diào)整工作,免去與其它軟件進(jìn)行數(shù)據(jù)轉(zhuǎn)換的過程,從

    2024年04月09日
    瀏覽(25)
  • 【Unity編輯器擴(kuò)展】| 自定義窗口和面板
  • Unity編輯器擴(kuò)展-第四集-獲取物體的方法

    Unity編輯器擴(kuò)展-第四集-獲取物體的方法

    第三集鏈接:Unity編輯器擴(kuò)展-第三集-添加按鈕到組件菜單并且重置組件_菌菌巧樂茲的博客-CSDN博客 ?一、本節(jié)目標(biāo)+效果展示 1.改選中單個(gè)物體的名字 2.改選中所有物體的名字 ?3.選中了所有的物體,但只改第一層物體的名稱 ?4.來個(gè)有用的(選中的所有物體,按順序起名)

    2024年02月14日
    瀏覽(25)
  • 【Unity UIToolkit】UIBuilder基礎(chǔ)教程-制作簡易的對話系統(tǒng)編輯器 3步教你玩轉(zhuǎn)Unity編輯器擴(kuò)展工具

    【Unity UIToolkit】UIBuilder基礎(chǔ)教程-制作簡易的對話系統(tǒng)編輯器 3步教你玩轉(zhuǎn)Unity編輯器擴(kuò)展工具

    隨著Unity開發(fā)的深入,基本的Unity編輯器界面并不能滿足大部分玩家高階開發(fā)的要求。為了提高開發(fā)的效率,有針對性的定制化擴(kuò)展編輯器界面是提高開發(fā)效率的不錯(cuò)選擇。 今天就給大家?guī)鞺nity官方提高的編輯器擴(kuò)展工具UIToolkit(集成了UIBuilder和UI Debugger等插件)的使用教程。

    2024年02月04日
    瀏覽(77)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包