Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(comp:i18n): support i18n #60

Merged
merged 1 commit into from
Dec 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .ls-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ ls:
.d.ts: camelCase
.spec.ts: camelCase
.vue: PascalCase

ignore:
- packages/components/i18n/languages
44 changes: 44 additions & 0 deletions docs/i18n.zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
order: 4
title: 国际化
---

目前的默认文案是中文(`zh-CN`),如果需要使用其他语言,可以在初始化时进行配置,也可以在运行时切换,可以参考下面的方案。

## 初始化

```typescript
import { useI18n } from '@idux/components'
import { en_US } from '@idux/components/i18n/languages'


useI18n(en_US)

```

## 运行时切换

```typescript
import { addI18n, useI18n } from '@idux/components'
import { es_ES, en_US } from '@idux/components/i18n/languages'

// 首先需要先添加多语言包
addI18n([es_ES, en_US])

useI18n('es_ES')

// 运行时切换
setTimeout(()=> useI18n('en_US'), 3000)

```

注意:`es_ES`, `en_US` 是语言包名称,以下表格也遵循同样的规则。

## 支持语言

| 语言 | 语言包名 |
| ---------------- | ------ |
| 英语(美式) | en_US |
| 西班牙语 | es_ES |
| 中文简体 | zh_CN |
| 中文繁体 | zh_TW |
1 change: 1 addition & 0 deletions packages/components/core/logger/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* istanbul ignore file */
import { IDUX_COMPONENTS_PREFIX } from '../constant'
import { isDevMode } from '../utils'

Expand Down
1 change: 1 addition & 0 deletions packages/components/core/utils/installComponent.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* istanbul ignore file */
import type { App, DefineComponent } from 'vue'

export const installComponent = (component: DefineComponent) => {
Expand Down
55 changes: 55 additions & 0 deletions packages/components/i18n/__tests__/useI18n.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/* eslint-disable camelcase */
import { flushPromises, mount } from '@vue/test-utils'
import { es_ES, en_US, zh_CN } from '../languages'
import { addI18n, getI18n, useI18n } from '../useI18n'

const Comp = {
template: `<div>{{globalI18n.placeholder}}</div>`,
setup() {
const globalI18n = getI18n('global')
return { globalI18n }
},
}

describe('useI18n.ts', () => {
test('default zh_CN work', async () => {
const wrapper = mount(Comp)
expect(wrapper.text()).toEqual(zh_CN.global.placeholder)
})

test('addI18n work', async () => {
const wrapper = mount(Comp)
addI18n(es_ES)
useI18n('es_ES')
await flushPromises()

expect(wrapper.text()).toEqual(es_ES.global.placeholder)

addI18n([en_US, zh_CN])
useI18n('en_US')
await flushPromises()
expect(wrapper.text()).toEqual(en_US.global.placeholder)
})

test('useI18n work', async () => {
const wrapper = mount(Comp)
useI18n(es_ES)
await flushPromises()

expect(wrapper.text()).toEqual(es_ES.global.placeholder)

useI18n('zh-CN')
await flushPromises()
expect(wrapper.text()).toEqual(zh_CN.global.placeholder)

const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {})
useI18n('zh-TW')
expect(warnSpy).toBeCalledTimes(1)
})

test('getI18n work', async () => {
const i18n = getI18n()

expect(i18n.value).toEqual(zh_CN)
})
})
2 changes: 2 additions & 0 deletions packages/components/i18n/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './types'
export * from './useI18n'
9 changes: 9 additions & 0 deletions packages/components/i18n/languages/en_US.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Locale } from '../types'

// eslint-disable-next-line camelcase
export const en_US: Locale = {
type: 'en_US',
global: {
placeholder: 'Please select',
},
}
9 changes: 9 additions & 0 deletions packages/components/i18n/languages/es_ES.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Locale } from '../types'

