国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

實(shí)戰(zhàn)React App的i18n

arashicage / 3312人閱讀

摘要:而就是產(chǎn)品具體實(shí)現(xiàn)某一種語言和文化的過程。貨幣的符號,以及數(shù)字分割方式各個國家都存在不同。那么有沒有其他的復(fù)數(shù)形式回答當(dāng)然是肯定的,比如波蘭語。但這個是自己的語法,并非標(biāo)準(zhǔn),同時這個語法還會破壞的測試,并不是一個很好的選擇。

記得我剛來我們公司的時候,接手現(xiàn)在負(fù)責(zé)的項(xiàng)目的時候,我就發(fā)覺了一個問題:所有的文本資源都是硬編碼在代碼里面。這當(dāng)然會帶來很多問題。但考慮到我負(fù)責(zé)的這個項(xiàng)目是公司內(nèi)部的管理工具,同時大部分用戶都是中國人,因此抽離文本資源,做i18n的需求并不是十分強(qiáng)烈。

這周公司招了一位外籍員工。我并不確定她是哪一國人,不過從口音上來判斷,以及言談間她曾經(jīng)提到的加利福尼亞州,我想應(yīng)該是一位美國女性。老大說她會和其他的PM一樣,居住在廈門,遠(yuǎn)程工作,偶爾來辦公室上班。并且她也會使用我負(fù)責(zé)的這個工具。

現(xiàn)在i18n就有比較強(qiáng)烈的需求了。有必要出一個合理的架構(gòu),一勞永逸的解決問題。

i18n的主要關(guān)注點(diǎn)

i18n是Internationalization的縮寫,實(shí)際上i18n應(yīng)該是指創(chuàng)建或者調(diào)整產(chǎn)品,使得產(chǎn)品具有能輕松適配指定的語言和文化的能力。當(dāng)然,我們還有另外一個概念,叫做Localization(簡寫L10n),也就是本地化。L10n正確的說是指已經(jīng)全球化的產(chǎn)品,適配某一個具體語言和文化的這一個過程。

有點(diǎn)繞口,簡單說就是,i18n就是給產(chǎn)品添加新特性,使產(chǎn)品能夠支持對多種語言和文化(貨幣,時間等等)。而L10n就是產(chǎn)品具體實(shí)現(xiàn)某一種語言和文化的過程。

回過頭來,i18n有這么幾個主要的關(guān)注點(diǎn):

Date and times formatting

Number formatting

Language sensitive string comparison

Pluralization

Date and times formatting

不同國家對應(yīng)的日期格式其實(shí)都是不同的,盡管我不覺得十分復(fù)雜,不過細(xì)節(jié)的處理上也是有很多選擇:

weekday,你可以設(shè)置成顯示全名字,比如zh-CN的星期四,en-US的Thursday等等

month,你可以設(shè)置成數(shù)字形式,全名,短名,類似于12,December,Dec

...

完整的例子:

var date = new Date(Date.UTC(2012, 11, 20, 3, 0, 0));

// Results below use the time zone of America/Los_Angeles (UTC-0800, Pacific Standard Time)

// US English uses month-day-year order
console.log(new Intl.DateTimeFormat("en-US").format(date));
// → "12/19/2012"

// British English uses day-month-year order
console.log(new Intl.DateTimeFormat("en-GB").format(date));
// → "19/12/2012"

// Korean uses year-month-day order
console.log(new Intl.DateTimeFormat("ko-KR").format(date));
// → "2012. 12. 19."

// Arabic in most Arabic speaking countries uses real Arabic digits
console.log(new Intl.DateTimeFormat("ar-EG").format(date));
// → "???/???/????"

// for Japanese, applications may want to use the Japanese calendar,
// where 2012 was the year 24 of the Heisei era
console.log(new Intl.DateTimeFormat("ja-JP-u-ca-japanese").format(date));
// → "24/12/19"

// when requesting a language that may not be supported, such as
// Balinese, include a fallback language, in this case Indonesian
console.log(new Intl.DateTimeFormat(["ban", "id"]).format(date));
// → "19/12/2012"

var date = new Date(Date.UTC(2012, 11, 20, 3, 0, 0));
// request a weekday along with a long date
var options = { weekday: "long", year: "numeric", month: "long", day: "numeric" };
// an application may want to use UTC and make that visible
options.timeZone = "UTC";
options.timeZoneName = "short";
console.log(new Intl.DateTimeFormat("en-US", options).format(date));
// → "Thursday, December 20, 2012, GMT"
Number formatting以及Pluralization

數(shù)字的格式化,這個比較有趣。這里說的數(shù)字,包含了貨幣,百分比,浮點(diǎn)數(shù)。其中貨幣的顯示應(yīng)該是相對比較復(fù)雜的。就以en-US來說,1000美元通常顯示成$1,000.00,而1000人民幣則會顯示成¥1,000.00。貨幣的符號,以及數(shù)字分割方式各個國家都存在不同。

var number = 123456.789;

// German uses comma as decimal separator and period for thousands
console.log(new Intl.NumberFormat("de-DE").format(number));
// → 123.456,789

