目錄
引導刺激應用程式
I18下一個
一次性翻译
复数和性别
切换区域设置
在 URL 中保留区域设置
检测区域设置
结论
首頁 CMS教程 &#&按 使用 I18Next 本地化刺激應用程式

使用 I18Next 本地化刺激應用程式

Aug 28, 2023 pm 11:53 PM

使用 I18Next 本地化刺激应用程序

在我之前的文章中,我介紹了 Stimulus——一個由 Basecamp 創建的簡單的 JavaScript 框架。今天我將討論 Stimulus 應用程式的國際化,因為該框架不提供任何開箱即用的國際化工具。國際化是重要的一步,特別是當您的應用程式被世界各地的人們使用時,因此對如何進行國際化的基本了解可能真的會派上用場。

當然,由您決定實作哪種國際化解決方案,無論是 jQuery.I18n、Polyglot 或其他解決方案。在本教程中,我想向您展示一個名為 I18next 的流行 I18n 框架,它具有許多很酷的功能,並提供許多額外的第三方插件來進一步簡化開發過程。即使具有所有這些功能,I18next 也不是一個複雜的工具,您不需要學習大量文件即可開始使用。

在本文中,您將了解如何借助 I18next 程式庫在 Stimulus 應用程式中啟用 I18n 支援。具體來說,我們將討論:

  • I18下一個設定
  • 翻譯檔案並非同步載入
  • 執行翻譯並一次翻譯整個頁面
  • 處理複數和性別資訊
  • 在區域設定之間切換並將所選區域設定保留在 GET 參數中
  • 根據使用者的偏好設定區域設定

原始程式碼可在教學 GitHub 儲存庫中找到。

引導刺激應用程式

首先,讓我們複製 Stimulus Starter 專案並使用 Yarn 套件管理器安裝所有依賴項:

git clone https://github.com/stimulusjs/stimulus-starter.git
cd stimulus-starter
yarn install
登入後複製

我們將建立一個簡單的 Web 應用程式來載入有關註冊用戶的資訊。對於每個用戶,我們將顯示他/她的登入名稱以及他/她迄今為止上傳的照片數量(這些照片是什麼並不重要)。

此外,我們將在頁面頂部提供一個語言切換器。選擇語言後,介面應立即翻譯,無需重新載入頁面。此外,URL 應附加 ?locale GET 參數,指定目前使用的區域設定。當然,如果頁面載入時已提供此參數,則應自動設定正確的語言。

好的,讓我們繼續渲染我們的用戶。將以下程式碼行加入到 public/index.html 檔案中:

<div data-controller="users" data-users-url="/api/users/index.json"></div>
登入後複製

在這裡,我們使用 users 控制器並提供一個用於載入使用者的 URL。在現實應用程式中,我們可能會有一個伺服器端腳本,用於從資料庫中獲取使用者並使用 JSON 進行回應。然而,在本教程中,我們只需將所有必要的資料放入 public/api/users/index.json 檔案中即可:

[
  {
    "login": "johndoe",
    "photos_count": "15",
    "gender": "male"
  },
  {
    "login": "annsmith",
    "photos_count": "20",
    "gender": "female"
  }
]
登入後複製

現在建立一個新的src/controllers/users_controller.js檔案:

import { Controller } from "stimulus"

export default class extends Controller {
  connect() {
    this.loadUsers()
  }
}
登入後複製

一旦控制器連接到 DOM,我們就會藉助 loadUsers() 方法非同步載入使用者:

  loadUsers() {
    fetch(this.data.get("url"))
    .then(response => response.text())
    .then(json => {
      this.renderUsers(json)
    })
  }
登入後複製

此方法向給定 URL 發送獲取請求,獲取回應,最後呈現使用者:

  renderUsers(users) {
    let content = ''
    JSON.parse(users).forEach((user) => {
      content += `<div>Login: ${user.login}<br>Has uploaded ${user.photos_count} photo(s)</div><hr>`
    })
    this.element.innerHTML = content
  }
登入後複製

renderUsers() 依序解析JSON,建構一個包含所有內容的新字串,最後將此內容顯示在頁面上(this.element 是將傳回控制器連接到的實際DOM 節點,在我們的例子中是div )。

I18下一個

現在我們將繼續將 I18next 整合到我們的應用程式中。在我們的專案中添加兩個庫:I18next 本身和一個插件,以實現從後端異步加載翻譯檔案:

yarn add i18next i18next-xhr-backend
登入後複製

我們將把所有與 I18next 相關的東西儲存在一個單獨的 src/i18n/config.js 檔案中,所以現在就建立它:

