Giter VIP home page Giter VIP logo

i18n-chain's Introduction

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

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

License GitHub Workflow Status (branch) Codecov

兼容性

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

安装

React | RN | Taro@3

yarn add @i18n-chain/react

NodeJS

yarn add @i18n-chain/node

使用

定义本地化文件

// ./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');

字符串模板

有时候您需要在组件外预定义一系列内容,此时不得不使用字符串模板('button.submit')来代表,并在组件渲染时翻译成相应的文字。很显然,这串字符串没有任何提示,即使写错了也没人知道。

别担心,框架提供了生成字符串模板的功能,现在一起试试

const key = i18n.literal.button.submit;
key === 'button.submit' // true

const value = i18n.translate(key);
value === 'Submit' // true

酷,带有提示的字符串模板也重新拥有了灵魂,不必再担心会写错了,让IDE和TS去处理吧。

带参数的模板

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

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.chain.user.profile({
  country: 'Earth',
  birthday: new Date(),
});

// 增加可选的属性:`name` 和 `age`
i18n.chain.user.profile({
  country: 'Earth',
  name: 'Lucy',
  age: 30,
  birthday: new Date(),
});

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


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

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

在Hooks中使用

import React, { FC } from 'react';
import i18n from '../i18n';

const App: FC = () => {
  // 使用use使得切换语言时可以重渲染
  const chain = i18n.use();

  return <button>{chain.button.submit}</button>;
};

export default App;

在Class组件中使用

import React, { PureComponent } from 'react';
import { InjectedI18nProps } from '@i18n-chain/react';
import i18n from '../i18n';

type Props = InjectedI18nProps<typeof i18n>;

class App extends PureComponent<Props> {
  render() {
    const { chain } = this.props;

    return <button>{chain.button.submit}</button>;
  }
};

// 使用高阶组件使得切换语言时可以重渲染
export default i18n.hoc(App);

在线Demo

CodeSandbox

i18n-chain's People

Contributors

fwh1990 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

i18n-chain's Issues

Taro Next 版本的 useState 等方法需要从 react 包中导出

最近将项目中的 Taro 升级到了 Taro Next,然后编译时 useI18n 报错,发现是 useState 等方法是从 taro 中导出而导致的问题,像这种情况,有办法判断 taro 的版本然后从不同的 package 中导出吗?还是要开个新的分支?

error: bundling failed: src/i18n/index.ts: src/i18n/index.ts:Invalid call at line 9: import('./locales/' + name)

loader: name => import('./locales/' + name)这行代码报错是为什么?在react-native中使用的

BUNDLE [android, dev] ./index.js ▓▓▓▓▓▓▓▓▓░░░░░░░ 58.1% (828/1086)::ffff:127.0.0.1 - - [10/Nov/2020:05:51:36 +0000] "GET /index.bundle?platform=android&dev=true&minify=false HTTP/1.1" 500 - "-" "okhttp/3.12.1"
error: bundling failed: src/i18n/index.ts: src/i18n/index.ts:Invalid call at line 9: import('./locales/' + name)

在 react navigation 中使用时报错:Should have a queue

WechatIMG10.jpeg

代码片段

const ApplicationNavigations = () => {
  const chain = i18n.use();

  return (
    <SafeAreaView style={styles.container}>
      <NavigationContainer theme={defaultTheme} ref={navigationRef}>
        <Stack.Navigator
          initialRouteName={ROUTES.TABS}
          screenOptions={{
            cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS,
          }}>
          <Stack.Screen
            name={ROUTES.HISTORY}
            component={History}
            options={{
              title: chain.routes.HISTORY,
            }}
          />
        </Stack.Navigator>
      </NavigationContainer>
    </SafeAreaView>
  );
};

如果直接导入的话就不会出现上面的错误,但是就无法动态更新了。

    "react": "16.13.1",
    "react-native": "0.63.4",
    "@react-navigation/bottom-tabs": "^5.11.7",
    "@react-navigation/material-top-tabs": "^5.3.15",
    "@react-navigation/native": "^5.9.2",
    "@react-navigation/stack": "^5.14.2",

Handling components inside translations

For @i18n-chain/react which is designed for React, it would be very useful to be able to have html/React components inside a translation. Currently, text or placeholder can only contain strings. I would like to be able to use html tags (to style some part of the text, or to add a link to some part of the text), or even custom React components.

Taro v2.0.7 无法渲染出字符串,但是 console.log 显示正常

微信开发者工具版本:v1.02.2003121

我用v2.0.7的 Taro-cli init 一个新的项目复现了这个问题
可能和 Pull requests #1 的问题一样?我不是很了解。

image

pages/index/Index.tsx

import Taro, { Component, Config } from "@tarojs/taro";
import { View, Text } from "@tarojs/components";
import { useI18n } from "@i18n-chain/taro";

import "./index.scss";
import i18n from "../../i18n";

const Index = () => {
  useI18n(i18n);
  console.log(i18n.button.submit)
  return <View>before_{i18n.button.submit}_after</View>;
};

export default Index;

i18n/index.ts

import { createI18n } from '@i18n-chain/taro';
import en from './locales/en';

const i18n = createI18n({
  defaultLocale: {
    key: 'en',
    values: en,
  },
});

export default i18n;

i18n/locales/index.ts

const en = {
  button: {
    submit: 'Submit',
    cancel: 'Go back',
  },
  user: {
    profile: 'Tom',
  },
};

export default en;
export type Locale = typeof en;

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.