Skip to content

Commit 9f4c47c

Browse files
committed
⭐ new(api): extract i18n locale messages from i18n custom block meta info
1 parent da18426 commit 9f4c47c

File tree

7 files changed

+164
-3
lines changed

7 files changed

+164
-3
lines changed

src/squeezer.ts

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,51 @@
11
import { LocaleMessageMeta, LocaleMessages } from '../types'
2+
import { VueTemplateCompiler } from '@vue/component-compiler-utils/dist/types'
3+
4+
import { parse } from '@vue/component-compiler-utils'
5+
import * as compiler from 'vue-template-compiler'
6+
7+
import { debug as Debug } from 'debug'
8+
const debug = Debug('vue-i18n-locale-messages:squeezer')
29

310
export default function sqeeze (meta: LocaleMessageMeta[]): LocaleMessages {
4-
return {}
11+
const messages: LocaleMessages = {}
12+
13+
meta.forEach(target => {
14+
const blockMessages = squeezeFromI18nBlock(target.content)
15+
const locales = Object.keys(blockMessages)
16+
const collects: LocaleMessages = locales.reduce((messages, locale) => {
17+
const ret = target.messageHierarchy.reduce((messages, key) => {
18+
return Object.assign({}, { [key]: messages })
19+
}, blockMessages[locale])
20+
return Object.assign(messages, { [locale]: ret })
21+
}, {})
22+
debug('collects', collects)
23+
24+
locales.forEach(locale => {
25+
messages[locale] = messages[locale] || {}
26+
messages[locale] = Object.assign(messages[locale], collects[locale])
27+
})
28+
})
29+
30+
return messages
31+
}
32+
33+
function squeezeFromI18nBlock (content: string): LocaleMessages {
34+
const desc = parse({
35+
source: content,
36+
compiler: compiler as VueTemplateCompiler
37+
})
38+
39+
return desc.customBlocks.reduce((messages, block) => {
40+
if (block.type === 'i18n') {
41+
const obj = JSON.parse(block.content)
42+
if (block.attrs.locale) {
43+
return Object.assign(messages, { [block.attrs.locale as string]: obj })
44+
} else {
45+
return Object.assign(messages, obj)
46+
}
47+
} else {
48+
return messages
49+
}
50+
}, {})
551
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`squeeze 1`] = `
4+
Object {
5+
"en": Object {
6+
"App": Object {
7+
"title": "Application",
8+
},
9+
"Modal": Object {
10+
"components": Object {
11+
"cancel": "Cancel",
12+
"ok": "OK",
13+
},
14+
},
15+
"RankingTable": Object {
16+
"nest": Object {
17+
"components": Object {
18+
"headers": Object {
19+
"name": "Name",
20+
"rank": "Rank",
21+
"score": "Score",
22+
},
23+
},
24+
},
25+
},
26+
},
27+
"ja": Object {
28+
"App": Object {
29+
"title": "アプリケーション",
30+
},
31+
"Login": Object {
32+
"pages": Object {
33+
"button": "ログイン",
34+
"confirm": "パスワードの確認入力",
35+
"id": "ユーザーID",
36+
"passowrd": "パスワード",
37+
},
38+
},
39+
"Modal": Object {
40+
"components": Object {
41+
"cancel": "キャンセル",
42+
"ok": "OK",
43+
},
44+
},
45+
},
46+
}
47+
`;

test/fixtures/meta.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
export default [{
2+
contentPath: '/path/to/project1/src/App.vue',
3+
content: `
4+
<i18n>
5+
{
6+
"en": { "title": "Application" },
7+
"ja": { "title": "アプリケーション" }
8+
}
9+
</i18n>
10+
`,
11+
component: 'App',
12+
messageHierarchy: ['App']
13+
}, {
14+
contentPath: '/path/to/project1/src/components/Modal.vue',
15+
content: `
16+
<i18n locale="en">
17+
{
18+
"ok": "OK",
19+
"cancel": "Cancel"
20+
}
21+
</i18n>
22+
<i18n locale="ja">
23+
{
24+
"ok": "OK",
25+
"cancel": "キャンセル"
26+
}
27+
</i18n>
28+
`,
29+
component: 'Modal',
30+
messageHierarchy: ['components', 'Modal']
31+
}, {
32+
contentPath: '/path/to/project1/src/components/nest/RankingTable.vue',
33+
content: `
34+
<i18n locale="en">
35+
{
36+
"headers": {
37+
"rank": "Rank",
38+
"name": "Name",
39+
"score": "Score"
40+
}
41+
}
42+
</i18n>
43+
`,
44+
component: 'RankingTable',
45+
messageHierarchy: ['components', 'nest', 'RankingTable']
46+
}, {
47+
contentPath: '/path/to/project1/src/pages/Login.vue',
48+
content: `
49+
<i18n>
50+
{
51+
"ja": {
52+
"id": "ユーザーID",
53+
"passowrd": "パスワード",
54+
"confirm": "パスワードの確認入力",
55+
"button": "ログイン"
56+
}
57+
}
58+
</i18n>
59+
`,
60+
compnent: 'Login',
61+
messageHierarchy: ['pages', 'Login']
62+
}]

test/infuser.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
12
import infuse from '../src/infuser'
23

34
test('infuse', () => {

test/reflector.tst.ts renamed to test/reflector.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
12
import getLocaleMessageMeta from '../src/reflector'
23

34
test('getLocaleMessageMeta', () => {

test/squeezer.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
import squeeze from '../src/squeezer'
2+
import metaInfo from './fixtures/meta'
3+
import { LocaleMessages, LocaleMessageMeta } from '../types'
24

35
test('squeeze', () => {
6+
const mesasges: LocaleMessages = squeeze(metaInfo as LocaleMessageMeta[])
7+
expect(mesasges).toMatchSnapshot()
48
})

types/index.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,13 @@ export type LocaleMessages = { [key: string]: LocaleMessageObject }
4848
* </i18n>
4949
* `,
5050
* component: 'Modal',
51-
* messagePath: '/components/common'
51+
* messageHierarchy: ['components', 'common', 'Modal']
5252
* }
5353
*/
5454

5555
export type LocaleMessageMeta = {
5656
contentPath: string
5757
content: string
5858
component: string
59-
messagePath: string
59+
messageHierarchy: string[]
6060
}

0 commit comments

Comments
 (0)