// eslint-disable-next-line camelcase
export const es_ES: Locale = {
type: 'es_ES',
global: {
placeholder: 'Seleccione',
},
}
4 changes: 4 additions & 0 deletions packages/components/i18n/languages/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './en_US'
export * from './es_ES'
export * from './zh_CN'
export * from './zh_TW'
9 changes: 9 additions & 0 deletions packages/components/i18n/languages/zh_CN.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Locale } from '../types'

// eslint-disable-next-line camelcase
export const zh_CN: Locale = {
type: 'zh-CN',
global: {
placeholder: '请选择',
},
}
9 changes: 9 additions & 0 deletions packages/components/i18n/languages/zh_TW.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Locale } from '../types'

// eslint-disable-next-line camelcase
export const zh_TW: Locale = {
type: 'zh-TW',
global: {
placeholder: '請選擇',
},
}
12 changes: 12 additions & 0 deletions packages/components/i18n/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export interface GlobalLocale {
placeholder: string
}

export interface Locale {
type: LocaleType
global: GlobalLocale
}

export type LocaleKey = keyof Locale

export type LocaleType = 'en_US' | 'es_ES' | 'zh-CN' | 'zh-TW'
48 changes: 48 additions & 0 deletions packages/components/i18n/useI18n.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { computed, ref } from 'vue'
import type { ComputedRef, Ref } from 'vue'
import { IDUX_COMPONENTS_PREFIX } from '../core/constant'
import { Logger } from '../core/logger'
import { zh_CN as defaultLocale } from './languages/zh_CN'
import type { Locale, LocaleKey, LocaleType } from './types'

const currentType: Ref<LocaleType> = ref('zh-CN')
const localeMap: Partial<Record<LocaleType, Locale>> = { 'zh-CN': defaultLocale }

export function useI18n(locale: LocaleType | Locale): void {
if (typeof locale === 'string') {
if (localeMap[locale]) {
currentType.value = locale
} else {
Logger.warn(`${IDUX_COMPONENTS_PREFIX} The local [${locale}] was not added, please via 'addI18n()' add it.`)
}
} else {
const type = locale.type
localeMap[type] = locale
currentType.value = type
}
}

export function addI18n(locale: Locale | Locale[]): void {
const locales = Array.isArray(locale) ? locale : [locale]
locales.forEach(item => {
localeMap[item.type] = item
})
}

/**
*
* @param key optional, gets the value of current locale by key
*/
export function getI18n<T extends LocaleKey>(key: T): ComputedRef<Locale[T]>
export function getI18n(): ComputedRef<Locale>
export function getI18n<T extends LocaleKey>(key?: T): ComputedRef<Locale | Locale[T]> {
return computed(() => {
let currLocale = localeMap[currentType.value]
/* istanbul ignore next */
if (!currLocale) {
/* istanbul ignore next */
currLocale = defaultLocale
}
return key ? currLocale[key] : currLocale
})
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Icon.vue render work 1`] = `"<i class=\\"ix-icon ix-icon-up\\" role=\\"img\\" arialabel=\\"up\\"><svg width=\\"1em\\" height=\\"1em\\" focusable=\\"false\\" aria-hidden=\\"true\\" data-icon=\\"up\\"></svg></i>"`;
exports[`Icon.vue render work 1`] = `"<i class=\\"ix-icon ix-icon-up\\" role=\\"img\\" arialabel=\\"up\\"><svg width=\\"1em\\" height=\\"1em\\" focusable=\\"false\\" fill=\\"currentColor\\" aria-hidden=\\"true\\" data-icon=\\"up\\"></svg></i>"`;
2 changes: 1 addition & 1 deletion packages/components/icon/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export function createScriptElements(urls: string[], index = 0): void {
if (urls.length > index + 1) {
scriptElement.onload = () => createScriptElements(urls, index + 1)
scriptElement.onerror = () => {
Logger.warn(`The url ${currentUrl} failed to load`)
Logger.error(`The url ${currentUrl} failed to load`)
createScriptElements(urls, index + 1)
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ export * from './core/config'
export * from './core/types'

export * from './button'
export * from './i18n'
export * from './icon'