11import { SFCDescriptor , SFCBlock } from 'vue-template-compiler'
2- import { Locale , LocaleMessages , SFCFileInfo } from '../types'
2+ import { Locale , MetaLocaleMessage , SFCI18nBlock , SFCFileInfo } from '../types'
33
4- import { reflectSFCDescriptor , parseContent , stringfyContent } from './utils'
4+ import { escape , reflectSFCDescriptor , parseContent , stringfyContent } from './utils'
55import prettier from 'prettier'
66
77import { debug as Debug } from 'debug'
88const debug = Debug ( 'vue-i18n-locale-message:infuser' )
99
10- export default function infuse ( basePath : string , sources : SFCFileInfo [ ] , messages : LocaleMessages ) : SFCFileInfo [ ] {
10+ export default function infuse ( basePath : string , sources : SFCFileInfo [ ] , meta : MetaLocaleMessage ) : SFCFileInfo [ ] {
1111 const descriptors = reflectSFCDescriptor ( basePath , sources )
12- const locales = Object . keys ( messages )
1312
1413 return descriptors . map ( descriptor => {
1514 return {
16- content : generate ( locales , messages , descriptor ) ,
15+ content : generate ( meta , descriptor ) ,
1716 path : descriptor . contentPath
1817 } as SFCFileInfo
1918 } )
2019}
2120
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 )
2524
2625 const blocks : SFCBlock [ ] = getBlocks ( descriptor )
2726 blocks . forEach ( b => debug ( `block: type=${ b . type } , start=${ b . start } , end=${ b . end } ` ) )
2827
2928 const { raw } = descriptor
30- const content = buildContent ( target , raw , blocks )
29+ const content = buildContent ( i18nBlocks , raw , blocks )
3130 debug ( `build content:\n${ content } ` )
3231 debug ( `content size: raw=${ raw . length } , content=${ content . length } ` )
3332
3433 return format ( content , 'vue' )
3534}
3635
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-
6636function getBlocks ( descriptor : SFCDescriptor ) : SFCBlock [ ] {
6737 const { template, script, styles, customBlocks } = descriptor
6838 const blocks : SFCBlock [ ] = [ ...styles , ...customBlocks ]
@@ -72,36 +42,36 @@ function getBlocks (descriptor: SFCDescriptor): SFCBlock[] {
7242 return blocks
7343}
7444
75- function buildContent ( target : LocaleMessages , raw : string , blocks : SFCBlock [ ] ) : string {
45+ function buildContent ( i18nBlocks : SFCI18nBlock [ ] , raw : string , blocks : SFCBlock [ ] ) : string {
7646 let offset = 0
47+ let i18nBlockCounter = 0
7748 let contents : string [ ] = [ ]
78- let targetLocales = Object . keys ( target ) as Locale [ ]
7949
8050 contents = blocks . reduce ( ( contents , block ) => {
8151 if ( block . type === 'i18n' ) {
8252 let lang = block . attrs . lang
8353 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 } ` )
8457
8558 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+ }
9665 } 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 )
9968 }
10069
10170 contents = contents . concat ( raw . slice ( offset , block . start ) )
10271 const serialized = `\n${ format ( stringfyContent ( messages , lang ) , lang ) } `
10372 contents = contents . concat ( serialized )
10473 offset = block . end as number
74+ i18nBlockCounter ++
10575 } else {
10676 contents = contents . concat ( raw . slice ( offset , block . end ) )
10777 offset = block . end as number
@@ -110,18 +80,32 @@ function buildContent (target: LocaleMessages, raw: string, blocks: SFCBlock[]):
11080 } , contents )
11181 contents = contents . concat ( raw . slice ( offset , raw . length ) )
11282
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 ) )
11886 return contents
11987 } , contents )
12088 }
12189
12290 return contents . join ( '' )
12391}
12492
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+
125109function format ( source : string , lang : string ) : string {
126110 debug ( `format: lang=${ lang } , source=${ source } ` )
127111
0 commit comments