1
1
import { SFCDescriptor , SFCBlock } from 'vue-template-compiler'
2
- import { Locale , LocaleMessages , SFCFileInfo } from '../types'
2
+ import { Locale , MetaLocaleMessage , SFCI18nBlock , SFCFileInfo } from '../types'
3
3
4
- import { reflectSFCDescriptor , parseContent , stringfyContent } from './utils'
4
+ import { escape , reflectSFCDescriptor , parseContent , stringfyContent } from './utils'
5
5
import prettier from 'prettier'
6
6
7
7
import { debug as Debug } from 'debug'
8
8
const debug = Debug ( 'vue-i18n-locale-message:infuser' )
9
9
10
- export default function infuse ( basePath : string , sources : SFCFileInfo [ ] , messages : LocaleMessages ) : SFCFileInfo [ ] {
10
+ export default function infuse ( basePath : string , sources : SFCFileInfo [ ] , meta : MetaLocaleMessage ) : SFCFileInfo [ ] {
11
11
const descriptors = reflectSFCDescriptor ( basePath , sources )
12
- const locales = Object . keys ( messages )
13
12
14
13
return descriptors . map ( descriptor => {
15
14
return {
16
- content : generate ( locales , messages , descriptor ) ,
15
+ content : generate ( meta , descriptor ) ,
17
16
path : descriptor . contentPath
18
17
} as SFCFileInfo
19
18
} )
20
19
}
21
20
22
- function generate ( locales : Locale [ ] , messages : LocaleMessages , descriptor : SFCDescriptor ) : string {
23
- const target = getTargetLocaleMessages ( locales , messages , descriptor )
24
- debug ( 'target locale messages \n' , target )
21
+ function generate ( meta : MetaLocaleMessage , descriptor : SFCDescriptor ) : string {
22
+ const i18nBlocks = meta . components [ descriptor . contentPath ]
23
+ debug ( 'target i18n blocks \n' , i18nBlocks )
25
24
26
25
const blocks : SFCBlock [ ] = getBlocks ( descriptor )
27
26
blocks . forEach ( b => debug ( `block: type=${ b . type } , start=${ b . start } , end=${ b . end } ` ) )
28
27
29
28
const { raw } = descriptor
30
- const content = buildContent ( target , raw , blocks )
29
+ const content = buildContent ( i18nBlocks , raw , blocks )
31
30
debug ( `build content:\n${ content } ` )
32
31
debug ( `content size: raw=${ raw . length } , content=${ content . length } ` )
33
32
34
33
return format ( content , 'vue' )
35
34
}
36
35
37
- function getTargetLocaleMessages ( locales : Locale [ ] , messages : LocaleMessages , descriptor : SFCDescriptor ) : LocaleMessages {
38
- return locales . reduce ( ( target , locale ) => {
39
- debug ( `processing curernt: locale=${ locale } , target=${ target } ` )
40
-
41
- const obj = messages [ locale ]
42
- if ( obj ) {
43
- let o : any = obj
44
- let prev : any = null
45
- const hierarchy = descriptor . hierarchy . concat ( )
46
- while ( hierarchy . length > 0 ) {
47
- const key = hierarchy . shift ( )
48
- debug ( 'processing hierarchy key: ' , key )
49
-
50
- if ( ! key || ! o ) { break }
51
- o = o [ key ]
52
- prev = o
53
- }
54
-
55
- if ( ! o && ! prev ) {
56
- return target
57
- } else {
58
- return Object . assign ( target , { [ locale ] : ( ( ! o && prev ) ? prev : o ) } ) as LocaleMessages
59
- }
60
- } else {
61
- return target
62
- }
63
- } , { } as LocaleMessages )
64
- }
65
-
66
36
function getBlocks ( descriptor : SFCDescriptor ) : SFCBlock [ ] {
67
37
const { template, script, styles, customBlocks } = descriptor
68
38
const blocks : SFCBlock [ ] = [ ...styles , ...customBlocks ]
@@ -72,36 +42,36 @@ function getBlocks (descriptor: SFCDescriptor): SFCBlock[] {
72
42
return blocks
73
43
}
74
44
75
- function buildContent ( target : LocaleMessages , raw : string , blocks : SFCBlock [ ] ) : string {
45
+ function buildContent ( i18nBlocks : SFCI18nBlock [ ] , raw : string , blocks : SFCBlock [ ] ) : string {
76
46
let offset = 0
47
+ let i18nBlockCounter = 0
77
48
let contents : string [ ] = [ ]
78
- let targetLocales = Object . keys ( target ) as Locale [ ]
79
49
80
50
contents = blocks . reduce ( ( contents , block ) => {
81
51
if ( block . type === 'i18n' ) {
82
52
let lang = block . attrs . lang
83
53
lang = ( ! lang || typeof lang !== 'string' ) ? 'json' : lang
54
+ const locale : Locale | undefined = block . attrs . locale
55
+ const i18nBlock = i18nBlocks [ i18nBlockCounter ]
56
+ debug ( `meta.lang = ${ i18nBlock . lang } , block.lang = ${ lang } , meta.locale = ${ i18nBlock . locale } , block.locale = ${ locale } ` )
84
57
85
58
let messages : any = null
86
- const locale = block . attrs . locale as Locale
87
- if ( ! locale || typeof locale !== 'string' ) {
88
- const obj = parseContent ( block . content , lang )
89
- const locales = Object . keys ( obj ) as Locale [ ]
90
- messages = locales . reduce ( ( messages , locale ) => {
91
- return Object . assign ( messages , { [ locale ] : target [ locale ] } )
92
- } , { } as LocaleMessages )
93
- locales . forEach ( locale => {
94
- targetLocales = targetLocales . filter ( l => l !== locale )
95
- } )
59
+ if ( lang === i18nBlock . lang && locale === i18nBlock . locale ) {
60
+ if ( locale ) {
61
+ messages = i18nBlock . messages [ locale ]
62
+ } else {
63
+ messages = i18nBlock . messages
64
+ }
96
65
} else {
97
- messages = Object . assign ( { } , target [ locale ] )
98
- targetLocales = targetLocales . filter ( l => l !== locale )
66
+ debug ( `unmatch meta block and sfc block` )
67
+ messages = parseContent ( block . content , lang )
99
68
}
100
69
101
70
contents = contents . concat ( raw . slice ( offset , block . start ) )
102
71
const serialized = `\n${ format ( stringfyContent ( messages , lang ) , lang ) } `
103
72
contents = contents . concat ( serialized )
104
73
offset = block . end as number
74
+ i18nBlockCounter ++
105
75
} else {
106
76
contents = contents . concat ( raw . slice ( offset , block . end ) )
107
77
offset = block . end as number
@@ -110,18 +80,32 @@ function buildContent (target: LocaleMessages, raw: string, blocks: SFCBlock[]):
110
80
} , contents )
111
81
contents = contents . concat ( raw . slice ( offset , raw . length ) )
112
82
113
- if ( targetLocales . length > 0 ) {
114
- contents = targetLocales . reduce ( ( contents , locale ) => {
115
- contents . push ( `\n
116
- <i18n locale="${ locale } ">
117
- ${ format ( stringfyContent ( target [ locale ] , 'json' ) , 'json' ) } </i18n>`)
83
+ if ( i18nBlocks . length > i18nBlockCounter ) {
84
+ i18nBlocks . slice ( i18nBlockCounter ) . reduce ( ( contents , i18nBlock ) => {
85
+ contents . push ( buildI18nTag ( i18nBlock ) )
118
86
return contents
119
87
} , contents )
120
88
}
121
89
122
90
return contents . join ( '' )
123
91
}
124
92
93
+ function buildI18nTag ( i18nBlock : SFCI18nBlock ) : string {
94
+ const { locale, lang, messages } = i18nBlock
95
+ let tag = '<i18n'
96
+ if ( locale ) {
97
+ tag += ` locale="${ escape ( locale ) } "`
98
+ }
99
+ if ( lang !== 'json' ) {
100
+ tag += ` lang="${ escape ( lang ) } "`
101
+ }
102
+ tag += '>'
103
+
104
+ return `\n
105
+ ${ tag }
106
+ ${ format ( stringfyContent ( locale ? messages [ locale ] : messages , lang ) , lang ) } </i18n>`
107
+ }
108
+
125
109
function format ( source : string , lang : string ) : string {
126
110
debug ( `format: lang=${ lang } , source=${ source } ` )
127
111
0 commit comments