import i18next from 'i18next'
import I18nXHR from 'i18next-xhr-backend'

const i18n = i18next.use(I18nXHR).init({
  fallbackLng: 'en',
  whitelist: ['en', 'ru'],
  preload: ['en', 'ru'],
  ns: 'users',
  defaultNS: 'users',
  fallbackNS: false,
  debug: true,
  backend: {
    loadPath: '/i18n/{{lng}}/{{ns}}.json',
  }
}, function(err, t) {
  if (err) return console.error(err)
});
 
export { i18n as i18n }
登入後複製

讓我們從上到下了解這裡發生了什麼:

  • use(I18nXHR) 啟用 i18next-xhr-backend 外掛程式。

  • fallbackLng 告訴它使用英語作為後備語言。

  • whitelist 只允許設定英文和俄文。當然,您可以選擇任何其他語言。

  • preload 指示從伺服器預先載入翻譯文件,而不是在選擇對應語言時載入它們。

  • ns 表示“命名空間”,接受字串或陣列。在此範例中,我們只有一個命名空間,但對於較大的應用程序,您可以引入其他命名空間,例如admincartprofile等。每個命名空間都應該建立一個單獨的翻譯檔案。

  • defaultNSusers 設定為預設命名空間。

  • fallbackNS 停用名稱空間回退。

  • debug 允许在浏览器的控制台中显示调试信息。具体来说,它会说明加载哪些翻译文件、选择哪种语言等。您可能希望在将应用程序部署到生产环境之前禁用此设置。

  • backend 为 I18nXHR 插件提供配置并指定从何处加载翻译。请注意,路径应包含区域设置的标题,而文件应以命名空间命名并具有 .json 扩展名

  • function(err, t) 是当 I18next 准备好时(或当出现错误时)运行的回调。

接下来,让我们制作翻译文件。俄语翻译应放入 public/i18n/ru/users.json 文件中:

{
  "login": "Логин"
}
登入後複製

login 这里是翻译键,而 Логин 是要显示的值。

英文翻译应该转到 public/i18n/en/users.json 文件:

{
  "login": "Login"
}
登入後複製

为了确保 I18next 正常工作,您可以将以下代码行添加到 i18n/config.js 文件内的回调中:

// config goes here...
function(err, t) {
  if (err) return console.error(err)
  console.log(i18n.t('login'))
}
登入後複製

在这里,我们使用一个名为 t 的方法,意思是“翻译”。该方法接受翻译键并返回相应的值。

但是,我们可能有很多 UI 部分需要翻译,而使用 t 方法来翻译会非常乏味。相反,我建议您使用另一个名为 loc-i18next 的插件,它允许您一次翻译多个元素。

一次性翻译

安装loc-i18next插件:

yarn add loc-i18next
登入後複製

将其导入src/i18n/config.js文件的顶部:

import locI18next from 'loc-i18next'
登入後複製

现在提供插件本身的配置:

// other config

const loci18n = locI18next.init(i18n, {
  selectorAttr: 'data-i18n',
  optionsAttr: 'data-i18n-options',
  useOptionsAttr: true
});

export { loci18n as loci18n, i18n as i18n }
登入後複製

这里有几点需要注意:

  • locI18next.init(i18n) 基于之前定义的 I18next 实例创建一个新的插件实例。
  • selectorAttr 指定使用哪个属性来检测需要本地化的元素。基本上,loc-i18next 将搜索此类元素并使用 data-i18n 属性的值作为翻译键。

  • optionsAttr 指定哪个属性包含附加翻译选项。

  • useOptionsAttr 指示插件使用其他选项。

我们的用户正在异步加载,因此我们必须等到此操作完成,然后才执行本地化。现在,我们简单地设置一个计时器,在调用 localize() 方法之前等待两秒——当然,这是一个临时的 hack。

  import { loci18n } from '../i18n/config'
  
  // other code...
  
  loadUsers() {
    fetch(this.data.get("url"))
    .then(response => response.text())
    .then(json => {
      this.renderUsers(json)
      setTimeout(() => { // <---
        this.localize()
      }, '2000')
    })
  }
登入後複製

编写 localize() 方法本身的代码:

  localize() {
    loci18n('.users')
  }
登入後複製

如您所见,我们只需要将选择器传递给 loc-i18next 插件即可。内部的所有元素(设置了 data-i18n 属性)都将自动本地化。

现在调整 renderUsers 方法。现在,我们只翻译“Login”一词:

  renderUsers(users) {
    let content = ''
    JSON.parse(users).forEach((user) => {
      content += `<div class="users">ID: ${user.id}<br><span data-i18n="login"></span>: ${user.login}<br>Has uploaded ${user.photos_count} photo(s)</div><hr>`
    })
    this.element.innerHTML = content
  }
