<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Cocos Creator 多語言組件實現(xiàn)

          共 13556字,需瀏覽 28分鐘

           ·

          2020-12-10 20:22

          簡介

          基于cocos creator 2.4.3 的一個手游項目模板, 提供一些自定義組件以及 Demo。

          項目地址:

          https://github.com/yanjifa/game-template

          本次著重介紹多語言組件

          Demo在線查看:

          https://yanjifa.github.io/web-desktop/

          目前的多語言組件如果想對已經(jīng)上線的項目進行多語言支持, 普遍都要對每個 Label組件都操作一遍, 掛上組件腳本, 這波操作說實話, 小項目還好, 大項目簡直讓人崩潰。

          所以之前基于 1.10.3 版本搞了一個使用上更方便的多語言實現(xiàn), 現(xiàn)在適配到 2.4.3版本, 并添加了對 BMFONT 的支持。

          • 繼承cc.Label 內(nèi)置組件實現(xiàn), 使用上完全兼容cc.Label
          • 老項目方便接入, vscode 全局查找替換即可。
          //?cocos?creator?開發(fā)者工具,?控制臺輸入
          //?uuid?為?LocalizedLabel.ts?腳本的?uuid
          Editor.Utils.UuidUtils.compressUuid("712432e0-72b6-4e45-90c5-42bf111e8964")
          //?得到壓縮后的?uuid,?全局替換?prefab?&?fire?文件中的?cc.Label
          "71243LgcrZORZDFQr8RHolk"
          //?重新打開?prefab,?組件就以替換完畢

          廢話不多說, 該上圖了:


          支持編輯器預覽

          修改語言設置立即生效



          怎么跑起來

          克隆完項目后初始化并更新子模塊, 子模塊使用了論壇 Next 大佬的 ccc-detools 我比較喜歡這個工具, 堪稱神器。

          //?不更新無法使用瀏覽器預覽
          git?submodule?update?--init?--recursive

          安裝依賴, 項目根目錄執(zhí)行

          //?必須
          npm?install

          全局安裝 ESlint

          //?非必須
          npm?install?-g?eslint?typescript?@typescript-eslint/parser?@typescript-eslint/eslint-plugin
          //?nvm?可能還需指定需要?NODE?環(huán)境變量
          export?NODE_PATH=$HOME/.nvm/versions/node/v12.19.0/lib/node_modules??//?根據(jù)自己使用的版本

          什么是 ESlint ?

          ESLint 是一個開源的 JavaScript代碼檢查工具,由 Nicholas C. Zakas于2013年6月創(chuàng)建。代碼檢查是一種靜態(tài)的分析,常用于尋找有問題的模式或者代碼,并且不依賴于具體的編碼風格。對大多數(shù)編程語言來說都會有代碼檢查,一般來說編譯程序會內(nèi)置檢查工具。

          JavaScript 是一個動態(tài)的弱類型語言,在開發(fā)中比較容易出錯。因為沒有編譯程序,為了尋找 JavaScript 代碼錯誤通常需要在執(zhí)行過程中不斷調(diào)試。像 ESLint 這樣的可以讓程序員在編碼的過程中發(fā)現(xiàn)問題而不是在執(zhí)行的過程中。

          ESLint 的初衷是為了讓程序員可以創(chuàng)建自己的檢測規(guī)則。ESLint 的所有規(guī)則都被設計成可插入的。ESLint 的默認規(guī)則與其他的插件并沒有什么區(qū)別,規(guī)則本身和測試可以依賴于同樣的模式。為了便于人們使用,ESLint 內(nèi)置了一些規(guī)則,當然,你可以在使用過程中自定義規(guī)則。

          ESLint 使用 Node.js 編寫,這樣既可以有一個快速的運行環(huán)境的同時也便于安裝。

          為什么不是 TSlint ?

          TSLint已于2019年棄用。

          Please see this issue for more details: Roadmap: TSLint → ESLint:

          https://github.com/palantir/tslint/issues/4534

          now typescript-eslint is your best option for linting TypeScript:

          https://github.com/typescript-eslint/typescript-eslint

          在我看來使用 ESlint 的意義

          • 統(tǒng)一代碼風格, 項目組內(nèi)不同人員寫出風格基本一致的代碼。
          • 提高代碼可讀性。

          這是此項目使用到的規(guī)則

          展開查看 .eslintrc.json

          {
          ????"env":?{
          ????????"browser":?true,
          ????????"node":?true
          ????},
          ????"globals":?{
          ????????"Editor":?true,
          ????????"Vue":?true
          ????},
          ????"extends":?[
          ????????"eslint:recommended"
          ????],
          ????"parserOptions":?{
          ????????"ecmaVersion":?12,
          ????????"sourceType":?"module"
          ????},
          ????"rules":?{
          ????????//?尤達表達式
          ????????"yoda":?"warn",
          ????????//?parseInt
          ????????"radix":?"error",
          ????????//?禁止多個連續(xù)空格
          ????????"no-multi-spaces":?[
          ????????????"error",
          ????????????{
          ????????????????"ignoreEOLComments":?true,
          ????????????????"exceptions":?{
          ????????????????????"Property":?true,
          ????????????????????"VariableDeclarator":?true
          ????????????????}
          ????????????}
          ????????],
          ????????//?箭頭表達式空格
          ????????"arrow-spacing":?[
          ????????????"error",
          ????????????{
          ????????????????"before":?true,
          ????????????????"after":?true
          ????????????}
          ????????],
          ????????//?使用?===?or?!===
          ????????"eqeqeq":?"error",
          ????????//?for?in?循環(huán)必須包含?if?語句
          ????????"guard-for-in":?"error",
          ????????//?雙引號
          ????????"quotes":?[
          ????????????"error",
          ????????????"double"
          ????????],
          ????????//?行尾空格警告
          ????????"no-trailing-spaces":?"warn",
          ????????//?一行最大字符
          ????????"max-len":?[
          ????????????"warn",
          ????????????{
          ????????????????"code":?160
          ????????????}
          ????????],
          ????????//?未定義
          ????????"no-unused-vars":?"warn",
          ????????"no-undef":?"error",
          ????????//?分號
          ????????"semi":?[
          ????????????"error",
          ????????????"always",
          ????????????{
          ????????????????"omitLastInOneLineBlock":?true
          ????????????}
          ????????],
          ????????//?禁止分號前后空格
          ????????"semi-spacing":?"error",
          ????????//?禁止不必要的分號
          ????????"no-extra-semi":?"error",
          ????????//?注釋相關
          ????????"comma-spacing":?[
          ????????????"warn",
          ????????????{
          ????????????????"before":?false,
          ????????????????"after":?true
          ????????????}
          ????????],
          ????????"comma-dangle":?[
          ????????????"error",
          ????????????"always-multiline"
          ????????],
          ????????"no-multiple-empty-lines":?[
          ????????????"error",
          ????????????{
          ????????????????"max":?2,
          ????????????????"maxEOF":?1,
          ????????????????"maxBOF":?1
          ????????????}
          ????????],
          ????????"line-comment-position":?[
          ????????????"warn",
          ????????????{
          ????????????????"position":?"above"
          ????????????}
          ????????],
          ????????"spaced-comment":?[
          ????????????"error",
          ????????????"always",
          ????????????{
          ????????????????"line":?{
          ????????????????????"markers":?["/"],
          ????????????????????"exceptions":?["-",?"+"]
          ????????????????},
          ????????????????"block":?{
          ????????????????????"markers":?["!"],
          ????????????????????"exceptions":?["*"],
          ????????????????????"balanced":?true
          ????????????????}
          ????????????}
          ????????]
          ????},
          ????//?typescript?獨有規(guī)則
          ????"overrides":?[
          ????????{
          ????????????"files":?[
          ????????????????"*.ts"
          ????????????],
          ????????????"plugins":?[
          ????????????????"@typescript-eslint"
          ????????????],
          ????????????"parser":?"@typescript-eslint/parser",
          ????????????"extends":?[
          ????????????????"plugin:@typescript-eslint/recommended"
          ????????????],
          ????????????"rules":?{
          ????????????????"@typescript-eslint/no-duplicate-imports":?"error",
          ????????????????"@typescript-eslint/ban-ts-comment":?"off",
          ????????????????//?4?空格縮進
          ????????????????"@typescript-eslint/indent":?[
          ????????????????????"warn",
          ????????????????????4
          ????????????????],
          ????????????????"@typescript-eslint/explicit-module-boundary-types":?"off",
          ????????????????"@typescript-eslint/no-unused-vars":?"off",
          ????????????????"@typescript-eslint/space-before-function-paren":?[
          ????????????????????"error",
          ????????????????????{
          ????????????????????????"anonymous":?"never",
          ????????????????????????"named":?"never",
          ????????????????????????"asyncArrow":?"always"
          ????????????????????}
          ????????????????],
          ????????????????"@typescript-eslint/naming-convention":?[
          ????????????????????"warn",
          ????????????????????{
          ????????????????????????"selector":?"typeParameter",
          ????????????????????????"format":?[
          ????????????????????????????"PascalCase"
          ????????????????????????],
          ????????????????????????"prefix":?["T"]
          ????????????????????},
          ????????????????????{
          ????????????????????????"selector":?"variable",
          ????????????????????????"format":?[
          ????????????????????????????"camelCase",
          ????????????????????????????"UPPER_CASE"
          ????????????????????????]
          ????????????????????},
          ????????????????????{
          ????????????????????????"selector":?"interface",
          ????????????????????????"format":?[
          ????????????????????????????"PascalCase"
          ????????????????????????],
          ????????????????????????"custom":?{
          ????????????????????????????"regex":?"^I[A-Z]",
          ????????????????????????????"match":?true
          ????????????????????????}
          ????????????????????}
          ????????????????]
          ????????????}
          ????????},
          ????????{
          ????????????"files":?[
          ????????????????"assets/scripts/Enum.ts"
          ????????????],
          ????????????"rules":?{
          ????????????????"line-comment-position":?[
          ????????????????????"warn",
          ????????????????????{
          ????????????????????????"position":?"beside"
          ????????????????????}
          ????????????????]
          ????????????}
          ????????}
          ????]
          }

          目錄結構

          .
          ├──?README.md
          ├──?assets
          │???├──?resources
          │???│???├──?language??????????????????//?多語言根目錄
          │???│???│???├──?en????????????????????//?英文
          │???│???│???│???├──?ArialUnicodeMs.fnt
          │???│???│???│???├──?ArialUnicodeMs.png
          │???│???│???│???└──?StringConfig.json???//?字符串配置表導出配置
          │???│???│???└──?zh?????????????????????//?中文
          │???│???│???????├──?ArialUnicodeMs.fnt
          │???│???│???????├──?ArialUnicodeMs.png
          │???│???│???????└──?StringConfig.json
          │???│???├──?listview
          │???│???│???└──?prefab
          │???│???│???????├──?ListViewDemo.prefab
          │???│???│???????└──?ListViewDemoItem.prefab
          │???│???└──?setting
          │???│???????└──?prefab
          │???│???????????└──?Setting.prefab
          │???├──?scene
          │???│???└──?Main.fire
          │???├──?scripts
          │???│???├──?Enum.ts
          │???│???├──?Game.ts
          │???│???├──?Macro.ts
          │???│???├──?Main.ts
          │???│???├──?base
          │???│???│???├──?BasePopView.ts????????//?彈窗基類
          │???│???│???├──?BaseScene.ts??????????//?場景基類
          │???│???│???└──?BaseSingeton.ts???????//?單例基類
          │???│???├──?component?????????????????//?組件
          │???│???│???├──?ListView.ts???????????//?支持復用,?和滾動條的?ListView?組件
          │???│???│???├──?LocalizedLabel.ts?????//?多語言?label?組件
          │???│???│???└──?LocalizedRichText.ts??//?多語言?RichText?組件
          │???│???├──?manager
          │???│???│???├──?AssetManager.ts???????//?資源管理器
          │???│???│???├──?AudioManager.ts???????//?音頻管理器(未實現(xiàn))
          │???│???│???├──?PopViewManager.ts?????//?彈窗管理器
          │???│???│???└──?SceneManager.ts???????//?場景管理器
          │???│???├──?scene
          │???│???│???└──?Home.ts
          │???│???├──?util
          │???│???│???├──?GameUtil.ts??????????//?待實現(xiàn)
          │???│???│???├──?LocalizedUtil.ts?????//?多語言工具,?負責加載語言目錄的資源,?獲取對應?Id?文本
          │???│???│???├──?NotifyUtil.ts????????//?全局事件工具
          │???│???│???└──?StorageUtil.ts???????//?存檔工具,?相比?cc.sys.localStorage?多了一層緩存機制
          │???│???└──?view
          │???│???????├──?listviewdemo
          │???│???????│???├──?ListViewDemo.ts
          │???│???????│???└──?ListViewDemoItem.ts
          │???│???????└──?setting
          │???│???????????└──?Setting.ts
          │???└──?shader
          │???????├──?effects
          │???????│???└──?avatar-mask.effect
          │???????└──?materials
          │???????????└──?avatar-mask.mtl
          ├──?creator.d.ts
          ├──?game.d.ts????????????????????????//?為擴展的組件提供定義文件,?防止編輯器報錯
          ├──?package-lock.json
          ├──?package.json
          ├──?packages
          │???└──?game-helper??????????????????//?項目插件
          │???????├──?component????????????????//?插件提供的組件模板
          │???????│???└──?prefab
          │???????│???????├──?ListView.prefab
          │???????│???????├──?LocalizedLabel.prefab
          │???????│???????└──?LocalizedRichText.prefab
          │???????├──?i18n
          │???????│???├──?en.js
          │???????│???└──?zh.js
          │???????├──?inspectors???????????????//?組件都是繼承?creator?原生組件,?通過擴展?inspector?實現(xiàn)
          │???????│???├──?listview.js
          │???????│???├──?localizedlabel.js
          │???????│???└──?localizedrichtext.js
          │???????├──?main.js?????????????????//?編輯器模式下獲取多語言文本方法
          │???????├──?package.json????????????//?里面設置了,?編輯器模式下,?返回的語言?zh?||?en
          │???????└──?panel
          │???????????└──?index.js
          ├──?project.json

          實現(xiàn)方式

          • 組件腳本
          import?{?ENotifyType?}?from?"../Enum";
          import?Game?from?"../Game";

          const?{ccclass,?property,?executeInEditMode,?menu,?inspector}?=?cc._decorator;

          @ccclass
          @executeInEditMode()
          @menu(`${CC_EDITOR?&&?Editor.T("game-helper.projectcomponent")}/LocalizedLabel`)
          @inspector("packages://game-helper/inspectors/localizedlabel.js")
          export?default?class?LocalizedLabel?extends?cc.Label?{
          ????@property()
          ????private?_tid?=?"";
          ????@property({
          ????????multiline:?true,
          ????????tooltip:?"多語言?text?id",
          ????})
          ????set?tid(value:?string)?{
          ????????this._tid?=?value;
          ????????this.updateString();
          ????}
          ????get?tid()?{
          ????????return?this._tid;
          ????}
          ????@property()
          ????private?_bmfontUrl?=?"";
          ????@property({
          ????????tooltip:?"動態(tài)加載?bmfonturl",
          ????})
          ????set?bmfontUrl(value:?string)?{
          ????????this._bmfontUrl?=?value;
          ????????this.updateString();
          ????}
          ????get?bmfontUrl()?{
          ????????return?this._bmfontUrl;
          ????}

          ????protected?onLoad()?{
          ????????super.onLoad();
          ????????Game.NotifyUtil.on(ENotifyType.LANGUAGE_CHANGED,?this.onLanguageChanged,?this);
          ????????this.updateString();
          ????}

          ????protected?onDestroy()?{
          ????????Game.NotifyUtil.off(ENotifyType.LANGUAGE_CHANGED,?this.onLanguageChanged,?this);
          ????????super.onDestroy();
          ????}

          ????/**
          ?????*?收到語言變更通知
          ?????*
          ?????*?@private
          ?????*?@memberof?LocalizedLabel
          ?????*/
          ????private?onLanguageChanged()?{
          ????????this.updateString();
          ????}

          ????/**
          ?????*?更新文本
          ?????*
          ?????*?@private
          ?????*?@returns?{*}
          ?????*?@memberof?LocalizedLabel
          ?????*/
          ????private?updateString():?void?{
          ????????if?(!this._tid)?{
          ????????????return;
          ????????}
          ????????if?(CC_EDITOR)?{
          ????????????//?編輯器模式下,?從插件中獲取文本
          ????????????Editor.Ipc.sendToMain("game-helper:getLangStr",?this._tid,?(e:?Error,?str:?string)?=>?{
          ????????????????if?(e)?{
          ????????????????????return;
          ????????????????}
          ????????????????this.string?=?""?+?str;
          ????????????});
          ????????}?else?{
          ????????????//?獲取多語言文本
          ????????????this.string?=?""?+?Game.LocalizeUtil.getLangStr(this._tid);
          ????????????//?如果使用了?bmfont,?切換對應語言的?bmfont
          ????????????//?_bmfontUrl?為自動生成
          ????????????if?(this._bmfontUrl)?{
          ????????????????const?lang?=?Game.LocalizeUtil.language;
          ????????????????this.font?=?cc.resources.get(this._bmfontUrl.replace("${lang}",?lang),?cc.BitmapFont);
          ????????????}
          ????????}
          ????}
          }
          • 插件腳本
          "use?strict";

          const?ipcMain?=?require("electron").ipcMain;
          const?fs?=?require("fs");

          module.exports?=?{

          ????localizeCfgs:?null,

          ????load()?{
          ????????ipcMain.on("editor:ready",?this.onEditorReady.bind(this));
          ????????//
          ????????this.profiles.load();
          ????????this.loadLangConfig();
          ????},

          ????unload()?{
          ????????//?execute?when?package?unloaded
          ????},

          ????onEditorReady()?{
          ????????//
          ????},
          ????//?加載多語言文本配置,?和項目中使用的是相同的
          ????loadLangConfig()?{
          ????????const?configPath?=?this.profiles.get("path");
          ????????const?lang?=?this.profiles.get("lang");
          ????????const?fileName?=?this.profiles.get("fileName");
          ????????try?{
          ????????????this.localizeCfgs?=?JSON.parse(fs.readFileSync(`${Editor.Project.path}/${configPath}/${lang}/${fileName}`,?"utf-8"));
          ????????????Editor.success("localized?config?load?success:",?lang);
          ????????}?catch?(e)?{
          ????????????Editor.warn("localized?config?load?fail:",?e);
          ????????}
          ????},

          ????messages:?{
          ????????open()?{
          ????????????Editor.Panel.open("game-helper");
          ????????},
          ????????//?reload?lang?config
          ????????reload()?{
          ????????????this.loadLangConfig();
          ????????},
          ????????//?獲取多語言配置字符串
          ????????getLangStr(event,?param)?{
          ????????????if?(this.localizeCfgs?===?null)?{
          ????????????????event.reply(new?Error("config?not?load"),?null);
          ????????????}
          ????????????const?[tid,?...args]?=?param.split(",");
          ????????????let?str?=?this.localizeCfgs[tid];
          ????????????if?(str)?{
          ????????????????args.forEach((arg,?index)?=>?{
          ????????????????????str?=?str.replace("${p"?+?(index?+?1)?+?"}",?arg);
          ????????????????});
          ????????????????event.reply(null,?str);
          ????????????}?else?{
          ????????????????event.reply(null,?tid);
          ????????????}
          ????????},
          ????},

          ????profiles:?{
          ????????config:?null,
          ????????path:?"",
          ????????load()?{
          ????????????this.path?=?Editor.url("packages://game-helper/package.json");
          ????????????this.config?=?JSON.parse(fs.readFileSync(this.path,?"utf8"));
          ????????},
          ????????get(key)?{
          ????????????return?this.config.profiles.local[key];
          ????????},
          ????},
          };

          結語

          感興趣的開發(fā)者可以克隆下來查看學習喲!

          感謝作者「alpha」的創(chuàng)作分享!本分享不定期維護中, 歡迎點擊「閱讀原文」進入社區(qū)原帖持續(xù)關注!

          如果您在使用 Cocos 引擎的過程中,獲得了獨到的開發(fā)心得、見解或是方法,并且樂于分享出來,幫助更多開發(fā)者解決技術問題,加速游戲開發(fā)效率,期待您與我們聯(lián)系!



          瀏覽 63
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩在线观看一区 | 黄片免费观看永久 | 亚洲无码黄色成人网站在线观看 | 北条麻妃九九九精品视频免费观看 | 中文字幕在线观看 |