// India uses thousands/lakh/crore separators
console.log(new Intl.NumberFormat("en-IN").format(number));
// → 1,23,456.789

// the nu extension key requests a numbering system, e.g. Chinese decimal
console.log(new Intl.NumberFormat("zh-Hans-CN-u-nu-hanidec").format(number));
// → 一二三,四五六.七八九

var number = 123456.789;

// request a currency format
console.log(new Intl.NumberFormat("de-DE", { style: "currency", currency: "EUR" }).format(number));
// → 123.456,79 €

// the Japanese yen doesn"t use a minor unit
console.log(new Intl.NumberFormat("ja-JP", { style: "currency", currency: "JPY" }).format(number));
// → ¥123,457

涉及到數(shù)字的,還有另外一個問題,那就是語言的復(fù)數(shù)形式。中文似乎是沒有復(fù)數(shù)形式的,比如我們經(jīng)常說,一只兔子,兩只兔子。但是如果你用英語,你就能明顯發(fā)覺不對。在英語里,應(yīng)該說one rabbit,two rabbits,many rabbits。是的,英語里主要有兩種復(fù)數(shù)形式。

那么有沒有其他的 復(fù)數(shù)形式?回答當(dāng)然是肯定的,比如波蘭語。在波蘭語,兔子一詞是królik,它的復(fù)數(shù)形式有這么幾種情況:

兔子的數(shù)量是1,那么應(yīng)該這么說,królik

如果兔子的數(shù)量在2-4之間,那么應(yīng)該說,królika

如果兔子的數(shù)量不是1,并且數(shù)量在0 - 1之間,或者5 - 9之間,或者12 - 14之間,都用królików

其他情況統(tǒng)一用króliki

解決方案的設(shè)計 項(xiàng)目背景

使用facebook官方的create-react-app腳手架創(chuàng)建的react app

關(guān)注點(diǎn)

目前我的解決方案有這么幾個關(guān)注點(diǎn):

文本資源要能夠輕易的導(dǎo)出

文本資源要孤立,避免和程序?qū)崿F(xiàn)的耦合

提供極簡的接口方法設(shè)計

處理語言復(fù)數(shù)形式的庫,應(yīng)該要能很好的拓展

技術(shù)選型

FormatJS, a modular collection of JavaScript libraries for internationalization that are focused on formatting numbers, dates, and strings for displaying to people.

解決方案 項(xiàng)目的目錄結(jié)構(gòu)
/--
  |--node_modules
  |--public
  |--src
    |--app
    |--common
    |--components
    |--configs
    |--i18n
      |--app
        |--routes
          |--setting
            |--en-US.js
            |--zh-CN.js
        |--index_en-US.js
      |--common
        |--index_en-US.js
      |--components
        |--index_en-US.js
      |--index_en-US.js
      |--index_zh-CN.js
    |--index.js
    |--logo.svg
    |--setupTests.js

如上文所示,我將所有的文本資源都獨(dú)立出來,多帶帶存放在了i18n這個文件夾下。實(shí)際上,這些文本資源是有自己獨(dú)立的命名空間的,比如/src/app相關(guān)的文本資源,就會多帶帶放在這個文件夾下。其他的比如/src/common//src/components/就以此類推。

Intl類

這個類很簡單,封裝了處理文本資源的相關(guān)方法。getText的參數(shù)key需要特別注意,這個參數(shù)應(yīng)該是絕對路徑,比如app.routes.setting.preferences這樣。那么,相關(guān)的資源應(yīng)該是要放在/src/i18n/app/routes/setting/en-US.js文件里。

class Intl {
  static COMP_COMMON_TEXT = "components.Common";
  constructor(locale, resource) {
    this.locale = locale || "zh-CN";
    this.resource = resource;
  }
  getCommonText(key, params = {}) {
    return this.getText(`${Intl.COMP_COMMON_TEXT}.${key}`, params);
  }
  getText(key, params = {}) {
    let textResource = "";
    let source = this.resource;
    const locale = this.locale;
    const properties = key.split(".");
    const hasOwnProperty = Object.prototype.hasOwnProperty;
    properties.forEach((property, index) => {
      const stillNameSpace = index !== properties.length - 1;
      if (stillNameSpace) {
        source = source[property];
      } else if (hasOwnProperty.call(source[property], "default")) {
        textResource = source[property].default;
      } else {
        textResource = source[property] || "";
      }
    });
    const msg = new IntlMessageFormat(textResource, locale);
    return msg.format(params);
  }
}
IntlProvider

這是一個React組件。這里我們要利用React提供的Context這一特性,讓整個React App范圍內(nèi),都會從上下文中得到getText的方法。

我們都知道,Web app初始化的時候加載的Javascript腳本是越小越好,并且我們應(yīng)該盡力保證按需加載所需要的資源。這也是我們?yōu)槭裁蠢肳ebPack提供的Code Splitting機(jī)制讓W(xué)ebPack在打包的時候,切分出多帶帶的chunk,減少包的體積。

在WebPack 1.x的時候,我們可以使用require.ensure()。但這個是WebPack自己的語法,并非標(biāo)準(zhǔn),同時這個語法還會破壞Jest的測試,并不是一個很好的選擇。WebPack 2.x以后就開始提供基于import()的Code Splitting機(jī)制。因此我們應(yīng)該利用起來。