登入後複製

不错!重新加载页面,等待两秒钟,并确保每个用户都显示“登录”字样。

复数和性别

我们对部分界面进行了本地化,这真的很酷。尽管如此,每个用户还有两个字段:上传的照片数量和性别。由于我们无法预测每个用户将拥有多少张照片,因此应根据给定的数量将“照片”一词正确地复数化。为此,我们需要之前配置的 data-i18n-options 属性。要提供计数,应为 data-i18n-options 分配以下对象:{ "count": YOUR_COUNT }

性别信息也应考虑在内。英语中的“uploaded”一词可以适用于男性和女性,但在俄语中它要么变成“загрузил”或“загрузила”,所以我们再次需要 data-i18n-options,其中有 { "context": "GENDER" } 作为值。顺便请注意,您可以利用此上下文来完成其他任务,而不仅仅是提供性别信息。

  renderUsers(users) {
    let content = ''
    JSON.parse(users).forEach((user) => {
      content += `<div class="users"><span data-i18n="login"></span>: ${user.login}<br><span data-i18n="uploaded" data-i18n-options="{ 'context': '${user.gender}' }"></span> <span data-i18n="photos" data-i18n-options="{ 'count': ${user.photos_count} }"></span></div><hr>`
    })
    this.element.innerHTML = content
  }
登入後複製

现在更新英文翻译:

{
  "login": "Login",
  "uploaded": "Has uploaded",
  "photos": "one photo",
  "photos_plural": "{{count}} photos"
}
登入後複製

这里没什么复杂的。由于对于英语,我们不关心性别信息(即上下文),因此翻译键应该只是 uploaded。为了提供正确的复数翻译,我们使用 photosphotos_plural 键。 {{count}} 部分为插值,将替换为实际数字。

至于俄语,事情就更复杂了:

{
  "login": "Логин",
  "uploaded_male": "Загрузил уже",
  "uploaded_female": "Загрузила уже",
  "photos_0": "одну фотографию",
  "photos_1": "{{count}} фотографии",
  "photos_2": "{{count}} фотографий"
}
登入後複製

首先,请注意,我们有两个可能的上下文的 uploaded_maleuploaded_female 键。接下来,俄语中的复数规则也比英语中更复杂,因此我们必须提供不是两个而是三个可能的短语。 I18next 支持多种开箱即用的语言,这个小工具可以帮助您了解应该为给定语言指定哪些复数键。

切换区域设置

我们已经完成了应用程序的翻译,但用户应该能够在区域设置之间切换。因此,向 public/index.html 文件添加一个新的“语言切换器”组件:

<ul data-controller="languages" class="switcher"></ul>
登入後複製

src/controllers/languages_controller.js 文件中制作相应的控制器:

import { Controller } from "stimulus"
import { i18n, loci18n } from '../i18n/config'

export default class extends Controller {
    initialize() {
      let languages = [
        {title: 'English', code: 'en'},
        {title: 'Русский', code: 'ru'}
      ]

      this.element.innerHTML = languages.map((lang) => {
        return `<li data-action="click->languages#switchLanguage"
        data-lang="${lang.code}">${lang.title}</li>`
      }).join('')
    }
}
登入後複製

这里我们使用 initialize() 回调来显示支持的语言列表。每个 li 都有一个 data-action 属性,该属性指定单击元素时应触发的方法(在本例中为 switchLanguage)。

现在添加 switchLanguage() 方法:

  switchLanguage(e) {
    this.currentLang = e.target.getAttribute("data-lang")
  }
登入後複製

它只是获取事件的目标并获取 data-lang 属性的值。

我还想为 currentLang 属性添加 getter 和 setter:

  get currentLang() {
    return this.data.get("currentLang")
  }

  set currentLang(lang) {
    if(i18n.language !== lang) {
      i18n.changeLanguage(lang)
    }

    if(this.currentLang !== lang) {
      this.data.set("currentLang", lang)
      loci18n('body')
      this.highlightCurrentLang()
    }
  }
登入後複製

getter 非常简单——我们获取当前使用的语言的值并返回它。

setter 更复杂。首先,如果当前设置的语言与所选语言不相等,我们使用 changeLanguage 方法。此外,我们将新选择的语言环境存储在 data-current-lang 属性(在 getter 中访问)下,使用 loc-i18next 插件本地化 HTML 页面的主体,最后突出显示当前使用的区域设置。

