ReactJS: I18n với React và i18next

Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực

Ngày càng có nhiều ứng dụng được thiết kế cho thị trường toàn cầu, điều đó có nghĩa là ứng dụng của bạn sẽ cần hoạt động cho đối tượng sử dụng nhiều ngôn ngữ và phương ngữ khác nhau. React không được tích hợp sẵn internationalization (i18n), nhưng không khó để quốc tế hóa một ứng dụng, đặc biệt là với sự trợ giúp từ i18next.

i18next là một framework i18n được viết bằng và cho JavaScript. Nó cung cấp các tính năng i18n tiêu chuẩn về nội suy, định dạng và xử lý số nhiều và ngữ cảnh.

Một view 30.000 foot của i18next sẽ là nó cung cấp một hàm nhận khóa, một số tùy chọn và trả về giá trị cho ngôn ngữ hiện tại.

Sau đây là một ví dụ đơn giản về việc sử dụng chức năng nói trên với một phím đơn giản và không có tùy chọn.

i18n.t('error') // 'An error occurred' in English và
                // 'Ocurrió un error' in Spanish.

Bởi vì hàm có thể sẽ được gọi nhiều lần trong một ứng dụng, những người tạo ra i18next đã chọn một tên viết tắt: t- viết tắt của translate. Bạn thường thấy hàm t trong tài liệu i18next và bạn sẽ thấy nó được sử dụng trong bài đăng này.

Mặc dù i18next được thiết kế để hoạt động với nhiều framework, nhưng bài đăng này sẽ tập trung vào cách quốc tế hóa một ứng dụng React bằng i18next.

Để sử dụng i18next với React, hàm t cần được cung cấp sẵn cho các component cần được quốc tế hóa. Điều này có thể được thực hiện bằng nhiều cách khác nhau. Chúng ta sẽ chứng minh một vài điều dưới đây.

Tích hợp thủ công

Trước khi có thể sử dụng i18next, nó cần được cấu hình. Đây là cấu hình được sử dụng bởi các ví dụ trong bài đăng này. Nó tắt tính năng thoát giá trị vì React đã lo việc đó cho chúng ta, nó đặt ngôn ngữ hiện tại thành tiếng Anh và mã hóa bản dịch cho hai ngôn ngữ (tiếng Anh và tiếng Tây Ban Nha). Xem cấu hình i18next để có thêm tùy chọn.

import i18next from 'i18next';

i18next
  .init({
    interpolation: {
      // React already does escaping
      escapeValue: false,
    },
    lng: 'en', // 'en' | 'es'
    // Using simple hardcoded resources for simple example
    resources: {
      en: {
        translation: {
          age: { label: 'Age', },
          home: { label: 'Home', },
          name: { label: 'Name', },
        },
      },
      es: {
        translation: {
          age: { label: 'Años', },
          home: { label: 'Casa', },
          name: { label: 'Nombre', },
        },
      },
    },
  })

export default i18next

Tích hợp thủ công bắt đầu bằng việc import phiên bản i18next được định cấu hình trước của chúng ta sẽ cung cấp hàm t.

// Import một phiên bản được định cấu hình trước của i18next
import i18n from './i18n';

function Gator({ gator }) {
  return (
    <div className="Gator">
      <label>i18n.t('name.label')</label>
      <span>{ gator.name } 🐊</span>
      <label>i18n.t('age.label')</label>
      <span>{ gator.age }</span>
      <label>i18n.t('home.label')</label>
      <span>{ gator.home }</span>
    </div>
  )
}

Mặc dù ví dụ trên sẽ hiển thị các nhãn bằng ngôn ngữ hiện tại (tiếng Anh), các nhãn sẽ không được cập nhật sau khi ngôn ngữ thay đổi vì React chưa biết cách xác định khi nào ngôn ngữ đã thay đổi. Vì vậy, hãy tinh chỉnh mã để hiển thị lại component khi ngôn ngữ thay đổi.

// Import một phiên bản được định cấu hình trước của i18next
import i18n from './i18n';

class Gator extends React.Component {

  constructor(props) {
    super(props)
    this.state = {
      lng: 'en'
    }
    this.onLanguageChanged = this.onLanguageChanged.bind(this)
  }

  componentDidMount() {
    i18n.on('languageChanged', this.onLanguageChanged)
  }

  componentWillUnmount() {
    i18n.off('languageChanged', this.onLanguageChanged)
  }

  onLanguageChanged(lng) {
    this.setState({
      lng: lng
    })
  }

  render() {
    let gator = this.props.gator,
        lng = this.state.lng

    return (
      <div>
        <label>{ i18n.t('name.label', { lng }) }</label>
        <span>{ gator.name } 🐊</span>
        <label>{ i18n.t('age.label', { lng }) }</label>
        <span>{ gator.age }</span>
        <label>{ i18n.t('home.label', { lng }) }</label>
        <span>{ gator.home }</span>
      </div>
    )
  }
}

Xem ví dụ làm việc của đoạn mã trên.

Mặc dù chúng ta đã khắc phục sự cố component không hiển thị sau khi ngôn ngữ thay đổi, nhưng chúng tôi cũng giới thiệu nhiều code có sẵn:

  1. Đã thêm hai phương thức vòng đời ( componentDidMount và componentWillUnmount). (Có nghĩa là chúng tôi phải chuyển từ một component dạng hàm sang một component dạng class).
  2. Đã thêm trình xử lý sự kiện để ta có thể thông báo cho React rằng ngôn ngữ đã thay đổi.
  3. Đã giới thiệu một cơ chế khiến component hiển thị lại. Trong ví dụ trên, state đã được sử dụng. Đây là một cách khác để gọi forceUpdate sau khi ngôn ngữ thay đổi.

Có cách nào dễ hơn không? Có, có!

Ràng buộc react-i18next

May mắn thay, có một cách dễ dàng hơn với một ràng buộc: react-i18next

import { I18n } from 'react-i18next';

// Import a pre-configured instance of i18next
import i18n_unused from './i18n';

function Gator({ gator }) {
  return (
    <I18n>
      {
        (t) => {
          return (
            <div>
              <label>{ t('name.label') }</label>
              <span>{ gator.name } 🐊</span>
              <label>{ t('age.label') }</label>
              <span>{ gator.age }</span>
              <label>{ t('home.label') }</label>
              <span>{ gator.home }</span>
            </div>
          )
        }
      }
    </I18n>
  )
}

Ràng buộc React cho i18next cung cấp component I18n. Nó mong đợi một biểu thức hàm duy nhất là con của nó. Hàm này sẽ được truyền tới hàm t. (Việc sử dụng một biểu thức hàm làm con của một component được gọi là mẫu hàm dưới dạng con).

Xem ví dụ làm việc của đoạn mã trên.

Bạn hãy xem i18next và react-i18next để biết thêm chi tiết về cấu hình, bản dịch nâng cao hơn và các tùy chọn ràng buộc khác.

» Tiếp: Tìm hiểu về API ngữ cảnh của React
« Trước: Cách bảo mật Nginx bằng Lets Encrypt trên Ubuntu
Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực
Copied !!!