高性能typescript版i18n库,支持React/RN/NodeJs



  • Github地址:https://github.com/fwh1990/i18n-chain

    说到国际化,你是否也常年奔波于复制粘贴的重复劳动里?像 t('home:submit') t('common:something:success') 这些没有任何提示,需要脑子去记,不仅开发效率低,而且键盘敲快一点就容易打错字母,重点是你基本发现不了这种错误。

    我更喜欢有提示的代码,利用typescript,我发明了一种使用链式操作的i18n组件,并拥有所有提示,就类似 i18n.common.something.success 这种,代码可以自动补全,保证不会写错。

    兼容性

    IE Edge Chrome Firefox Safari Node
    9+ 12+ 5+ 4+ 5+ *

    案例

    React I18n

    定义本地化文件

    // ./src/i18n/locales/en.ts
    
    const en = {
      button: {
        submit: 'Submit',
        cancel: 'Go back',
      },
      user: {
        profile: 'Tom',
      },
    };
    
    export default en;
    export type Locale = typeof en;
    
    // ./src/i18n/locales/zh.ts
    
    import { Locale } from './en';
    
    const zh: Locale = {
      button: {
        submit: '提交',
        cancel: '返回',
      },
      user: {
        profile: '原罪',
      },
    };
    
    export default zh;
    

    创建i18n实例

    // ./src/i18n/index.ts
    
    import { createI18n } from '@i18n-chain/*';
    import en from './locales/en';
    
    const i18n = createI18n({
      defaultLocale: {
        key: 'en',
        values: en,
      },
    });
    
    export default i18n;
    

    导入语言

    第一种, 直接定义

    import { createI18n } from '@i18n-chain/*';
    import zh from './locales/zh';
    
    const i18n = createI18n({
      defaultLocale: { ... },
    });
    
    i18n._.define('zh', zh);
    
    export default i18n;
    

    第二种, 异步导入。当组件检测到语言未定义时,会自动触发loader函数

    const i18n = createI18n({
      defaultLanguage: { ... },
      loader: (name) => import('./locales/' + name),
    });
    
    export default i18n;
    

    切换语言

    i18n._.locale('zh');
    

    调用字符串

    你可以随意地切换 i18n._.t('button.submit')i18n.button.submit,他们是等价的。唯一的区别就是前者无法享受到typescript的类型提示。

    带参数的模板

    当你想用参数的时候,你需要把模板写成数组的形式

    const en = {
      property: ['{{property1}}template{{property2}}', { property1: value2, property2: value2 }],
    };
    

    数组第二个元素就是参数列表以及,你可以设置参数的默认值。

    const en = {
      user: {
        profile: [
          'My name is {{name}}, I born in {{country}}, I am {{age}} old now, my birthday is {{birthday}}',
          {
            country: undefined,
            name: 'Tom',
            age: (value: number = 20) => {
              if (value <= 1) {
                return `${value} year`;
              } else {
                return `${value} years`;
              }
            },
            birthday: (value: Date) => {
              return value.toString();
            },
          },
        ],
      },
    };
    
    ////////////////////////////////////
    // 上面的代码可以自动推导出和下面一致的类型:
    interface User {
      Profile {
        country: string | number;
        name?: string;
        age?: number;
        birthday: Date;
      }
    }
    /////////////////////////////////////
    
    // 最小化调用
    i18n.user.profile({
      age: 20,
      country: 'China',
    });
    
    // 增加可选的属性:`name`
    i18n.user.profile({
      age: 30,
      country: 'Usa',
      name: 'Lucy',
    });
    

    方法参数 agebirthday 的区别是,age的形参中含有默认值(value: number = 20) => {...},而后者没有。有默认值意味着调用的时候可以不传参数。


    普通参数如果没有默认值,需要设置成undefined,这样typescript才能正确识别,并强制要求调用者输入对应的参数值。

    const en = {
      template: ['Hello, {{world}}', { world: undefined }]
    };
    

    在React-Hooks中使用

    // ./src/components/App.ts
    
    import React, { FC } from 'react';
    import { useI18n } from '@i18n-chain/react';
    import i18n from '../i18n';
    
    const App: FC = () => {
      // 切换语言时可以触发重渲染
      useI18n(i18n);
    
      return <button>{i18n.button.submit}</button>;
    };
    
    export default App;
    

    在React-Component中使用

    // ./src/components/App.ts
    
    import React, { FC } from 'react';
    import { I18nProvider } from '@i18n-chain/react';
    import i18n from '../i18n';
    
    const App: FC = () => {
      return <button>{i18n.button.submit}</button>;
    };
    
    // 切换语言时可以触发重渲染
    export default I18nProvider(i18n)(App);
    

    Github地址:https://github.com/fwh1990/i18n-chain ,欢迎使用


Log in to reply