让我们编写 highlightCurrentLang() 的代码:

  highlightCurrentLang() {
    this.switcherTargets.forEach((el, i) => {
      el.classList.toggle("current", this.currentLang === el.getAttribute("data-lang"))
    })
  }
登入後複製

这里我们迭代区域设置切换器的数组,并将它们的 data-lang 属性的值与当前使用的区域设置的值进行比较。如果值匹配,则为切换器分配 current CSS 类,否则删除该类。

为了使 this.switcherTargets 构建工作,我们需要按以下方式定义刺激目标:

static targets = [ "switcher" ]
登入後複製

此外,为 lis 添加值为 switcherdata-target 属性:

  initialize() {
      // ...
      this.element.innerHTML = languages.map((lang) => {
        return `<li data-action="click->languages#switchLanguage"
        data-target="languages.switcher" data-lang="${lang.code}">${lang.title}</li>`
      }).join('')
      // ...
  }
登入後複製

另一个需要考虑的重要事项是翻译文件可能需要一些时间来加载,我们必须等待此操作完成才能允许切换区域设置。因此,让我们利用 loaded 回调:

  initialize() {
    i18n.on('loaded', (loaded) => { // <---
      let languages = [
        {title: 'English', code: 'en'},
        {title: 'Русский', code: 'ru'}
      ]

      this.element.innerHTML = languages.map((lang) => {
        return `<li data-action="click->languages#switchLanguage"
        data-target="languages.switcher" data-lang="${lang.code}">${lang.title}</li>`
      }).join('')

      this.currentLang = i18n.language
    })
  }
登入後複製

最后,不要忘记从 loadUsers() 方法中删除 setTimeout

  loadUsers() {
    fetch(this.data.get("url"))
    .then(response => response.text())
    .then(json => {
      this.renderUsers(json)
      this.localize()
    })
  }
登入後複製

在 URL 中保留区域设置

切换语言环境后,我想在包含所选语言代码的 URL 中添加 ?lang GET 参数。在 History API 的帮助下,可以轻松地添加 GET 参数而不重新加载页面:

  set currentLang(lang) {
    if(i18n.language !== lang) {
      i18n.changeLanguage(lang)
      window.history.pushState(null, null, `?lang=${lang}`) // <---
    }

    if(this.currentLang !== lang) {
      this.data.set("currentLang", lang)
      loci18n('body')
      this.highlightCurrentLang()
    }
  }
登入後複製

检测区域设置

我们今天要实现的最后一件事是能够根据用户的偏好设置区域设置。一个名为 LanguageDetector 的插件可以帮助我们解决这个任务。添加新的 Yarn 包:

yarn add i18next-browser-languagedetector
登入後複製

i18n/config.js 文件中导入 LanguageDetector

import LngDetector from 'i18next-browser-languagedetector'
登入後複製

现在调整配置:

const i18n = i18next.use(I18nXHR).use(LngDetector).init({ // <---
  // other options go here...
  detection: {
    order: ['querystring', 'navigator', 'htmlTag'],
    lookupQuerystring: 'lang',
  }
}, function(err, t) {
  if (err) return console.error(err)
});
登入後複製

order 选项列出了插件应尝试的所有技术(按重要性排序),以便“猜测”首选区域设置:

  • querystring 表示检查包含区域设置代码的 GET 参数。
  • lookupQuerystring 设置要使用的 GET 参数的名称,在我们的例子中是 lang
  • navigator 表示从用户的请求中获取语言环境数据。
  • htmlTag 涉及从 html 标记的 lang 属性获取首选区域设置。

结论

在本文中,我们介绍了 I18next——一种轻松翻译 JavaScript 应用程序的流行解决方案。您已经学习了如何将 I18next 与 Stimulus 框架集成、配置它以及以异步方式加载翻译文件。此外,您还了解了如何在区域设置之间切换以及如何根据用户的偏好设置默认语言。

I18next 有一些额外的配置选项和许多插件,因此请务必浏览其官方文档以了解更多信息。另请注意,Stimulus 不会强制您使用特定的本地化解决方案,因此您也可以尝试使用 jQuery.I18n 或 Polyglot 等解决方案。

這就是今天的全部內容!感謝您的閱讀,直到下次。

以上是使用 I18Next 本地化刺激應用程式的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何開始WordPress博客:初學者的分步指南 如何開始WordPress博客:初學者的分步指南 Apr 17, 2025 am 08:25 AM

