From 5228b0a614319e896a816f66eab216ce52d9abd9 Mon Sep 17 00:00:00 2001 From: kazuya kawaguchi Date: Mon, 21 Dec 2020 15:10:23 +0900 Subject: [PATCH] breaking: change sfc custom block interface (#246) * breaking: change sfc custom block interface * fix lint errors --- packages/vue-i18n/src/composer.ts | 60 ++------- packages/vue-i18n/src/index.ts | 1 + packages/vue-i18n/test/composer.test.ts | 163 +++++++++--------------- packages/vue-i18n/test/i18n.test.ts | 20 ++- packages/vue-i18n/test/mixin.test.ts | 7 +- 5 files changed, 93 insertions(+), 158 deletions(-) diff --git a/packages/vue-i18n/src/composer.ts b/packages/vue-i18n/src/composer.ts index 78215bfe5..417c384da 100644 --- a/packages/vue-i18n/src/composer.ts +++ b/packages/vue-i18n/src/composer.ts @@ -26,7 +26,6 @@ import { isObject } from '@intlify/shared' import { - parse as parsePath, resolveValue, createCoreContext, MISSING_RESOLVE_VALUE, @@ -108,9 +107,12 @@ export type PreCompileHandler = () => { functions: MessageFunctions } -export type CustomBlocks = - | Array> - | PreCompileHandler +export interface CustomBlock { + locale: Locale + resource: LocaleMessages | LocaleMessageDictionary +} + +export type CustomBlocks = Array> /** * Composer Options @@ -950,15 +952,14 @@ export function getLocaleMessages( // merge locale messages of i18n custom block if (isArray(__i18n)) { - __i18n.forEach(raw => { - deepCopy(isString(raw) ? JSON.parse(raw) : raw, ret) + __i18n.forEach(({ locale, resource }) => { + if (locale) { + ret[locale] = ret[locale] || {} + deepCopy(resource, ret[locale]) + } else { + deepCopy(resource, ret) + } }) - return ret - } - - if (isFunction(__i18n)) { - const { functions } = __i18n() - addPreCompileMessages(ret, functions as MessageFunctions) } return ret @@ -985,41 +986,6 @@ function deepCopy(source: any, destination: any): void { } } -export function addPreCompileMessages( - messages: LocaleMessages, - functions: MessageFunctions -): void { - const keys = Object.keys(functions) - keys.forEach(key => { - const compiled = functions[key] - const { l, k } = JSON.parse(key) - if (!messages[l]) { - messages[l] = {} - } - const targetLocaleMessage = messages[l] - const paths = parsePath(k) - if (paths != null) { - const len = paths.length - let last = targetLocaleMessage as any // eslint-disable-line @typescript-eslint/no-explicit-any - let i = 0 - while (i < len) { - const path = paths[i] - if (i === len - 1) { - last[path] = compiled - break - } else { - let val = last[path] - if (!val) { - last[path] = val = {} - } - last = val - i++ - } - } - } - }) -} - /** * Create composer interface factory * diff --git a/packages/vue-i18n/src/index.ts b/packages/vue-i18n/src/index.ts index c6cec1035..c80350d34 100644 --- a/packages/vue-i18n/src/index.ts +++ b/packages/vue-i18n/src/index.ts @@ -21,6 +21,7 @@ export { MissingHandler, ComposerOptions, Composer, + CustomBlock, CustomBlocks } from './composer' export { diff --git a/packages/vue-i18n/test/composer.test.ts b/packages/vue-i18n/test/composer.test.ts index 043788e89..b4a1cda33 100644 --- a/packages/vue-i18n/test/composer.test.ts +++ b/packages/vue-i18n/test/composer.test.ts @@ -10,14 +10,12 @@ import { isString, warn } from '@intlify/shared' import { createComposer, MissingHandler, - addPreCompileMessages, ComposerOptions, VueMessageType, TransrateVNodeSymbol, NumberPartsSymbol, DatetimePartsSymbol } from '../src/composer' -import { generateFormatCacheKey } from '@intlify/shared' import { watch, watchEffect, nextTick, Text, createVNode } from 'vue' import { Locale, @@ -960,122 +958,97 @@ describe('getNumberFormat / setNumberFormat / mergeNumberFormat', () => { }) describe('__i18n', () => { - test('default value', () => { - const options = { - __i18n: [ - JSON.stringify({ en: { hello: 'Hello,world!' } }), - JSON.stringify({ - ja: { - hello: 'こんにちは、世界!', - nest: { - foo: { - bar: 'ばー' - } + test('locale included locale messages', () => { + const enResource = { + locale: '', + resource: { + en: { hello: () => 'Hello,world!' } + } + } + const jaResource = { + locale: '', + resource: { + ja: { + hello: () => 'こんにちは、世界!', + nest: { + foo: { + bar: () => 'ばー' } } - }) - ] + } + } + } + const options = { + __i18n: [enResource, jaResource] } const { messages } = createComposer( options as ComposerOptions ) expect(messages.value).toEqual({ - en: { hello: 'Hello,world!' }, - ja: { - hello: 'こんにちは、世界!', - nest: { - foo: { - bar: 'ばー' - } - } - } + en: enResource.resource.en, + ja: jaResource.resource.ja }) }) - test('locale messages object', () => { - const options = { - __i18n: [ - { en: { hello: 'Hello,world!' } }, - { - ja: { - hello: 'こんにちは、世界!', - nest: { - foo: { - bar: 'ばー' - } - } - } - } - ] + test('locale not included locale messages', () => { + const enResource = { + locale: 'en', + resource: { hello: () => 'Hello,world!' } } - const { messages } = createComposer( - options as ComposerOptions - ) - expect(messages.value).toEqual({ - en: { hello: 'Hello,world!' }, - ja: { - hello: 'こんにちは、世界!', + const jaResource = { + locale: 'ja', + resource: { + hello: () => 'こんにちは、世界!', nest: { foo: { - bar: 'ばー' + bar: () => 'ばー' } } } - }) - }) - - test('merge locale messages', () => { - const msgFn = () => 'ふー' + } const options = { - __i18n: [ - JSON.stringify({ en: { hello: 'Hello,world!' } }), - JSON.stringify({ ja: { hello: 'こんにちは、世界!' } }) - ], - messages: { - en: { foo: 'foo' }, - ja: { foo: msgFn } - } + __i18n: [enResource, jaResource] } const { messages } = createComposer( options as ComposerOptions ) - expect(messages.value!.en).toEqual({ - hello: 'Hello,world!', - foo: 'foo' - }) - expect(messages.value!.ja).toEqual({ - hello: 'こんにちは、世界!', - foo: msgFn + expect(messages.value).toEqual({ + en: enResource.resource, + ja: jaResource.resource }) }) - test('function + locale messages', () => { - const functions = Object.create(null) - const msg1 = () => {} - const msg2 = () => {} - functions[generateFormatCacheKey('en', 'hello', 'hello,world')] = msg1 - functions[ - generateFormatCacheKey('ja', 'hello.hello', 'こんにちは、世界') - ] = msg2 + test('merge locale messages', () => { + const msgFnEn = () => 'foo' + const msgFnJa = () => 'ふー' + const enI18nFn = () => 'Hello,world!' + const jaI18nFn = () => 'こんにちは、世界!' const options = { - __i18n: () => ({ functions }), + __i18n: [ + { + locale: 'en', + resource: { hello: enI18nFn } + }, + { + locale: 'ja', + resource: { hello: jaI18nFn } + } + ], messages: { - en: { foo: 'foo' }, - ja: { foo: 'ふー' } + en: { foo: msgFnEn }, + ja: { foo: msgFnJa } } } const { messages } = createComposer( options as ComposerOptions ) expect(messages.value!.en).toEqual({ - hello: msg1, - foo: 'foo' + hello: enI18nFn, + foo: msgFnEn }) expect(messages.value!.ja).toEqual({ - hello: { - hello: msg2 - }, - foo: 'ふー' + hello: jaI18nFn, + foo: msgFnJa }) }) }) @@ -1208,28 +1181,6 @@ describe('__datetimeParts', () => { }) }) -test('addPreCompileMessages', () => { - const messages: any = {} - const functions = Object.create(null) - const msg1 = () => {} - const msg2 = () => {} - functions[generateFormatCacheKey('en', 'hello', 'hello,world')] = msg1 - functions[ - generateFormatCacheKey('ja', 'foo.bar.hello', 'こんにちは、世界') - ] = msg2 - addPreCompileMessages(messages, functions) - expect(messages!['en']).toMatchObject({ - hello: msg1 - }) - expect(messages!['ja']).toMatchObject({ - foo: { - bar: { - hello: msg2 - } - } - }) -}) - describe('root', () => { test('global', () => { const __root = createComposer({ diff --git a/packages/vue-i18n/test/i18n.test.ts b/packages/vue-i18n/test/i18n.test.ts index a33646882..2196b3fb1 100644 --- a/packages/vue-i18n/test/i18n.test.ts +++ b/packages/vue-i18n/test/i18n.test.ts @@ -222,8 +222,14 @@ describe('useI18n', () => { } const options = instance.type as ComponentOptions options.__i18n = [ - JSON.stringify({ en: { hello: 'Hello,world!' } }), - JSON.stringify({ ja: { hello: 'こんにちは、世界!' } }) + { + locale: '', + resource: { en: { hello: 'Hello,world!' } } + }, + { + locale: '', + resource: { ja: { hello: 'こんにちは、世界!' } } + } ] composer = useI18n() return { t: (composer as Composer).t } @@ -627,8 +633,14 @@ test('merge i18n custom blocks to global scope', async () => { } const options = instance.type as ComponentOptions options.__i18nGlobal = [ - JSON.stringify({ en: { foo: 'foo!' } }), - JSON.stringify({ ja: { foo: 'ふー!' } }) + { + locale: 'en', + resource: { foo: 'foo!' } + }, + { + locale: 'ja', + resource: { foo: 'ふー!' } + } ] useI18n({ useScope: 'global', diff --git a/packages/vue-i18n/test/mixin.test.ts b/packages/vue-i18n/test/mixin.test.ts index 96880d145..36916d2c2 100644 --- a/packages/vue-i18n/test/mixin.test.ts +++ b/packages/vue-i18n/test/mixin.test.ts @@ -55,7 +55,12 @@ describe('beforeCreate', () => { } const App = defineComponent({ template: `

{{ $t('bye') }}

`, - __i18n: [JSON.stringify(messages)] + __i18n: [ + { + locale: '', + resource: messages + } + ] }) const { html } = await mount(App, i18n)