Repository: IduxFE/components
Pull request #111 (2021-01-04 12:28:38)

refactor(comp:i18n): update useI18n to useLocale
## PR Checklist

Please check if your PR fulfills the following requirements:

- [x] The commit message follows [our guidelines](https://github.com/IduxFE/components/blob/main/docs/contributing.zh.md#commit)
- [x] Tests for the changes have been added/updated or not needed
- [x] Docs and demo have been added/updated or not needed

## PR Type

What kind of change does this PR introduce?

- [ ] Bugfix
- [ ] Feature
- [ ] Component style update
- [ ] Code style update (formatting, local variables)
- [x] Refactoring (no functional changes, no api changes)
- [ ] Build related changes
- [ ] CI related changes
- [ ] Documentation content changes
- [ ] Application (the showcase website) / infrastructure changes
- [ ] Other... Please describe:

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying, or link to a relevant issue. -->

## What is the new behavior?

## Other information


codecov[bot]: # [Codecov](https://codecov.io/gh/IduxFE/components/pull/111?src=pr&el=h1) Report
> Merging [#111](https://codecov.io/gh/IduxFE/components/pull/111?src=pr&el=desc) (d6b0fc6) into [main](https://codecov.io/gh/IduxFE/components/commit/599b41fa8e42134da70dcfa2e2d119a9b9bf3d8a?el=desc) (599b41f) will **decrease** coverage by `0.01%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/IduxFE/components/pull/111/graphs/tree.svg?width=650&height=150&src=pr&token=PGAUXP06V3)](https://codecov.io/gh/IduxFE/components/pull/111?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##             main     #111      +/-   ##
==========================================
- Coverage   95.15%   95.13%   -0.02%     
==========================================
  Files          44       42       -2     
  Lines         557      555       -2     
  Branches       99       99              
==========================================
- Hits          530      528       -2     
  Misses         10       10              
  Partials       17       17              
```


| [Impacted Files](https://codecov.io/gh/IduxFE/components/pull/111?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [packages/components/i18n/locales/en-US.ts](https://codecov.io/gh/IduxFE/components/pull/111/diff?src=pr&el=tree#diff-cGFja2FnZXMvY29tcG9uZW50cy9pMThuL2xvY2FsZXMvZW4tVVMudHM=) | `100.00% <100.00%> (ø)` | |
| [packages/components/i18n/locales/zh-CN.ts](https://codecov.io/gh/IduxFE/components/pull/111/diff?src=pr&el=tree#diff-cGFja2FnZXMvY29tcG9uZW50cy9pMThuL2xvY2FsZXMvemgtQ04udHM=) | `100.00% <100.00%> (ø)` | |
| [packages/components/i18n/useI18n.ts](https://codecov.io/gh/IduxFE/components/pull/111/diff?src=pr&el=tree#diff-cGFja2FnZXMvY29tcG9uZW50cy9pMThuL3VzZUkxOG4udHM=) | `100.00% <100.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/IduxFE/components/pull/111?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/IduxFE/components/pull/111?src=pr&el=footer). Last update [599b41f...d6b0fc6](https://codecov.io/gh/IduxFE/components/pull/111?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/.ls-lint.yml b/.ls-lint.yml
index 1c724be0..26c73bfd 100644
--- a/.ls-lint.yml
+++ b/.ls-lint.yml
@@ -7,4 +7,4 @@ ls:
     (.zh|.en).md: kebab-case
 
 ignore:
-  - packages/components/i18n/languages
+  - packages/components/i18n/locales
diff --git a/docs/i18n.zh.md b/docs/i18n.zh.md
index 6f7fd687..0a583e13 100755
--- a/docs/i18n.zh.md
+++ b/docs/i18n.zh.md
@@ -8,37 +8,36 @@ title: 国际化
 ## 初始化
 
 ```typescript
-import { useI18n } from '@idux/components'
-import { en_US } from '@idux/components/i18n/languages'
+import { useLocale } from '@idux/components'
+import en_US from '@idux/components/i18n/locales/en-US'
 
 
-useI18n(en_US)
+useLocale(en_US)
 
 ```
 
 ## 运行时切换
 
 ```typescript
-import { addI18n, useI18n } from '@idux/components'
-import { es_ES, en_US } from '@idux/components/i18n/languages'
+import { addLocale, useLocale } from '@idux/components'
+import zh_CN from '@idux/components/i18n/locales/zh-CN'
+import en_US from '@idux/components/i18n/locales/en-US'
 
 // 首先需要先添加多语言包
-addI18n([es_ES, en_US])
+addLocale([zh_CN, en_US])
 
-useI18n('es_ES')
+useLocale('en-US')
 
 // 运行时切换
-setTimeout(()=> useI18n('en_US'), 3000)
+setTimeout(()=> useLocale('en-US'), 3000)
 
 ```
 
-注意：`es_ES`, `en_US` 是语言包名称，以下表格也遵循同样的规则。
+注意：`zh-CN`, `en-US` 是语言包名称，以下表格也遵循同样的规则。
 
 ## 支持语言
 
-| 语言             | 语言包名 |
-| ---------------- | ------ |
-| 英语（美式）     | en_US  |
-| 西班牙语         | es_ES  |
-| 中文简体         | zh_CN  |
-| 中文繁体         | zh_TW  |
+| 语言 | 语言包名 |
+| --- | --- |
+| 中文简体 | `zh-CN` |
+| 英语（美式）| `en-US` |
diff --git a/packages/components/divider/src/Divider.vue b/packages/components/divider/src/Divider.vue
index 2909288f..a1bf9e1e 100644
--- a/packages/components/divider/src/Divider.vue
+++ b/packages/components/divider/src/Divider.vue
@@ -1,16 +1,16 @@
 <template>
   <div class="ix-divider" :class="className">
-    <span v-if="$slots.default" class="ix-divider-inner-text">
+    <span v-if="withText" class="ix-divider-inner-text">
       <slot />
     </span>
   </div>
 </template>
 <script lang="ts">
-import type { Ref, SetupContext } from 'vue'
+import type { ComputedRef, SetupContext, Slots } from 'vue'
 import type { DividerConfig } from '@idux/components/core/config'
 import type { DividerProps } from './types'
 
-import { computed, defineComponent, onUpdated, ref } from 'vue'
+import { computed, defineComponent } from 'vue'
 import { PropTypes } from '@idux/cdk/utils'
 import { useGlobalConfig } from '@idux/components/core/config'
 import { getFirstValidNode, isValidElementNode } from '@idux/cdk/utils'
@@ -25,21 +25,21 @@ export default defineComponent({
   },
   setup(props: DividerProps, { slots }: SetupContext) {
     const dividerConfig = useGlobalConfig('divider')
-    let text = getFirstValidNode(slots.default?.())
-    const withText = ref(!!(text && isValidElementNode(text)))
-
-    onUpdated(() => {
-      text = getFirstValidNode(slots.default?.())
-      withText.value = !!(text && isValidElementNode(text))
-    })
-
+    const withText = useChildren(slots)
     const className = useClassName(props, dividerConfig, withText)
 
-    return { className }
+    return { className, withText }
   },
 })
 
-function useClassName(props: DividerProps, config: DividerConfig, withText: Ref<boolean>) {
+function useChildren(slots: Slots) {
+  return computed(() => {
+    const text = getFirstValidNode(slots.default?.())
+    return !!(text && isValidElementNode(text))
+  })
+}
+
+function useClassName(props: DividerProps, config: DividerConfig, withText: ComputedRef<boolean>) {
   return computed(() => {
     const position = props.position || config.position
     const type = props.type || config.type
diff --git a/packages/components/i18n/languages/en_US.ts b/packages/components/i18n/languages/en_US.ts
deleted file mode 100644
index 26fcf843..00000000
--- a/packages/components/i18n/languages/en_US.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { Locale } from '../types'
-
-// eslint-disable-next-line camelcase
-export const en_US: Locale = {
-  type: 'en_US',
-  global: {
-    placeholder: 'Please select',
-  },
-}
diff --git a/packages/components/i18n/languages/es_ES.ts b/packages/components/i18n/languages/es_ES.ts
deleted file mode 100755
index 4d173bfe..00000000
--- a/packages/components/i18n/languages/es_ES.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { Locale } from '../types'
-
-// eslint-disable-next-line camelcase
-export const es_ES: Locale = {
-  type: 'es_ES',
-  global: {
-    placeholder: 'Seleccione',
-  },
-}
diff --git a/packages/components/i18n/languages/index.ts b/packages/components/i18n/languages/index.ts
deleted file mode 100644
index 1f55b25e..00000000
--- a/packages/components/i18n/languages/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export * from './en_US'
-export * from './es_ES'
-export * from './zh_CN'
-export * from './zh_TW'
diff --git a/packages/components/i18n/languages/zh_CN.ts b/packages/components/i18n/languages/zh_CN.ts
deleted file mode 100755
index 1185dfde..00000000
--- a/packages/components/i18n/languages/zh_CN.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { Locale } from '../types'
-
-// eslint-disable-next-line camelcase
-export const zh_CN: Locale = {
-  type: 'zh-CN',
-  global: {
-    placeholder: '请选择',
-  },
-}
diff --git a/packages/components/i18n/languages/zh_TW.ts b/packages/components/i18n/languages/zh_TW.ts
deleted file mode 100755
index b5ae50bf..00000000
--- a/packages/components/i18n/languages/zh_TW.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { Locale } from '../types'
-
-// eslint-disable-next-line camelcase
-export const zh_TW: Locale = {
-  type: 'zh-TW',
-  global: {
-    placeholder: '請選擇',
-  },
-}
diff --git a/packages/components/i18n/locales/en-US.ts b/packages/components/i18n/locales/en-US.ts
new file mode 100644
index 00000000..ae13954b
--- /dev/null
+++ b/packages/components/i18n/locales/en-US.ts
@@ -0,0 +1,13 @@
+import { Locale } from '../types'
+/* eslint-disable camelcase */
+const en_US: Locale = {
+  type: 'en-US',
+  global: {
+    placeholder: 'Please select',
+  },
+  empty: {
+    description: 'No Data',
+  },
+}
+
+export default en_US
diff --git a/packages/components/i18n/locales/zh-CN.ts b/packages/components/i18n/locales/zh-CN.ts
new file mode 100755
index 00000000..890032ae
--- /dev/null
+++ b/packages/components/i18n/locales/zh-CN.ts
@@ -0,0 +1,13 @@
+import { Locale } from '../types'
+/* eslint-disable camelcase */
+const zh_CN: Locale = {
+  type: 'zh-CN',
+  global: {
+    placeholder: '请选择',
+  },
+  empty: {
+    description: '暂无数据',
+  },
+}
+
+export default zh_CN
diff --git a/packages/components/i18n/types.ts b/packages/components/i18n/types.ts
index 2b4a7c40..5e39c427 100644
--- a/packages/components/i18n/types.ts
+++ b/packages/components/i18n/types.ts
@@ -2,11 +2,16 @@ export interface GlobalLocale {
   placeholder: string
 }
 
+export interface EmptyLocale {
+  description: string
+}
+
 export interface Locale {
   type: LocaleType
   global: GlobalLocale
+  empty: EmptyLocale
 }
 
 export type LocaleKey = keyof Locale
 
-export type LocaleType = 'en_US' | 'es_ES' | 'zh-CN' | 'zh-TW'
+export type LocaleType = 'zh-CN' | 'en-US'
diff --git a/packages/components/i18n/useI18n.ts b/packages/components/i18n/useI18n.ts
index 6ffb8069..1c4b658d 100644
--- a/packages/components/i18n/useI18n.ts
+++ b/packages/components/i18n/useI18n.ts
@@ -1,19 +1,21 @@
+import type { ComputedRef } from 'vue'
+import type { Locale, LocaleKey, LocaleType } from './types'
+
 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'
+import defaultLocale from './locales/zh-CN'
 
-const currentType: Ref<LocaleType> = ref('zh-CN')
+const currentType = ref<LocaleType>('zh-CN')
 const localeMap: Partial<Record<LocaleType, Locale>> = { 'zh-CN': defaultLocale }
 
-export function useI18n(locale: LocaleType | Locale): void {
+export function useLocale(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.`)
+      Logger.warn(`${IDUX_COMPONENTS_PREFIX} The local [${locale}] was not added, please via 'addLocale()' add it.`)
     }
   } else {
     const type = locale.type
@@ -22,7 +24,7 @@ export function useI18n(locale: LocaleType | Locale): void {
   }
 }
 
-export function addI18n(locale: Locale | Locale[]): void {
+export function addLocale(locale: Locale | Locale[]): void {
   const locales = Array.isArray(locale) ? locale : [locale]
   locales.forEach(item => {
     localeMap[item.type] = item
@@ -33,9 +35,9 @@ export function addI18n(locale: Locale | Locale[]): void {
  *
  * @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]> {
+export function getLocale<T extends LocaleKey>(key: T): ComputedRef<Locale[T]>
+export function getLocale(): ComputedRef<Locale>
+export function getLocale<T extends LocaleKey>(key?: T): ComputedRef<Locale | Locale[T]> {
   return computed(() => {
     let currLocale = localeMap[currentType.value]
     /* istanbul ignore next */


Test patch:
diff --git a/packages/components/i18n/__tests__/useI18n.spec.ts b/packages/components/i18n/__tests__/useI18n.spec.ts
index 815fc741..0fa9b34b 100644
--- a/packages/components/i18n/__tests__/useI18n.spec.ts
+++ b/packages/components/i18n/__tests__/useI18n.spec.ts
@@ -1,55 +1,58 @@
 /* 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'
+import zh_CN from '../locales/zh-CN'
+import en_US from '../locales/en-US'
+import { addLocale, getLocale, useLocale } from '../useI18n'
 
 const Comp = {
-  template: `<div>{{globalI18n.placeholder}}</div>`,
+  template: `<div>{{globalLocale.placeholder}}</div>`,
   setup() {
-    const globalI18n = getI18n('global')
-    return { globalI18n }
+    const globalLocale = getLocale('global')
+    return { globalLocale }
   },
 }
 
 describe('useI18n.ts', () => {
-  test('default zh_CN work', async () => {
+  test('default zh-CN work', async () => {
     const wrapper = mount(Comp)
     expect(wrapper.text()).toEqual(zh_CN.global.placeholder)
   })
 
-  test('addI18n work', async () => {
+  test('addLocale work', async () => {
     const wrapper = mount(Comp)
-    addI18n(es_ES)
-    useI18n('es_ES')
-    await flushPromises()
 
-    expect(wrapper.text()).toEqual(es_ES.global.placeholder)
+    const warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {})
+    useLocale('en-US')
+    expect(warnSpy).toBeCalledTimes(1)
 
-    addI18n([en_US, zh_CN])
-    useI18n('en_US')
+    addLocale(en_US)
+    useLocale('en-US')
     await flushPromises()
     expect(wrapper.text()).toEqual(en_US.global.placeholder)
+
+    addLocale([en_US, zh_CN])
+    useLocale('zh-CN')
+    await flushPromises()
+    expect(wrapper.text()).toEqual(zh_CN.global.placeholder)
   })
 
-  test('useI18n work', async () => {
+  test('useLocale work', async () => {
     const wrapper = mount(Comp)
-    useI18n(es_ES)
-    await flushPromises()
 
-    expect(wrapper.text()).toEqual(es_ES.global.placeholder)
+    useLocale(en_US)
+    await flushPromises()
+    expect(wrapper.text()).toEqual(en_US.global.placeholder)
 
-    useI18n('zh-CN')
+    useLocale('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()
+  test('getLocale work', async () => {
+    const i18n = getLocale()
 
-    expect(i18n.value).toEqual(zh_CN)
+    useLocale(en_US)
+    await flushPromises()
+    expect(i18n.value).toEqual(en_US)
   })
 })