博客是人們在網上表達觀點、意見和見解的理想平台。許多新手渴望建立自己的網站,卻因擔心技術障礙或成本問題而猶豫不決。然而,隨著平台不斷發展以滿足初學者的能力和需求,現在開始變得比以往任何時候都更容易。 本文將逐步指導您如何建立一個WordPress博客,從主題選擇到使用插件提升安全性和性能,助您輕鬆創建自己的網站。 選擇博客主題和方向 在購買域名或註冊主機之前,最好先確定您計劃涵蓋的主題。個人網站可以圍繞旅行、烹飪、產品評論、音樂或任何激發您興趣的愛好展開。專注於您真正感興趣的領域可以鼓勵持續寫作

如何在父分類的存檔頁面上顯示子分類 如何在父分類的存檔頁面上顯示子分類 Apr 19, 2025 pm 11:54 PM

您想了解如何在父分類存檔頁面上顯示子分類嗎?在自定義分類存檔頁面時,您可能需要執行此操作,以使其對訪問者更有用。在本文中,我們將向您展示如何在父分類存檔頁面上輕鬆顯示子分類。為什麼在父分類存檔頁面上顯示子分類?通過在父分類存檔頁面上顯示所有子分類,您可以使其不那麼通用,對訪問者更有用。例如,如果您運行一個關於書籍的WordPress博客,並且有一個名為“主題”的分類法,那麼您可以添加“小說”、“非小說”等子分類法,以便您的讀者可以

如何在 WordPress 中獲取登錄用戶信息以獲得個性化結果 如何在 WordPress 中獲取登錄用戶信息以獲得個性化結果 Apr 19, 2025 pm 11:57 PM

最近,我們向您展示瞭如何通過允許用戶將自己喜歡的帖子保存在個性化庫中來為用戶創建個性化體驗。您可以通過在某些地方(即歡迎屏幕)使用他們的名字,將個性化結果提升到另一個水平。幸運的是,WordPress使獲取登錄用戶的信息變得非常容易。在本文中,我們將向您展示如何檢索與當前登錄用戶相關的信息。我們將利用get_currentuserinfo(); 功能。這可以在主題中的任何地方使用(頁眉、頁腳、側邊欄、頁面模板等)。為了使其工作,用戶必須登錄。因此我們需要使用

wordpress文章列表怎麼調 wordpress文章列表怎麼調 Apr 20, 2025 am 10:48 AM

有四種方法可以調整 WordPress 文章列表:使用主題選項、使用插件(如 Post Types Order、WP Post List、Boxy Stuff)、使用代碼(在 functions.php 文件中添加設置)或直接修改 WordPress 數據庫。

對於初學者來說,WordPress容易嗎? 對於初學者來說,WordPress容易嗎? Apr 03, 2025 am 12:02 AM

WordPress對初學者來說容易上手。 1.登錄後台後,用戶界面直觀,簡潔的儀表板提供所有必要功能鏈接。 2.基本操作包括創建和編輯內容,所見即所得的編輯器簡化了內容創建。 3.初學者可以通過插件和主題擴展網站功能,學習曲線存在但可以通過實踐掌握。

如何在 WordPress 中按帖子過期日期對帖子進行排序 如何在 WordPress 中按帖子過期日期對帖子進行排序 Apr 19, 2025 pm 11:48 PM

過去,我們分享過如何使用PostExpirator插件使WordPress中的帖子過期。好吧,在創建活動列表網站時,我們發現這個插件非常有用。我們可以輕鬆刪除過期的活動列表。其次,多虧了這個插件,按帖子過期日期對帖子進行排序也非常容易。在本文中,我們將向您展示如何在WordPress中按帖子過期日期對帖子進行排序。更新了代碼以反映插件中更改自定義字段名稱的更改。感謝Tajim在評論中讓我們知道。在我們的特定項目中,我們將事件作為自定義帖子類型。現在

如何在 WordPress 中顯示查詢數量和頁面加載時間 如何在 WordPress 中顯示查詢數量和頁面加載時間 Apr 19, 2025 pm 11:51 PM

我們的一位用戶詢問其他網站如何在頁腳中顯示查詢數量和頁面加載時間。您經常會在網站的頁腳中看到這一點,它可能會顯示類似以下內容:“1.248秒內64個查詢”。在本文中,我們將向您展示如何在WordPress中顯示查詢數量和頁面加載時間。只需將以下代碼粘貼到主題文件中您喜歡的任何位置(例如footer.php)。 queriesin

我可以在3天內學習WordPress嗎? 我可以在3天內學習WordPress嗎? Apr 09, 2025 am 12:16 AM

能在三天內學會WordPress。 1.掌握基礎知識,如主題、插件等。 2.理解核心功能,包括安裝和工作原理。 3.通過示例學習基本和高級用法。 4.了解調試技巧和性能優化建議。

See all articles