具體的兩個文檔:

WebPack的Code Splitting with ES2015

Dynamic import() proposal

class IntlProvider extends React.Component {
  static DEFAULT_LOCALE = "zh-CN";
  static propTypes = {
    locale: PropTypes.string,
    children: PropTypes.element,
  };
  static defaultProps = {
    locale: "zh-CN",
    children: null,
  };
  static childContextTypes = {
    getText: PropTypes.func,
    getCommonText: PropTypes.func,
  };
  state = {};
  constructor(props, context) {
    super(props, context);
    this.childContext = new Intl(props.locale);
  }
  async componentWillMount() {
    const { locale } = this.props;
    const lang = await import(`../i18n/index_${locale}.js`);
    this.childContext = new Intl(locale, lang);
    this.setState({
      lang,
    });
  }
  getChildContext() {
    if (!this.childContext) {
      return {
        getText: (key, params) => "",
        getCommonText: (key, params) => "",
      };
    }
    return {
      getText: (key, params) => this.childContext.getText(key, params),
      getCommonText: (key, params) => this.childContext.getCommonText(key, params),
    };
  }
  render() {
    const comp = (!this.state.lang)
    ? null
    : React.Children.only(this.props.children);
    return comp;
  }
}
App

使用的時候也是相當(dāng)簡單,不多說,直接上代碼。

class App extends React.PureComponent {
  render() {
    const { preferences } = this.props;
    return (
      
        
{this.props.children}
); } }
參考文檔

Tags for Identifying Languages

ECMAScript Internationalization API

Pluralization for JavaScript

ICU User Guide

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/89829.html

相關(guān)文章

  • 一個簡單且靈活易用 React 格式化和 i18n 工具

    摘要:是一個簡單且靈活易用的格式化和工具。它通過連接組件給組件一個默認(rèn)為的。是一個可以根據(jù)不同的顯示不同內(nèi)容的函數(shù)。和內(nèi)容之間的關(guān)系可以靈活地通過配置確定。在線互動演示最簡單的使用方式你好歡迎你好歡迎也可與相連 react-put 是一個簡單且靈活易用的格式化和 i18n 工具。 它通過連接組件給組件一個默認(rèn)為 put 的 props。put 是一個可以根據(jù)不同的 key 顯示不同內(nèi)容的函數(shù)...

    20171112 評論0 收藏0
  • react 國際化了解一下

    摘要:先睹為快先看一下最后的成果來一發(fā)控制臺中對應(yīng)中的信息開始原理原理其實(shí)很簡單字符串替換。拉取遠(yuǎn)程的國際化文件到本地,再根據(jù)語言做一個映射就可以了。 背景 樓主最近新接了一個項(xiàng)目,從0開始做,需要做多語言的國際化,今天搞了一下,基本達(dá)到了想要的效果, 在這里簡單分享下: 一些探索 也說不上是探索吧,就Google了一波, GitHub 上找了一個比較成熟的庫 react-i18next,...

    CrazyCodes 評論0 收藏0
  • react 國際化了解一下

    摘要:先睹為快先看一下最后的成果來一發(fā)控制臺中對應(yīng)中的信息開始原理原理其實(shí)很簡單字符串替換。拉取遠(yuǎn)程的國際化文件到本地,再根據(jù)語言做一個映射就可以了。 背景 樓主最近新接了一個項(xiàng)目,從0開始做,需要做多語言的國際化,今天搞了一下,基本達(dá)到了想要的效果, 在這里簡單分享下: 一些探索 也說不上是探索吧,就Google了一波, GitHub 上找了一個比較成熟的庫 react-i18next,...

    魏明 評論0 收藏0
  • [ 一起學(xué)React系列 -- 10 ] i18n

    摘要:假如有這么一段句子這件衣服是人民幣如果我們想將一個數(shù)字以人民幣的形式寫進(jìn)去的話可以這么做最終顯示結(jié)果是這件衣服是人民幣其實(shí)它做了兩件事一個是加符號,另一個是加分隔符。同時表示人民幣,表示美元。 今天來介紹一個非常international的東西。 i18n國際化(internationalization)的簡稱。之所以叫i18n,是因?yàn)樽帜竔和n之間有18個字母,所以才叫i18n。不...

    biaoxiaoduan 評論0 收藏0
  • React項(xiàng)目國際化(antd)多語言開發(fā)

    摘要:本國際化方案僅針對技術(shù)棧,且不會涉及服務(wù)端國際化內(nèi)容。引入多語言環(huán)境的數(shù)據(jù)雖然我只用到了文本翻譯的功能,以為就不需要加載這些數(shù)據(jù),但后來發(fā)現(xiàn)這是必須的步驟。 前言 最近新接了一個項(xiàng)目,從0開始做,需要做多語言的國際化,今天搞了一下,基本達(dá)到了想要的效果, 在這里簡單分享下: showImg(https://segmentfault.com/img/bVbuiJB); 背景國際化方案國際...

    tracymac7 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<