際化(i18n)實(shí)戰(zhàn)指南:核心代碼與插件本地化完整解析)
Brackets 國(guó)際化i18n實(shí)戰(zhàn)指南核心代碼與插件本地化完整解析【免費(fèi)下載鏈接】bracketsAn open source code editor for the web, written in JavaScript, HTML and CSS.項(xiàng)目地址: https://gitcode.com/gh_mirrors/br/bracketsBrackets 是一款用 JavaScript、HTML 與 CSS 編寫的開(kāi)源 Web 代碼編輯器其對(duì)用戶可見(jiàn)文本的多語(yǔ)言支持Localization / i18n以nls目錄 RequireJSi18n插件為核心。本文基于 LocalizationExample 示例插件文檔 展開(kāi)結(jié)合 src/strings.js、src/nls/strings.js 等核心實(shí)現(xiàn)系統(tǒng)講解如何在 Brackets 核心代碼與第三方插件中正確添加、加載和渲染本地化字符串。讀完本文你將掌握如何為 Brackets 核心新增語(yǔ)言翻譯、如何在 JS 與 HTML 中消費(fèi)本地化字符串、如何編寫一個(gè)完整支持多語(yǔ)言的插件以及插件字符串與核心字符串加載方式的區(qū)別。一、Brackets 本地化機(jī)制總覽Brackets 為用戶可見(jiàn)文本提供了基礎(chǔ)的多語(yǔ)言支持詳見(jiàn) LocalizationExample/README.md。其設(shè)計(jì)核心約束是任何向用戶顯示文本的 JavaScript 和 HTML 代碼都不應(yīng)把英文靜態(tài)字符串直接寫在代碼里而應(yīng)把字符串集中存放在nls目錄下的strings.js文件中再按需動(dòng)態(tài)加載。整個(gè)機(jī)制由三個(gè)環(huán)節(jié)組成字符串倉(cāng)庫(kù)nls 目錄所有語(yǔ)言的字符串以define({...})形式存放在 src/nls 下root目錄存放英文基準(zhǔn)串其余每個(gè)語(yǔ)言目錄如fr、de、zh-cn存放對(duì)應(yīng)翻譯。字符串入口模塊src/strings.js代碼通過(guò)require(strings)加載 src/strings.js該模塊內(nèi)部借助i18n!nls/strings加載當(dāng)前 locale 對(duì)應(yīng)的strings.js。i18n 加載插件Brackets 使用 RequireJS 的 i18n 插件i18n!前綴按用戶 locale 動(dòng)態(tài)加載字符串文件并在缺失翻譯時(shí)自動(dòng)回退到英文保證任何語(yǔ)言環(huán)境下界面都不會(huì)出現(xiàn)空串。核心模塊 src/strings.js 的實(shí)現(xiàn)清晰地體現(xiàn)了這一點(diǎn)var strings require(i18n!nls/strings), urls require(i18n!nls/urls), stringsApp require(i18n!nls/strings-app), ... module.exports strings;該模塊還做了兩件額外的事把APP_NAME、APP_TITLE、VERSION、BUILD_TYPE等應(yīng)用級(jí)元數(shù)據(jù)作為額外全局值用正則{名稱}替換的方式注入到所有字符串模板中并通過(guò)stringsApp疊加產(chǎn)品特定字符串最終將合并結(jié)果導(dǎo)出為Strings模塊。這意味著strings.js中的字符串還支持占位符替換如{APP_NAME}為模板化文案提供了底層能力。二、locale 的注冊(cè)與解析nls/strings.js 配置無(wú)論是核心還是插件都通過(guò)nls目錄下的strings.js來(lái)聲明支持的 locale 列表。以核心為例src/nls/strings.js 內(nèi)容如下module.exports { root: true, bg: true, cs: true, da: true, de: true, el: true, en-gb: true, es: true, fa-ir: true, fi: true, fr: true, gl: true, hr: true, hu: true, id: true, it: true, ja: true, ko: true, lv: true, nb: true, nl: true, pl: true, pt-br: true, pt-pt: true, ro: true, ru: true, sk: true, sr: true, sv: true, tr: true, uk: true, zh-cn: true, zh-tw: true };幾點(diǎn)關(guān)鍵說(shuō)明root: true是必填項(xiàng)表示以root目錄為英文基準(zhǔn)root目錄中缺少的翻譯會(huì)自動(dòng)回退到英文。每個(gè)鍵即一個(gè) locale 標(biāo)識(shí)命名遵循「語(yǔ)言-國(guó)家/地區(qū)」慣例如zh-cn、zh-tw、pt-br。locale 目錄結(jié)構(gòu)形如nls/locale/strings.js。新增一種語(yǔ)言時(shí)需要同時(shí)做三件事在nls/strings.js中登記 locale 鍵、新建nls/locale/strings.js翻譯文件、在root/strings.js中補(bǔ)充英文基準(zhǔn)串。目前核心支持 30 種語(yǔ)言/區(qū)域變體完整的翻譯文件位于 src/nls 各語(yǔ)言目錄中實(shí)際存在的內(nèi)容可對(duì)照 src/nls 目錄逐一查看。三、為 Brackets 核心新增本地化字符串3.1 英文基準(zhǔn)串寫入 root/strings.js新增英文字符串時(shí)把鍵值對(duì)添加到 src/nls/root/strings.js。該文件是 Brackets 全部用戶可見(jiàn)文本的英文主檔例如其中定義NOT_FOUND_ERR : The file/directory could not be found.,3.2 其他語(yǔ)言翻譯寫入對(duì)應(yīng) locale 目錄其他語(yǔ)言的翻譯應(yīng)添加到nls目錄下各 locale 文件夾內(nèi)的strings.js。例如法語(yǔ)翻譯應(yīng)修改 src/nls/fr/strings.js。翻譯文件與 root 文件采用相同的鍵名結(jié)構(gòu)僅替換值為對(duì)應(yīng)語(yǔ)言的文本。建議為某個(gè)語(yǔ)言補(bǔ)充翻譯時(shí)與 src/nls/root/strings.js 保持鍵名一一對(duì)應(yīng)未翻譯的鍵會(huì)由 i18n 插件自動(dòng)回退到英文因此部分翻譯不會(huì)導(dǎo)致崩潰但完整的鍵覆蓋才能提供最佳體驗(yàn)。四、在 Brackets 模塊中使用本地化字符串4.1 JavaScript 中使用字符串在需要顯示字符串的文件中加載Strings模塊然后通過(guò)屬性訪問(wèn)Strings require(strings);隨后即可按屬性名引用字符串例如Strings.NOT_FOUND_ERR在英文 locale 下返回 “The file/directory could not be found.”該鍵定義于 src/nls/root/strings.js。Strings模塊會(huì)根據(jù)當(dāng)前 locale 自動(dòng)返回對(duì)應(yīng)翻譯無(wú)需在業(yè)務(wù)代碼中做任何語(yǔ)言判斷。4.2 HTML 中使用字符串Mustache 模板HTML 無(wú)法直接引用strings.js中的屬性因此 Brackets 引入 Mustache.js 模板引擎來(lái)完成替換。JS 與 HTML 共用的字符串都存放在src/nls/root/strings.js但 HTML 中通過(guò)模板語(yǔ)法{{stringKeyName}}引用。例如h1 classdialog-title{{SAVE_CHANGES}}/h1渲染后得到h1 classdialog-titleSave Changes/h1其底層流程是Mustache 在 Brackets 啟動(dòng)、模塊加載時(shí)運(yùn)行——src/brackets.js 中的代碼使用 i18n 加載對(duì)應(yīng)的strings.js以 text 方式加載 HTML 文件內(nèi)容以strings.js為數(shù)據(jù)源對(duì)文本執(zhí)行Mustache.render最后將結(jié)果插入 DOM。實(shí)際證據(jù)可見(jiàn) src/brackets.js$(body).html(Mustache.render(MainViewHTML, { shouldAddAA: (brackets.platform mac), Strings: Strings }));此外src/brackets.js 還通過(guò)Object.defineProperty(window, Mustache, ...)把 Mustache 暴露為全局對(duì)象并附帶棄用警告建議插件改用brackets.getModule(thirdparty/mustache/mustache)獲取。依賴 DOM 的核心代碼在檢查或操作 DOM 之前應(yīng)監(jiān)聽(tīng)htmlContentLoadComplete事件確保 Mustache 渲染完成。五、本地化準(zhǔn)則與已知限制禁止拼接多個(gè)字符串鍵strings.js中的多個(gè)字符串鍵不應(yīng)被拼接組合使用因?yàn)椴煌Z(yǔ)言的詞序差異很大例如形容詞與名詞的位置、主謂賓順序硬拼接會(huì)導(dǎo)致翻譯錯(cuò)亂。應(yīng)盡量讓每個(gè)鍵承載完整、自洽的句子。鍵盤快捷鍵暫不支持本地化目前 Brackets 尚未支持針對(duì)鍵盤快捷鍵keyboard shortcuts的本地化快捷鍵相關(guān)顯示不在 i18n 覆蓋范圍內(nèi)。六、插件本地化實(shí)戰(zhàn)LocalizationExample 全解析插件本地化的機(jī)制與核心模塊幾乎一致同樣使用 RequireJS 的 i18n 插件按 locale 動(dòng)態(tài)加載strings.jsJavaScript 通過(guò)屬性名引用字符串HTML 片段則借助 Mustache 插入本地化文本。完整示例見(jiàn) src/extensions/samples/LocalizationExample。6.1 運(yùn)行示例插件示例插件默認(rèn)位于samples目錄不會(huì)被自動(dòng)加載將其移動(dòng)到用戶插件目錄extensions/user/即可運(yùn)行。加載后它會(huì)在Edit 菜單末尾新增一個(gè) “My New Command” 菜單項(xiàng)點(diǎn)擊該命令會(huì)先彈出一個(gè)包含本地化文本的 alert隨后展示一個(gè)包含本地化 HTML 內(nèi)容的模態(tài)對(duì)話框。6.2 目錄結(jié)構(gòu)與各文件職責(zé)示例插件的目錄結(jié)構(gòu)如下與 README 描述一致LocalizationExample/ ├── main.js # 加載插件 Strings 模塊并用 Mustache 本地化 HTML ├── package.json # 聲明支持的語(yǔ)言與本地化元數(shù)據(jù) ├── strings.js # 用 i18n 加載 nls 目錄中的 strings.js ├── htmlContent/ │ └── sampleHTMLFragment.html # 待 Mustache 本地化的 HTML 模板 └── nls/ ├── strings.js # 配置 i18n指定 root 目錄并列出插件支持的 locale ├── root/ │ └── strings.js # 英文root字符串 └── fr/ └── strings.js # 法語(yǔ)字符串各文件具體職責(zé)如下main.js—— main.js 是插件的核心邏輯var CommandManager brackets.getModule(command/CommandManager), Menus brackets.getModule(command/Menus), Dialogs brackets.getModule(widgets/Dialogs), Mustache brackets.getModule(thirdparty/mustache/mustache); var browserWrapperHtml require(text!htmlContent/sampleHTMLFragment.html); var Strings require(strings); function testCommand() { window.alert(Strings.ALERT_MESSAGE); var localizedTemplate Mustache.render(browserWrapperHtml, Strings); Dialogs.showModalDialogUsingTemplate(localizedTemplate); } var myCommandID localizationExample.command; CommandManager.register(Strings.COMMAND_NAME, myCommandID, testCommand); var menu Menus.getMenu(Menus.AppMenuBar.EDIT_MENU); menu.addMenuItem(myCommandID, null, Menus.AFTER, myCommandID);要點(diǎn)require(strings)加載本插件的字符串模塊指向插件目錄下的 strings.js核心字符串則用brackets.getModule(strings)。命令名通過(guò)Strings.COMMAND_NAME本地化因此菜單項(xiàng)文本隨 locale 變化。Mustache.render(html, Strings)以字符串模塊為數(shù)據(jù)源渲染模板再交給Dialogs.showModalDialogUsingTemplate展示。package.json—— package.json 聲明語(yǔ)言支持與本地化元數(shù)據(jù){ name: localization-example, title: Localization Example, description: A guide on how to localize your extension., version: 1.0.0, author: The Brackets team, license: MIT, engines: { brackets: 0.42.0 }, i18n: [en, fr], package-i18n: { fr: { title: Localisation Exemple, description: Un guide sur la fa?on de localiser votre poste. } } }i18n: [en, fr]聲明插件支持的語(yǔ)言列表。package-i18n提供各語(yǔ)言下的本地化元數(shù)據(jù)如 Extension Manager 中顯示的標(biāo)題與描述鍵為 locale值為覆蓋字段。strings.js—— strings.js 是插件字符串入口一行即完成動(dòng)態(tài)加載module.exports require(i18n!nls/strings);nls/strings.js—— nls/strings.js 配置 i18n指定 root 目錄并列出插件支持的 localemodule.exports { root: true, fr: true };nls/root/strings.js—— 英文基準(zhǔn)串查看完整文件define({ COMMAND_NAME : My New Command, ALERT_MESSAGE : This is a sample alert message, DIALOG_TITLE : Localized Dialog Example, DIALOG_TEXT : This is an example of localized text in Brackets, DIALOG_OK : OK });nls/fr/strings.js—— 法語(yǔ)翻譯查看完整文件鍵名與 root 一致僅值不同如COMMAND_NAME: Ma nouvelle commande。htmlContent/sampleHTMLFragment.html—— Mustache 模板查看完整文件div classsample-localized-dialog modal div classmodal-header h1 classdialog-title{{DIALOG_TITLE}}/h1 /div div classmodal-body {{DIALOG_TEXT}} /div div classmodal-footer a href# classdialog-button btn primary contenteditable="false">【免費(fèi)下載鏈接】bracketsAn open source code editor for the web, written in JavaScript, HTML and CSS.項(xiàng)目地址: https://gitcode.com/gh_mirrors/br/brackets創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考