Comparing version 5.0.2 to 6.0.0-alpha.1
@@ -0,1 +1,54 @@ | ||
<a name="6.0.0-alpha.1"></a> | ||
# [6.0.0-alpha.1](https://github.com/kazupon/vue-i18n/compare/v5.0.2...v6.0.0-alpha.1) (2017-02-23) | ||
This is the first release of 6.0. | ||
In this version, we are some big breaking changes. | ||
- Recommended for: experiments, prototypes, upgrading small, non-critical apps | ||
- **NOT** recommended for: production use, upgrading production apps | ||
:warning: Documentation still needs to be worked on. And also, we might change some APIs and features. | ||
In the examples, please refer to this [examples](https://github.com/kazupon/vue-i18n/tree/dev/examples) directory. | ||
## Improvements | ||
- Server-Side Rendering: [example](https://github.com/kazupon/vue-i18n/tree/dev/examples/formatting/custom) | ||
- Custom formatter: [example](https://github.com/kazupon/vue-i18n/tree/dev/examples/ssr) | ||
## Features | ||
- Formatting <sup>support</sup> | ||
- Pluralization <sup>support</sup> | ||
- Locale and KeyPath Syntax <sup>support</sup> | ||
- Linked translation <sup>support</sup> | ||
- Fallback translation <sup>support</sup> | ||
- Component locale <sup>support</sup> | ||
- Dynamic locale <sup>DEPRECATED</sup> | ||
- Hot reload <sup>support</sup> | ||
## API | ||
### Global Config | ||
- Vue.config.lang <sup>DEPRECATED, use VueI18n constructor `locale` option, or VueI18n#locale</sup> | ||
- Vue.config.fallbackLang <sup>DEPRECATED, use VueI18n constructor `fallbackLocale` option, or VueI18n#fallbackLocale</sup> | ||
- Vue.config.missingHandler <sup>DEPRECATED, use VueI18n constructor `missing` option, or VueI18n#missing</sup> | ||
- Vue.config.i18nFormatter <sup>DEPRECATED, use VueI18n constructor `formatter` option, or VueI18n#formatter</sup> | ||
### Global Method | ||
- Vue.locale <sup>DEPRECATED, use VueI18n constructor `messages` option, or VueI18n#messages</sup> | ||
- Vue.t <sup>DEPRECATED, use VueI18n#t</sup> | ||
- Vue.tc <sup>DEPRECATED, use VueI18n#tc</sup> | ||
- Vue.te <sup>DEPRECATED, use VueI18n#te</sup> | ||
### Constructor Options | ||
- locales <sup>DEPRECATED, use `messages` of `i18n` option (e.g `{ i18n: { messaes: ... } }`)</sup> | ||
### Instance Properties | ||
- $lang <sup>DEPRECATED, use `locale` of Vue instance property `$i18n` (e.g `vm.$i18n.locale = 'en'`) | ||
### VueI18n class <sup>NEW</sup> | ||
- constructor options: See the [`I18nOptions` type](https://github.com/kazupon/vue-i18n/blob/dev/decls/i18n.js#L7-L15) of flowtype. | ||
- methods / properties: See the [`I18n` interface definition](https://github.com/kazupon/vue-i18n/blob/dev/decls/i18n.js#L17-L33) of flowtype. | ||
<a name="5.0.2"></a> | ||
@@ -2,0 +55,0 @@ ## [5.0.2](https://github.com/kazupon/vue-i18n/compare/v5.0.1...v5.0.2) (2017-02-18) |
/*! | ||
* vue-i18n v5.0.2 | ||
* vue-i18n v6.0.0-alpha.1 | ||
* (c) 2017 kazuya kawaguchi | ||
@@ -8,12 +8,6 @@ * Released under the MIT License. | ||
/** | ||
* warn | ||
* | ||
* @param {String} msg | ||
* @param {Error} [err] | ||
* | ||
*/ | ||
/* */ | ||
function warn (msg, err) { | ||
if (window.console) { | ||
if (typeof console !== 'undefined') { | ||
console.warn('[vue-i18n] ' + msg); | ||
@@ -26,216 +20,193 @@ if (err) { | ||
var Asset = function (Vue, langVM) { | ||
/** | ||
* Register or retrieve a global locale definition. | ||
* | ||
* @param {String} id | ||
* @param {Object | Function | Promise} definition | ||
* @param {Function} cb | ||
*/ | ||
/* */ | ||
Vue.locale = function (id, definition, cb) { | ||
if (definition === undefined) { // getter | ||
return langVM.locales[id] | ||
} else { // setter | ||
if (definition === null) { | ||
langVM.locales[id] = undefined; | ||
delete langVM.locales[id]; | ||
} else { | ||
setLocale(id, definition, function (locale) { | ||
if (locale) { | ||
langVM.$set(langVM.locales, id, locale); | ||
} else { | ||
warn('failed set `' + id + '` locale'); | ||
} | ||
cb && cb(); | ||
}); | ||
} | ||
} | ||
}; | ||
}; | ||
var mixin = { | ||
computed: { | ||
$t: function $t () { | ||
var this$1 = this; | ||
// HACK: add dependency tracking !! | ||
var locale = this.$i18n.locale; | ||
var messages = this.$i18n.messages; | ||
return function (key) { | ||
var args = [], len = arguments.length - 1; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; | ||
function setLocale (id, definition, cb) { | ||
if (typeof definition === 'object') { // sync | ||
cb(definition); | ||
} else { | ||
var future = definition.call(this); | ||
if (typeof future === 'function') { | ||
if (future.resolved) { | ||
// cached | ||
cb(future.resolved); | ||
} else if (future.requested) { | ||
// pool callbacks | ||
future.pendingCallbacks.push(cb); | ||
} else { | ||
future.requested = true; | ||
var cbs = future.pendingCallbacks = [cb]; | ||
future(function (locale) { // resolve | ||
future.resolved = locale; | ||
for (var i = 0, l = cbs.length; i < l; i++) { | ||
cbs[i](locale); | ||
} | ||
}, function () { // reject | ||
cb(); | ||
}); | ||
return (ref = this$1.$i18n)._t.apply(ref, [ key, locale, messages, this$1 ].concat( args )) | ||
var ref; | ||
} | ||
} else if (isPromise(future)) { // promise | ||
future.then(function (locale) { // resolve | ||
cb(locale); | ||
}, function () { // reject | ||
cb(); | ||
}).catch(function (err) { | ||
console.error(err); | ||
cb(); | ||
}); | ||
} | ||
} | ||
} | ||
}, | ||
/** | ||
* Forgiving check for a promise | ||
* | ||
* @param {Object} p | ||
* @return {Boolean} | ||
*/ | ||
$tc: function $tc () { | ||
var this$1 = this; | ||
function isPromise (p) { | ||
return p && typeof p.then === 'function' | ||
} | ||
// HACK: add dependency tracking !! | ||
var locale = this.$i18n.locale; | ||
var messages = this.$i18n.messages; | ||
return function (key, choice) { | ||
var args = [], len = arguments.length - 2; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 2 ]; | ||
var Override = function (Vue, langVM) { | ||
// override _init | ||
var init = Vue.prototype._init; | ||
Vue.prototype._init = function (options) { | ||
var this$1 = this; | ||
return (ref = this$1.$i18n)._tc.apply(ref, [ key, locale, messages, this$1, choice ].concat( args )) | ||
var ref; | ||
} | ||
}, | ||
init.call(this, options); | ||
$te: function $te () { | ||
var this$1 = this; | ||
if (!this.$parent) { // root | ||
this._$lang = langVM; | ||
this._langUnwatch = this._$lang.$watch('$data', function (val, old) { | ||
this$1.$forceUpdate(); | ||
}, { deep: true }); | ||
// HACK: add dependency tracking !! | ||
var locale = this.$i18n.locale; | ||
var messages = this.$i18n.messages; | ||
return function (key) { | ||
var args = [], len = arguments.length - 1; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; | ||
return (ref = this$1.$i18n)._te.apply(ref, [ key, locale, messages ].concat( args )) | ||
var ref; | ||
} | ||
} | ||
}; | ||
}, | ||
// override _destroy | ||
var destroy = Vue.prototype._destroy; | ||
Vue.prototype._destroy = function () { | ||
if (!this.$parent && this._langUnwatch) { | ||
this._langUnwatch(); | ||
this._langUnwatch = null; | ||
this._$lang = null; | ||
beforeCreate: function beforeCreate () { | ||
var options = this.$options; | ||
if (options.i18n) { | ||
if (options.i18n instanceof VueI18n) { | ||
this.$i18n = options.i18n; | ||
} else { | ||
// component local i18n | ||
if (this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n) { | ||
options.i18n.root = this.$root.$i18n; | ||
} | ||
this.$i18n = new VueI18n(options.i18n); | ||
} | ||
} else if (this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n) { | ||
// root i18n | ||
this.$i18n = this.$root.$i18n; | ||
} | ||
} | ||
}; | ||
destroy.apply(this, arguments); | ||
}; | ||
var Asset = function (Vue) { | ||
var strats = Vue.config.optionMergeStrategies; | ||
if (strats) { | ||
strats.i18n = function (parent, child) { | ||
if (!child) { return parent } | ||
if (!parent) { return child } | ||
if (!child & !parent) { | ||
// TODO: should be warn | ||
return {} | ||
} | ||
var ret = Object.create(null); | ||
Vue.extend(ret, parent); | ||
for (var key in child) { | ||
ret[key] = child[key]; | ||
} | ||
return ret | ||
}; | ||
} | ||
}; | ||
/** | ||
* Observer | ||
*/ | ||
var Vue; | ||
var Watcher; | ||
/** | ||
* getWatcher | ||
* | ||
* @param {Vue} vm | ||
* @return {Watcher} | ||
*/ | ||
function install (_Vue) { | ||
Vue = _Vue; | ||
function getWatcher (vm) { | ||
if (!Watcher) { | ||
var unwatch = vm.$watch('__watcher__', function (a) {}); | ||
Watcher = vm._watchers[0].constructor; | ||
unwatch(); | ||
var version = (Vue.version && Number(Vue.version.split('.')[0])) || -1; | ||
if (process.env.NODE_ENV !== 'production' && install.installed) { | ||
warn('already installed.'); | ||
return | ||
} | ||
return Watcher | ||
install.installed = true; | ||
if (process.env.NODE_ENV !== 'production' && version < 2) { | ||
warn(("vue-i18n (" + (install.version) + ") need to use Vue 2.0 or later (Vue: " + (Vue.version) + ").")); | ||
return | ||
} | ||
Vue.mixin(mixin); | ||
Asset(Vue); | ||
} | ||
var Dep; | ||
/* */ | ||
/** | ||
* getDep | ||
* | ||
* @param {Vue} vm | ||
* @return {Dep} | ||
* utilites | ||
*/ | ||
function getDep (vm) { | ||
if (!Dep && vm && vm._data && vm._data.__ob__ && vm._data.__ob__.dep) { | ||
Dep = vm._data.__ob__.dep.constructor; | ||
function isNil (val) { | ||
return val === null || val === undefined | ||
} | ||
function parseArgs () { | ||
var args = [], len = arguments.length; | ||
while ( len-- ) args[ len ] = arguments[ len ]; | ||
var locale = null; | ||
if (args.length === 1) { | ||
if (Vue.util.isObject(args[0]) || Array.isArray(args[0])) { | ||
args = args[0]; | ||
} else if (typeof args[0] === 'string') { | ||
locale = args[0]; | ||
} | ||
} else if (args.length === 2) { | ||
if (typeof args[0] === 'string') { | ||
locale = args[0]; | ||
} | ||
if (Vue.util.isObject(args[1]) || Array.isArray(args[1])) { | ||
args = args[1]; | ||
} | ||
} | ||
return Dep | ||
return { locale: locale, params: args } | ||
} | ||
var fallback; // fallback lang | ||
var missingHandler = null; // missing handler | ||
var i18nFormatter = null; // custom formatter | ||
function getOldChoiceIndexFixed (choice) { | ||
return choice | ||
? choice > 1 | ||
? 1 | ||
: 0 | ||
: 1 | ||
} | ||
var Config = function (Vue, langVM, lang) { | ||
var ref = Vue.util; | ||
var bind = ref.bind; | ||
var Watcher = getWatcher(langVM); | ||
var Dep = getDep(langVM); | ||
function getChoiceIndex (choice, choicesLength) { | ||
choice = Math.abs(choice); | ||
function makeComputedGetter (getter, owner) { | ||
var watcher = new Watcher(owner, getter, null, { | ||
lazy: true | ||
}); | ||
if (choicesLength === 2) { return getOldChoiceIndexFixed(choice) } | ||
return function computedGetter () { | ||
watcher.dirty && watcher.evaluate(); | ||
Dep && Dep.target && watcher.depend(); | ||
return watcher.value | ||
} | ||
} | ||
return choice ? Math.min(choice, 2) : 0 | ||
} | ||
// define Vue.config.lang configration | ||
Object.defineProperty(Vue.config, 'lang', { | ||
enumerable: true, | ||
configurable: true, | ||
get: makeComputedGetter(function () { return langVM.lang }, langVM), | ||
set: bind(function (val) { langVM.lang = val; }, langVM) | ||
}); | ||
function fetchChoice (message, choice) { | ||
if (!message && typeof message !== 'string') { return null } | ||
var choices = message.split('|'); | ||
// define Vue.config.fallbackLang configration | ||
fallback = lang; | ||
Object.defineProperty(Vue.config, 'fallbackLang', { | ||
enumerable: true, | ||
configurable: true, | ||
get: function () { return fallback }, | ||
set: function (val) { fallback = val; } | ||
}); | ||
choice = getChoiceIndex(choice, choices.length); | ||
if (!choices[choice]) { return message } | ||
return choices[choice].trim() | ||
} | ||
// define Vue.config.missingHandler configration | ||
Object.defineProperty(Vue.config, 'missingHandler', { | ||
enumerable: true, | ||
configurable: true, | ||
get: function () { return missingHandler }, | ||
set: function (val) { missingHandler = val; } | ||
}); | ||
/* */ | ||
// define Vue.config.i18Formatter configration | ||
Object.defineProperty(Vue.config, 'i18nFormatter', { | ||
enumerable: true, | ||
configurable: true, | ||
get: function () { return i18nFormatter }, | ||
set: function (val) { i18nFormatter = val; } | ||
}); | ||
var BaseFormatter = function BaseFormatter (options) { | ||
if ( options === void 0 ) options = {}; | ||
this._options = options; | ||
}; | ||
/** | ||
* utilites | ||
*/ | ||
var prototypeAccessors$1 = { options: {} }; | ||
/** | ||
* isNil | ||
* | ||
* @param {*} val | ||
* @return Boolean | ||
*/ | ||
function isNil (val) { | ||
return val === null || val === undefined | ||
} | ||
prototypeAccessors$1.options.get = function () { return this._options }; | ||
prototypeAccessors$1.options.set = function (options) { this._options = options; }; | ||
BaseFormatter.prototype.format = function format (message) { | ||
var args = [], len = arguments.length - 1; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; | ||
return template.apply(void 0, [ message ].concat( args )) | ||
}; | ||
Object.defineProperties( BaseFormatter.prototype, prototypeAccessors$1 ); | ||
/** | ||
@@ -249,49 +220,43 @@ * String format template | ||
/** | ||
* template | ||
* | ||
* @param {String} string | ||
* @param {Array} ...args | ||
* @return {String} | ||
*/ | ||
var Format = function (Vue) { | ||
var ref = Vue.util; | ||
var hasOwn = ref.hasOwn; | ||
function template (str) { | ||
var args = [], len = arguments.length - 1; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; | ||
/** | ||
* template | ||
* | ||
* @param {String} string | ||
* @param {Array} ...args | ||
* @return {String} | ||
*/ | ||
if (args.length === 1 && typeof args[0] === 'object') { | ||
args = args[0]; | ||
} else { | ||
args = {}; | ||
} | ||
function template (string) { | ||
var args = [], len = arguments.length - 1; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; | ||
if (!args || !args.hasOwnProperty) { | ||
args = {}; | ||
} | ||
if (args.length === 1 && typeof args[0] === 'object') { | ||
args = args[0]; | ||
return str.replace(RE_NARGS, function (match, prefix, i, index) { | ||
var result; | ||
if (str[index - 1] === '{' && | ||
str[index + match.length] === '}') { | ||
return i | ||
} else { | ||
args = {}; | ||
} | ||
result = Vue.util.hasOwn(args, i) ? args[i] : match; | ||
if (isNil(result)) { | ||
return '' | ||
} | ||
if (!args || !args.hasOwnProperty) { | ||
args = {}; | ||
return result | ||
} | ||
}) | ||
} | ||
return string.replace(RE_NARGS, function (match, prefix, i, index) { | ||
var result; | ||
/* */ | ||
if (string[index - 1] === '{' && | ||
string[index + match.length] === '}') { | ||
return i | ||
} else { | ||
result = hasOwn(args, i) ? args[i] : match; | ||
if (isNil(result)) { | ||
return '' | ||
} | ||
return result | ||
} | ||
}) | ||
} | ||
return template | ||
}; | ||
/** | ||
@@ -379,5 +344,2 @@ * Path paerser | ||
* Check if an expression is a literal value. | ||
* | ||
* @param {String} exp | ||
* @return {Boolean} | ||
*/ | ||
@@ -392,5 +354,2 @@ | ||
* Strip quotes from a string | ||
* | ||
* @param {String} str | ||
* @return {String | false} | ||
*/ | ||
@@ -408,9 +367,6 @@ | ||
* Determine the type of a character in a keypath. | ||
* | ||
* @param {Char} ch | ||
* @return {String} type | ||
*/ | ||
function getPathCharType (ch) { | ||
if (ch === undefined) { return 'eof' } | ||
if (ch === undefined || ch === null) { return 'eof' } | ||
@@ -459,5 +415,2 @@ var code = ch.charCodeAt(0); | ||
* dynamic indicator (*). | ||
* | ||
* @param {String} path | ||
* @return {String} | ||
*/ | ||
@@ -475,5 +428,2 @@ | ||
* Parse a string path into an array of segments | ||
* | ||
* @param {String} path | ||
* @return {Array|undefined} | ||
*/ | ||
@@ -486,4 +436,9 @@ | ||
var subPathDepth = 0; | ||
var c, newChar, key, type, transition, action, typeMap; | ||
var c; | ||
var key; | ||
var newChar; | ||
var type; | ||
var transition; | ||
var action; | ||
var typeMap; | ||
var actions = []; | ||
@@ -538,3 +493,3 @@ | ||
while (mode != null) { | ||
while (mode !== null) { | ||
index++; | ||
@@ -568,3 +523,2 @@ c = path[index]; | ||
if (mode === AFTER_PATH) { | ||
keys.raw = path; | ||
return keys | ||
@@ -577,5 +531,2 @@ } | ||
* External parse that check for a cache hit first | ||
* | ||
* @param {String} path | ||
* @return {Array|undefined} | ||
*/ | ||
@@ -591,5 +542,9 @@ | ||
} | ||
return hit | ||
return hit || [] | ||
} | ||
var Path = function (Vue) { | ||
@@ -619,358 +574,236 @@ var ref = Vue.util; | ||
/** | ||
* Get value from path string | ||
* | ||
* @param {Object} obj | ||
* @param {String} path | ||
* @return value | ||
* Get path value from path string | ||
*/ | ||
function getValue (obj, path) { | ||
function getPathValue (obj, path) { | ||
if (!isObject(obj)) { return null } | ||
var paths = parsePath(path); | ||
if (empty(paths)) { return null } | ||
if (empty(paths)) { | ||
return null | ||
} else { | ||
var length = paths.length; | ||
var ret = null; | ||
var last = obj; | ||
var i = 0; | ||
while (i < length) { | ||
var value = last[paths[i]]; | ||
if (value === undefined) { | ||
last = null; | ||
break | ||
} | ||
last = value; | ||
i++; | ||
} | ||
var length = paths.length; | ||
var ret = null; | ||
var last = obj; | ||
var i = 0; | ||
while (i < length) { | ||
var value = last[paths[i]]; | ||
if (value === undefined) { | ||
last = null; | ||
break | ||
} | ||
last = value; | ||
i++; | ||
ret = last; | ||
return ret | ||
} | ||
ret = last; | ||
return ret | ||
} | ||
return getValue | ||
return getPathValue | ||
}; | ||
/** | ||
* extend | ||
* | ||
* @param {Vue} Vue | ||
* @return {Vue} | ||
*/ | ||
/* */ | ||
var Extend = function (Vue) { | ||
var ref = Vue.util; | ||
var isObject = ref.isObject; | ||
var bind = ref.bind; | ||
var format = Format(Vue); | ||
var getValue = Path(Vue); | ||
var VueI18n = function VueI18n (options) { | ||
if ( options === void 0 ) options = {}; | ||
function parseArgs () { | ||
var args = [], len = arguments.length; | ||
while ( len-- ) args[ len ] = arguments[ len ]; | ||
var locale = options.locale || 'en-US'; | ||
var messages = options.messages || {}; | ||
this._vm = null; | ||
this._fallbackLocale = options.fallbackLocale || 'en-US'; | ||
this._formatter = options.formatter || new BaseFormatter(); | ||
this._missing = options.missing; | ||
this._root = options.root || null; | ||
this._fallbackRoot = options.fallbackRoot || false; | ||
var lang = Vue.config.lang; | ||
var fallback = Vue.config.fallbackLang; | ||
var getPathValue = Path(Vue); | ||
this._getPathValue = getPathValue; | ||
this._exist = function (message, key) { | ||
if (!message || !key) { return false } | ||
return !isNil(getPathValue(message, key)) | ||
}; | ||
if (args.length === 1) { | ||
if (isObject(args[0]) || Array.isArray(args[0])) { | ||
args = args[0]; | ||
} else if (typeof args[0] === 'string') { | ||
lang = args[0]; | ||
} | ||
} else if (args.length === 2) { | ||
if (typeof args[0] === 'string') { | ||
lang = args[0]; | ||
} | ||
if (isObject(args[1]) || Array.isArray(args[1])) { | ||
args = args[1]; | ||
} | ||
} | ||
this._resetVM({ locale: locale, messages: messages }); | ||
}; | ||
return { lang: lang, fallback: fallback, params: args } | ||
} | ||
var prototypeAccessors = { messages: {},locale: {},fallbackLocale: {},missing: {},formatter: {} }; | ||
function exist (locale, key) { | ||
if (!locale || !key) { return false } | ||
return !isNil(getValue(locale, key)) | ||
} | ||
VueI18n.prototype._resetVM = function _resetVM (data) { | ||
var silent = Vue.config.silent; | ||
Vue.config.silent = true; | ||
this._vm = new Vue({ data: data }); | ||
Vue.config.silent = silent; | ||
}; | ||
function interpolate (locale, key, args) { | ||
if (!locale) { return null } | ||
prototypeAccessors.messages.get = function () { return this._vm.$data.messages }; | ||
prototypeAccessors.messages.set = function (messages) { this._vm.$set(this._vm, 'messages', messages); }; | ||
var val = getValue(locale, key); | ||
if (Array.isArray(val)) { return val } | ||
if (isNil(val)) { val = locale[key]; } | ||
if (isNil(val)) { return null } | ||
if (typeof val !== 'string') { warn("Value of key '" + key + "' is not a string!"); return null } | ||
prototypeAccessors.locale.get = function () { return this._vm.$data.locale }; | ||
prototypeAccessors.locale.set = function (locale) { this._vm.$set(this._vm, 'locale', locale); }; | ||
// Check for the existance of links within the translated string | ||
if (val.indexOf('@:') >= 0) { | ||
// Match all the links within the local | ||
// We are going to replace each of | ||
// them with its translation | ||
var matches = val.match(/(@:[\w|.]+)/g); | ||
for (var idx in matches) { | ||
var link = matches[idx]; | ||
// Remove the leading @: | ||
var linkPlaceholder = link.substr(2); | ||
// Translate the link | ||
var translatedstring = interpolate(locale, linkPlaceholder, args); | ||
// Replace the link with the translated string | ||
val = val.replace(link, translatedstring); | ||
} | ||
} | ||
prototypeAccessors.fallbackLocale.get = function () { return this._fallbackLocale }; | ||
prototypeAccessors.fallbackLocale.set = function (locale) { this._fallbackLocale = locale; }; | ||
return !args | ||
? val | ||
: Vue.config.i18nFormatter | ||
? Vue.config.i18nFormatter.apply(null, [val].concat(args)) | ||
: format(val, args) | ||
} | ||
prototypeAccessors.missing.get = function () { return this._missing }; | ||
prototypeAccessors.missing.set = function (handler) { this._missing = handler; }; | ||
function translate (getter, lang, fallback, key, params) { | ||
var res = null; | ||
res = interpolate(getter(lang), key, params); | ||
if (!isNil(res)) { return res } | ||
prototypeAccessors.formatter.get = function () { return this._formatter }; | ||
prototypeAccessors.formatter.set = function (formatter) { this._formatter = formatter; }; | ||
res = interpolate(getter(fallback), key, params); | ||
if (!isNil(res)) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
warn('Fall back to translate the keypath "' + key + '" with "' + | ||
fallback + '" language.'); | ||
} | ||
return res | ||
} else { | ||
return null | ||
VueI18n.prototype._warnDefault = function _warnDefault (locale, key, result, vm) { | ||
if (!isNil(result)) { return result } | ||
if (this.missing) { | ||
this.missing.apply(null, [locale, key, vm]); | ||
} else { | ||
if (process.env.NODE_ENV !== 'production') { | ||
warn( | ||
"Cannot translate the value of keypath '" + key + "'. " + | ||
'Use the value of keypath as default.' | ||
); | ||
} | ||
} | ||
return key | ||
}; | ||
VueI18n.prototype._isFallbackRoot = function _isFallbackRoot (val) { | ||
return !val && !isNil(this._root) && this._fallbackRoot | ||
}; | ||
function warnDefault (lang, key, vm, result) { | ||
if (!isNil(result)) { return result } | ||
if (Vue.config.missingHandler) { | ||
Vue.config.missingHandler.apply(null, [lang, key, vm]); | ||
} else { | ||
if (process.env.NODE_ENV !== 'production') { | ||
warn('Cannot translate the value of keypath "' + key + '". ' + | ||
'Use the value of keypath as default'); | ||
} | ||
} | ||
return key | ||
} | ||
VueI18n.prototype._interpolate = function _interpolate (message, key, args) { | ||
var this$1 = this; | ||
function getAssetLocale (lang) { | ||
return Vue.locale(lang) | ||
} | ||
if (!message) { return null } | ||
function getComponentLocale (lang) { | ||
return this.$options.locales[lang] | ||
var val = this._getPathValue(message, key); | ||
if (Array.isArray(val)) { return val } | ||
if (isNil(val)) { val = message[key]; } | ||
if (isNil(val)) { return null } | ||
if (typeof val !== 'string') { | ||
warn(("Value of key '" + key + "' is not a string!")); | ||
return null | ||
} | ||
function getOldChoiceIndexFixed (choice) { | ||
return choice ? choice > 1 ? 1 : 0 : 1 | ||
// Check for the existance of links within the translated string | ||
if (val.indexOf('@:') >= 0) { | ||
// Match all the links within the local | ||
// We are going to replace each of | ||
// them with its translation | ||
var matches = val.match(/(@:[\w|.]+)/g); | ||
for (var idx in matches) { | ||
var link = matches[idx]; | ||
// Remove the leading @: | ||
var linkPlaceholder = link.substr(2); | ||
// Translate the link | ||
var translatedstring = this$1._interpolate(message, linkPlaceholder, args); | ||
// Replace the link with the translated string | ||
val = val.replace(link, translatedstring); | ||
} | ||
} | ||
function getChoiceIndex (choice, choicesLength) { | ||
choice = Math.abs(choice); | ||
return !args ? val : this._format(val, args) | ||
}; | ||
if (choicesLength === 2) { return getOldChoiceIndexFixed(choice) } | ||
VueI18n.prototype._format = function _format (val) { | ||
var args = [], len = arguments.length - 1; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; | ||
return choice ? Math.min(choice, 2) : 0 | ||
} | ||
return (ref = this._formatter).format.apply(ref, [ val ].concat( args )) | ||
var ref; | ||
}; | ||
function fetchChoice (locale, choice) { | ||
if (!locale && typeof locale !== 'string') { return null } | ||
var choices = locale.split('|'); | ||
VueI18n.prototype._translate = function _translate (messages, locale, fallback, key, args) { | ||
var res = null; | ||
res = this._interpolate(messages[locale], key, args); | ||
if (!isNil(res)) { return res } | ||
choice = getChoiceIndex(choice, choices.length); | ||
if (!choices[choice]) { return locale } | ||
return choices[choice].trim() | ||
res = this._interpolate(messages[fallback], key, args); | ||
if (!isNil(res)) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
warn(("Fall back to translate the keypath '" + key + "' with '" + fallback + "' locale.")); | ||
} | ||
return res | ||
} else { | ||
return null | ||
} | ||
}; | ||
/** | ||
* Vue.t | ||
* | ||
* @param {String} key | ||
* @param {Array} ...args | ||
* @return {String} | ||
*/ | ||
VueI18n.prototype._t = function _t (key, _locale, messages, host) { | ||
var args = [], len = arguments.length - 4; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 4 ]; | ||
Vue.t = function (key) { | ||
var args = [], len = arguments.length - 1; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; | ||
if (!key) { return '' } | ||
if (!key) { return '' } | ||
var ref = parseArgs.apply(void 0, args); | ||
var lang = ref.lang; | ||
var fallback = ref.fallback; | ||
var params = ref.params; | ||
return warnDefault(lang, key, null, translate(getAssetLocale, lang, fallback, key, params)) | ||
}; | ||
var parsedArgs = parseArgs.apply(void 0, args); | ||
var locale = parsedArgs.locale || _locale; | ||
/** | ||
* Vue.tc | ||
* | ||
* @param {String} key | ||
* @param {number|undefined} choice | ||
* @param {Array} ...args | ||
* @return {String} | ||
*/ | ||
var ret = this._translate(messages, locale, this.fallbackLocale, key, parsedArgs.params); | ||
if (this._isFallbackRoot(ret)) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
warn(("Fall back to translate the keypath '" + key + "' with root locale.")); | ||
} | ||
if (!this._root) { throw Error('unexpected error') } | ||
return (ref = this._root).t.apply(ref, [ key ].concat( args )) | ||
} else { | ||
return this._warnDefault(locale, key, ret, host) | ||
} | ||
var ref; | ||
}; | ||
Vue.tc = function (key, choice) { | ||
var args = [], len = arguments.length - 2; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 2 ]; | ||
return fetchChoice(Vue.t.apply(Vue, [ key ].concat( args )), choice) | ||
}; | ||
/** | ||
* Vue.te | ||
* | ||
* @param {String} key | ||
* @param {Array} ...args | ||
* @return {Boolean} | ||
*/ | ||
Vue.te = function (key) { | ||
VueI18n.prototype.t = function t (key) { | ||
var args = [], len = arguments.length - 1; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; | ||
var ref = parseArgs.apply(void 0, args); | ||
var lang = ref.lang; | ||
return exist(getAssetLocale(lang), key) | ||
}; | ||
return (ref = this)._t.apply(ref, [ key, this.locale, this.messages, null ].concat( args )) | ||
var ref; | ||
}; | ||
/** | ||
* $t | ||
* | ||
* @param {String} key | ||
* @param {Array} ...args | ||
* @return {String} | ||
*/ | ||
VueI18n.prototype._tc = function _tc (key, _locale, messages, host, choice) { | ||
var args = [], len = arguments.length - 5; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 5 ]; | ||
Vue.prototype.$t = function (key) { | ||
var args = [], len = arguments.length - 1; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; | ||
if (!key) { return '' } | ||
if (choice !== undefined) { | ||
return fetchChoice((ref = this)._t.apply(ref, [ key, _locale, messages, host ].concat( args )), choice) | ||
} else { | ||
return (ref$1 = this)._t.apply(ref$1, [ key, _locale, messages, host ].concat( args )) | ||
} | ||
var ref; | ||
var ref$1; | ||
}; | ||
if (!key) { return '' } | ||
var ref = parseArgs.apply(void 0, args); | ||
var lang = ref.lang; | ||
var fallback = ref.fallback; | ||
var params = ref.params; | ||
var res = null; | ||
if (this.$options.locales) { | ||
res = translate( | ||
bind(getComponentLocale, this), lang, fallback, key, params | ||
); | ||
if (res) { return res } | ||
} | ||
return warnDefault(lang, key, this, translate(getAssetLocale, lang, fallback, key, params)) | ||
}; | ||
/** | ||
* $tc | ||
* | ||
* @param {String} key | ||
* @param {number|undefined} choice | ||
* @param {Array} ...args | ||
* @return {String} | ||
*/ | ||
Vue.prototype.$tc = function (key, choice) { | ||
VueI18n.prototype.tc = function tc (key, choice) { | ||
var args = [], len = arguments.length - 2; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 2 ]; | ||
if (typeof choice !== 'number' && typeof choice !== 'undefined') { | ||
return key | ||
} | ||
return fetchChoice((ref = this).$t.apply(ref, [ key ].concat( args )), choice) | ||
return (ref = this)._tc.apply(ref, [ key, this.locale, this.messages, null, choice ].concat( args )) | ||
var ref; | ||
}; | ||
}; | ||
/** | ||
* $te | ||
* | ||
* @param {String} key | ||
* @param {Array} ...args | ||
* @return {Boolean} | ||
* | ||
*/ | ||
VueI18n.prototype._te = function _te (key, _locale, messages) { | ||
var args = [], len = arguments.length - 3; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 3 ]; | ||
Vue.prototype.$te = function (key) { | ||
var locale = parseArgs.apply(void 0, args).locale || _locale; | ||
return this._exist(messages[locale], key) | ||
}; | ||
VueI18n.prototype.te = function te (key) { | ||
var args = [], len = arguments.length - 1; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; | ||
var ref = parseArgs.apply(void 0, args); | ||
var lang = ref.lang; | ||
var found = false; | ||
if (this.$options.locales) { // exist component locale | ||
found = exist(bind(getComponentLocale)(lang), key); | ||
} | ||
if (!found) { | ||
found = exist(getAssetLocale(lang), key); | ||
} | ||
return found | ||
return (ref = this)._te.apply(ref, [ key, this.locale, this.messages ].concat( args )) | ||
var ref; | ||
}; | ||
Vue.mixin({ | ||
computed: { | ||
$lang: function $lang () { | ||
return Vue.config.lang | ||
} | ||
} | ||
}); | ||
Object.defineProperties( VueI18n.prototype, prototypeAccessors ); | ||
return Vue | ||
}; | ||
VueI18n.install = install; | ||
VueI18n.version = '__VERSION__'; | ||
var langVM; // singleton | ||
/** | ||
* plugin | ||
* | ||
* @param {Object} Vue | ||
* @param {Object} opts | ||
*/ | ||
function plugin (Vue, opts) { | ||
if ( opts === void 0 ) opts = {}; | ||
var version = (Vue.version && Number(Vue.version.split('.')[0])) || -1; | ||
if (process.env.NODE_ENV !== 'production' && plugin.installed) { | ||
warn('already installed.'); | ||
return | ||
} | ||
if (process.env.NODE_ENV !== 'production' && version < 2) { | ||
warn(("vue-i18n (" + (plugin.version) + ") need to use Vue 2.0 or later (Vue: " + (Vue.version) + ").")); | ||
return | ||
} | ||
var lang = 'en'; | ||
setupLangVM(Vue, lang); | ||
Asset(Vue, langVM); | ||
Override(Vue, langVM); | ||
Config(Vue, langVM, lang); | ||
Extend(Vue); | ||
} | ||
function setupLangVM (Vue, lang) { | ||
var silent = Vue.config.silent; | ||
Vue.config.silent = true; | ||
if (!langVM) { | ||
langVM = new Vue({ data: { lang: lang, locales: {} } }); | ||
} | ||
Vue.config.silent = silent; | ||
} | ||
plugin.version = '__VERSION__'; | ||
if (typeof window !== 'undefined' && window.Vue) { | ||
window.Vue.use(plugin); | ||
window.Vue.use(VueI18n); | ||
} | ||
module.exports = plugin; | ||
module.exports = VueI18n; |
/*! | ||
* vue-i18n v5.0.2 | ||
* vue-i18n v6.0.0-alpha.1 | ||
* (c) 2017 kazuya kawaguchi | ||
@@ -12,12 +12,6 @@ * Released under the MIT License. | ||
/** | ||
* warn | ||
* | ||
* @param {String} msg | ||
* @param {Error} [err] | ||
* | ||
*/ | ||
/* */ | ||
function warn (msg, err) { | ||
if (window.console) { | ||
if (typeof console !== 'undefined') { | ||
console.warn('[vue-i18n] ' + msg); | ||
@@ -30,216 +24,193 @@ if (err) { | ||
var Asset = function (Vue, langVM) { | ||
/** | ||
* Register or retrieve a global locale definition. | ||
* | ||
* @param {String} id | ||
* @param {Object | Function | Promise} definition | ||
* @param {Function} cb | ||
*/ | ||
/* */ | ||
Vue.locale = function (id, definition, cb) { | ||
if (definition === undefined) { // getter | ||
return langVM.locales[id] | ||
} else { // setter | ||
if (definition === null) { | ||
langVM.locales[id] = undefined; | ||
delete langVM.locales[id]; | ||
} else { | ||
setLocale(id, definition, function (locale) { | ||
if (locale) { | ||
langVM.$set(langVM.locales, id, locale); | ||
} else { | ||
warn('failed set `' + id + '` locale'); | ||
} | ||
cb && cb(); | ||
}); | ||
} | ||
} | ||
}; | ||
}; | ||
var mixin = { | ||
computed: { | ||
$t: function $t () { | ||
var this$1 = this; | ||
// HACK: add dependency tracking !! | ||
var locale = this.$i18n.locale; | ||
var messages = this.$i18n.messages; | ||
return function (key) { | ||
var args = [], len = arguments.length - 1; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; | ||
function setLocale (id, definition, cb) { | ||
if (typeof definition === 'object') { // sync | ||
cb(definition); | ||
} else { | ||
var future = definition.call(this); | ||
if (typeof future === 'function') { | ||
if (future.resolved) { | ||
// cached | ||
cb(future.resolved); | ||
} else if (future.requested) { | ||
// pool callbacks | ||
future.pendingCallbacks.push(cb); | ||
} else { | ||
future.requested = true; | ||
var cbs = future.pendingCallbacks = [cb]; | ||
future(function (locale) { // resolve | ||
future.resolved = locale; | ||
for (var i = 0, l = cbs.length; i < l; i++) { | ||
cbs[i](locale); | ||
} | ||
}, function () { // reject | ||
cb(); | ||
}); | ||
return (ref = this$1.$i18n)._t.apply(ref, [ key, locale, messages, this$1 ].concat( args )) | ||
var ref; | ||
} | ||
} else if (isPromise(future)) { // promise | ||
future.then(function (locale) { // resolve | ||
cb(locale); | ||
}, function () { // reject | ||
cb(); | ||
}).catch(function (err) { | ||
console.error(err); | ||
cb(); | ||
}); | ||
} | ||
} | ||
} | ||
}, | ||
/** | ||
* Forgiving check for a promise | ||
* | ||
* @param {Object} p | ||
* @return {Boolean} | ||
*/ | ||
$tc: function $tc () { | ||
var this$1 = this; | ||
function isPromise (p) { | ||
return p && typeof p.then === 'function' | ||
} | ||
// HACK: add dependency tracking !! | ||
var locale = this.$i18n.locale; | ||
var messages = this.$i18n.messages; | ||
return function (key, choice) { | ||
var args = [], len = arguments.length - 2; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 2 ]; | ||
var Override = function (Vue, langVM) { | ||
// override _init | ||
var init = Vue.prototype._init; | ||
Vue.prototype._init = function (options) { | ||
var this$1 = this; | ||
return (ref = this$1.$i18n)._tc.apply(ref, [ key, locale, messages, this$1, choice ].concat( args )) | ||
var ref; | ||
} | ||
}, | ||
init.call(this, options); | ||
$te: function $te () { | ||
var this$1 = this; | ||
if (!this.$parent) { // root | ||
this._$lang = langVM; | ||
this._langUnwatch = this._$lang.$watch('$data', function (val, old) { | ||
this$1.$forceUpdate(); | ||
}, { deep: true }); | ||
// HACK: add dependency tracking !! | ||
var locale = this.$i18n.locale; | ||
var messages = this.$i18n.messages; | ||
return function (key) { | ||
var args = [], len = arguments.length - 1; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; | ||
return (ref = this$1.$i18n)._te.apply(ref, [ key, locale, messages ].concat( args )) | ||
var ref; | ||
} | ||
} | ||
}; | ||
}, | ||
// override _destroy | ||
var destroy = Vue.prototype._destroy; | ||
Vue.prototype._destroy = function () { | ||
if (!this.$parent && this._langUnwatch) { | ||
this._langUnwatch(); | ||
this._langUnwatch = null; | ||
this._$lang = null; | ||
beforeCreate: function beforeCreate () { | ||
var options = this.$options; | ||
if (options.i18n) { | ||
if (options.i18n instanceof VueI18n) { | ||
this.$i18n = options.i18n; | ||
} else { | ||
// component local i18n | ||
if (this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n) { | ||
options.i18n.root = this.$root.$i18n; | ||
} | ||
this.$i18n = new VueI18n(options.i18n); | ||
} | ||
} else if (this.$root && this.$root.$i18n && this.$root.$i18n instanceof VueI18n) { | ||
// root i18n | ||
this.$i18n = this.$root.$i18n; | ||
} | ||
} | ||
}; | ||
destroy.apply(this, arguments); | ||
}; | ||
var Asset = function (Vue) { | ||
var strats = Vue.config.optionMergeStrategies; | ||
if (strats) { | ||
strats.i18n = function (parent, child) { | ||
if (!child) { return parent } | ||
if (!parent) { return child } | ||
if (!child & !parent) { | ||
// TODO: should be warn | ||
return {} | ||
} | ||
var ret = Object.create(null); | ||
Vue.extend(ret, parent); | ||
for (var key in child) { | ||
ret[key] = child[key]; | ||
} | ||
return ret | ||
}; | ||
} | ||
}; | ||
/** | ||
* Observer | ||
*/ | ||
var Vue; | ||
var Watcher; | ||
/** | ||
* getWatcher | ||
* | ||
* @param {Vue} vm | ||
* @return {Watcher} | ||
*/ | ||
function install (_Vue) { | ||
Vue = _Vue; | ||
function getWatcher (vm) { | ||
if (!Watcher) { | ||
var unwatch = vm.$watch('__watcher__', function (a) {}); | ||
Watcher = vm._watchers[0].constructor; | ||
unwatch(); | ||
var version = (Vue.version && Number(Vue.version.split('.')[0])) || -1; | ||
if ("development" !== 'production' && install.installed) { | ||
warn('already installed.'); | ||
return | ||
} | ||
return Watcher | ||
install.installed = true; | ||
if ("development" !== 'production' && version < 2) { | ||
warn(("vue-i18n (" + (install.version) + ") need to use Vue 2.0 or later (Vue: " + (Vue.version) + ").")); | ||
return | ||
} | ||
Vue.mixin(mixin); | ||
Asset(Vue); | ||
} | ||
var Dep; | ||
/* */ | ||
/** | ||
* getDep | ||
* | ||
* @param {Vue} vm | ||
* @return {Dep} | ||
* utilites | ||
*/ | ||
function getDep (vm) { | ||
if (!Dep && vm && vm._data && vm._data.__ob__ && vm._data.__ob__.dep) { | ||
Dep = vm._data.__ob__.dep.constructor; | ||
function isNil (val) { | ||
return val === null || val === undefined | ||
} | ||
function parseArgs () { | ||
var args = [], len = arguments.length; | ||
while ( len-- ) args[ len ] = arguments[ len ]; | ||
var locale = null; | ||
if (args.length === 1) { | ||
if (Vue.util.isObject(args[0]) || Array.isArray(args[0])) { | ||
args = args[0]; | ||
} else if (typeof args[0] === 'string') { | ||
locale = args[0]; | ||
} | ||
} else if (args.length === 2) { | ||
if (typeof args[0] === 'string') { | ||
locale = args[0]; | ||
} | ||
if (Vue.util.isObject(args[1]) || Array.isArray(args[1])) { | ||
args = args[1]; | ||
} | ||
} | ||
return Dep | ||
return { locale: locale, params: args } | ||
} | ||
var fallback; // fallback lang | ||
var missingHandler = null; // missing handler | ||
var i18nFormatter = null; // custom formatter | ||
function getOldChoiceIndexFixed (choice) { | ||
return choice | ||
? choice > 1 | ||
? 1 | ||
: 0 | ||
: 1 | ||
} | ||
var Config = function (Vue, langVM, lang) { | ||
var ref = Vue.util; | ||
var bind = ref.bind; | ||
var Watcher = getWatcher(langVM); | ||
var Dep = getDep(langVM); | ||
function getChoiceIndex (choice, choicesLength) { | ||
choice = Math.abs(choice); | ||
function makeComputedGetter (getter, owner) { | ||
var watcher = new Watcher(owner, getter, null, { | ||
lazy: true | ||
}); | ||
if (choicesLength === 2) { return getOldChoiceIndexFixed(choice) } | ||
return function computedGetter () { | ||
watcher.dirty && watcher.evaluate(); | ||
Dep && Dep.target && watcher.depend(); | ||
return watcher.value | ||
} | ||
} | ||
return choice ? Math.min(choice, 2) : 0 | ||
} | ||
// define Vue.config.lang configration | ||
Object.defineProperty(Vue.config, 'lang', { | ||
enumerable: true, | ||
configurable: true, | ||
get: makeComputedGetter(function () { return langVM.lang }, langVM), | ||
set: bind(function (val) { langVM.lang = val; }, langVM) | ||
}); | ||
function fetchChoice (message, choice) { | ||
if (!message && typeof message !== 'string') { return null } | ||
var choices = message.split('|'); | ||
// define Vue.config.fallbackLang configration | ||
fallback = lang; | ||
Object.defineProperty(Vue.config, 'fallbackLang', { | ||
enumerable: true, | ||
configurable: true, | ||
get: function () { return fallback }, | ||
set: function (val) { fallback = val; } | ||
}); | ||
choice = getChoiceIndex(choice, choices.length); | ||
if (!choices[choice]) { return message } | ||
return choices[choice].trim() | ||
} | ||
// define Vue.config.missingHandler configration | ||
Object.defineProperty(Vue.config, 'missingHandler', { | ||
enumerable: true, | ||
configurable: true, | ||
get: function () { return missingHandler }, | ||
set: function (val) { missingHandler = val; } | ||
}); | ||
/* */ | ||
// define Vue.config.i18Formatter configration | ||
Object.defineProperty(Vue.config, 'i18nFormatter', { | ||
enumerable: true, | ||
configurable: true, | ||
get: function () { return i18nFormatter }, | ||
set: function (val) { i18nFormatter = val; } | ||
}); | ||
var BaseFormatter = function BaseFormatter (options) { | ||
if ( options === void 0 ) options = {}; | ||
this._options = options; | ||
}; | ||
/** | ||
* utilites | ||
*/ | ||
var prototypeAccessors$1 = { options: {} }; | ||
/** | ||
* isNil | ||
* | ||
* @param {*} val | ||
* @return Boolean | ||
*/ | ||
function isNil (val) { | ||
return val === null || val === undefined | ||
} | ||
prototypeAccessors$1.options.get = function () { return this._options }; | ||
prototypeAccessors$1.options.set = function (options) { this._options = options; }; | ||
BaseFormatter.prototype.format = function format (message) { | ||
var args = [], len = arguments.length - 1; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; | ||
return template.apply(void 0, [ message ].concat( args )) | ||
}; | ||
Object.defineProperties( BaseFormatter.prototype, prototypeAccessors$1 ); | ||
/** | ||
@@ -253,49 +224,43 @@ * String format template | ||
/** | ||
* template | ||
* | ||
* @param {String} string | ||
* @param {Array} ...args | ||
* @return {String} | ||
*/ | ||
var Format = function (Vue) { | ||
var ref = Vue.util; | ||
var hasOwn = ref.hasOwn; | ||
function template (str) { | ||
var args = [], len = arguments.length - 1; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; | ||
/** | ||
* template | ||
* | ||
* @param {String} string | ||
* @param {Array} ...args | ||
* @return {String} | ||
*/ | ||
if (args.length === 1 && typeof args[0] === 'object') { | ||
args = args[0]; | ||
} else { | ||
args = {}; | ||
} | ||
function template (string) { | ||
var args = [], len = arguments.length - 1; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; | ||
if (!args || !args.hasOwnProperty) { | ||
args = {}; | ||
} | ||
if (args.length === 1 && typeof args[0] === 'object') { | ||
args = args[0]; | ||
return str.replace(RE_NARGS, function (match, prefix, i, index) { | ||
var result; | ||
if (str[index - 1] === '{' && | ||
str[index + match.length] === '}') { | ||
return i | ||
} else { | ||
args = {}; | ||
} | ||
result = Vue.util.hasOwn(args, i) ? args[i] : match; | ||
if (isNil(result)) { | ||
return '' | ||
} | ||
if (!args || !args.hasOwnProperty) { | ||
args = {}; | ||
return result | ||
} | ||
}) | ||
} | ||
return string.replace(RE_NARGS, function (match, prefix, i, index) { | ||
var result; | ||
/* */ | ||
if (string[index - 1] === '{' && | ||
string[index + match.length] === '}') { | ||
return i | ||
} else { | ||
result = hasOwn(args, i) ? args[i] : match; | ||
if (isNil(result)) { | ||
return '' | ||
} | ||
return result | ||
} | ||
}) | ||
} | ||
return template | ||
}; | ||
/** | ||
@@ -383,5 +348,2 @@ * Path paerser | ||
* Check if an expression is a literal value. | ||
* | ||
* @param {String} exp | ||
* @return {Boolean} | ||
*/ | ||
@@ -396,5 +358,2 @@ | ||
* Strip quotes from a string | ||
* | ||
* @param {String} str | ||
* @return {String | false} | ||
*/ | ||
@@ -412,9 +371,6 @@ | ||
* Determine the type of a character in a keypath. | ||
* | ||
* @param {Char} ch | ||
* @return {String} type | ||
*/ | ||
function getPathCharType (ch) { | ||
if (ch === undefined) { return 'eof' } | ||
if (ch === undefined || ch === null) { return 'eof' } | ||
@@ -463,5 +419,2 @@ var code = ch.charCodeAt(0); | ||
* dynamic indicator (*). | ||
* | ||
* @param {String} path | ||
* @return {String} | ||
*/ | ||
@@ -479,5 +432,2 @@ | ||
* Parse a string path into an array of segments | ||
* | ||
* @param {String} path | ||
* @return {Array|undefined} | ||
*/ | ||
@@ -490,4 +440,9 @@ | ||
var subPathDepth = 0; | ||
var c, newChar, key, type, transition, action, typeMap; | ||
var c; | ||
var key; | ||
var newChar; | ||
var type; | ||
var transition; | ||
var action; | ||
var typeMap; | ||
var actions = []; | ||
@@ -542,3 +497,3 @@ | ||
while (mode != null) { | ||
while (mode !== null) { | ||
index++; | ||
@@ -572,3 +527,2 @@ c = path[index]; | ||
if (mode === AFTER_PATH) { | ||
keys.raw = path; | ||
return keys | ||
@@ -581,5 +535,2 @@ } | ||
* External parse that check for a cache hit first | ||
* | ||
* @param {String} path | ||
* @return {Array|undefined} | ||
*/ | ||
@@ -595,5 +546,9 @@ | ||
} | ||
return hit | ||
return hit || [] | ||
} | ||
var Path = function (Vue) { | ||
@@ -623,360 +578,238 @@ var ref = Vue.util; | ||
/** | ||
* Get value from path string | ||
* | ||
* @param {Object} obj | ||
* @param {String} path | ||
* @return value | ||
* Get path value from path string | ||
*/ | ||
function getValue (obj, path) { | ||
function getPathValue (obj, path) { | ||
if (!isObject(obj)) { return null } | ||
var paths = parsePath(path); | ||
if (empty(paths)) { return null } | ||
if (empty(paths)) { | ||
return null | ||
} else { | ||
var length = paths.length; | ||
var ret = null; | ||
var last = obj; | ||
var i = 0; | ||
while (i < length) { | ||
var value = last[paths[i]]; | ||
if (value === undefined) { | ||
last = null; | ||
break | ||
} | ||
last = value; | ||
i++; | ||
} | ||
var length = paths.length; | ||
var ret = null; | ||
var last = obj; | ||
var i = 0; | ||
while (i < length) { | ||
var value = last[paths[i]]; | ||
if (value === undefined) { | ||
last = null; | ||
break | ||
} | ||
last = value; | ||
i++; | ||
ret = last; | ||
return ret | ||
} | ||
ret = last; | ||
return ret | ||
} | ||
return getValue | ||
return getPathValue | ||
}; | ||
/** | ||
* extend | ||
* | ||
* @param {Vue} Vue | ||
* @return {Vue} | ||
*/ | ||
/* */ | ||
var Extend = function (Vue) { | ||
var ref = Vue.util; | ||
var isObject = ref.isObject; | ||
var bind = ref.bind; | ||
var format = Format(Vue); | ||
var getValue = Path(Vue); | ||
var VueI18n = function VueI18n (options) { | ||
if ( options === void 0 ) options = {}; | ||
function parseArgs () { | ||
var args = [], len = arguments.length; | ||
while ( len-- ) args[ len ] = arguments[ len ]; | ||
var locale = options.locale || 'en-US'; | ||
var messages = options.messages || {}; | ||
this._vm = null; | ||
this._fallbackLocale = options.fallbackLocale || 'en-US'; | ||
this._formatter = options.formatter || new BaseFormatter(); | ||
this._missing = options.missing; | ||
this._root = options.root || null; | ||
this._fallbackRoot = options.fallbackRoot || false; | ||
var lang = Vue.config.lang; | ||
var fallback = Vue.config.fallbackLang; | ||
var getPathValue = Path(Vue); | ||
this._getPathValue = getPathValue; | ||
this._exist = function (message, key) { | ||
if (!message || !key) { return false } | ||
return !isNil(getPathValue(message, key)) | ||
}; | ||
if (args.length === 1) { | ||
if (isObject(args[0]) || Array.isArray(args[0])) { | ||
args = args[0]; | ||
} else if (typeof args[0] === 'string') { | ||
lang = args[0]; | ||
} | ||
} else if (args.length === 2) { | ||
if (typeof args[0] === 'string') { | ||
lang = args[0]; | ||
} | ||
if (isObject(args[1]) || Array.isArray(args[1])) { | ||
args = args[1]; | ||
} | ||
} | ||
this._resetVM({ locale: locale, messages: messages }); | ||
}; | ||
return { lang: lang, fallback: fallback, params: args } | ||
} | ||
var prototypeAccessors = { messages: {},locale: {},fallbackLocale: {},missing: {},formatter: {} }; | ||
function exist (locale, key) { | ||
if (!locale || !key) { return false } | ||
return !isNil(getValue(locale, key)) | ||
} | ||
VueI18n.prototype._resetVM = function _resetVM (data) { | ||
var silent = Vue.config.silent; | ||
Vue.config.silent = true; | ||
this._vm = new Vue({ data: data }); | ||
Vue.config.silent = silent; | ||
}; | ||
function interpolate (locale, key, args) { | ||
if (!locale) { return null } | ||
prototypeAccessors.messages.get = function () { return this._vm.$data.messages }; | ||
prototypeAccessors.messages.set = function (messages) { this._vm.$set(this._vm, 'messages', messages); }; | ||
var val = getValue(locale, key); | ||
if (Array.isArray(val)) { return val } | ||
if (isNil(val)) { val = locale[key]; } | ||
if (isNil(val)) { return null } | ||
if (typeof val !== 'string') { warn("Value of key '" + key + "' is not a string!"); return null } | ||
prototypeAccessors.locale.get = function () { return this._vm.$data.locale }; | ||
prototypeAccessors.locale.set = function (locale) { this._vm.$set(this._vm, 'locale', locale); }; | ||
// Check for the existance of links within the translated string | ||
if (val.indexOf('@:') >= 0) { | ||
// Match all the links within the local | ||
// We are going to replace each of | ||
// them with its translation | ||
var matches = val.match(/(@:[\w|.]+)/g); | ||
for (var idx in matches) { | ||
var link = matches[idx]; | ||
// Remove the leading @: | ||
var linkPlaceholder = link.substr(2); | ||
// Translate the link | ||
var translatedstring = interpolate(locale, linkPlaceholder, args); | ||
// Replace the link with the translated string | ||
val = val.replace(link, translatedstring); | ||
} | ||
} | ||
prototypeAccessors.fallbackLocale.get = function () { return this._fallbackLocale }; | ||
prototypeAccessors.fallbackLocale.set = function (locale) { this._fallbackLocale = locale; }; | ||
return !args | ||
? val | ||
: Vue.config.i18nFormatter | ||
? Vue.config.i18nFormatter.apply(null, [val].concat(args)) | ||
: format(val, args) | ||
} | ||
prototypeAccessors.missing.get = function () { return this._missing }; | ||
prototypeAccessors.missing.set = function (handler) { this._missing = handler; }; | ||
function translate (getter, lang, fallback, key, params) { | ||
var res = null; | ||
res = interpolate(getter(lang), key, params); | ||
if (!isNil(res)) { return res } | ||
prototypeAccessors.formatter.get = function () { return this._formatter }; | ||
prototypeAccessors.formatter.set = function (formatter) { this._formatter = formatter; }; | ||
res = interpolate(getter(fallback), key, params); | ||
if (!isNil(res)) { | ||
{ | ||
warn('Fall back to translate the keypath "' + key + '" with "' + | ||
fallback + '" language.'); | ||
} | ||
return res | ||
} else { | ||
return null | ||
VueI18n.prototype._warnDefault = function _warnDefault (locale, key, result, vm) { | ||
if (!isNil(result)) { return result } | ||
if (this.missing) { | ||
this.missing.apply(null, [locale, key, vm]); | ||
} else { | ||
{ | ||
warn( | ||
"Cannot translate the value of keypath '" + key + "'. " + | ||
'Use the value of keypath as default.' | ||
); | ||
} | ||
} | ||
return key | ||
}; | ||
VueI18n.prototype._isFallbackRoot = function _isFallbackRoot (val) { | ||
return !val && !isNil(this._root) && this._fallbackRoot | ||
}; | ||
function warnDefault (lang, key, vm, result) { | ||
if (!isNil(result)) { return result } | ||
if (Vue.config.missingHandler) { | ||
Vue.config.missingHandler.apply(null, [lang, key, vm]); | ||
} else { | ||
{ | ||
warn('Cannot translate the value of keypath "' + key + '". ' + | ||
'Use the value of keypath as default'); | ||
} | ||
} | ||
return key | ||
} | ||
VueI18n.prototype._interpolate = function _interpolate (message, key, args) { | ||
var this$1 = this; | ||
function getAssetLocale (lang) { | ||
return Vue.locale(lang) | ||
} | ||
if (!message) { return null } | ||
function getComponentLocale (lang) { | ||
return this.$options.locales[lang] | ||
var val = this._getPathValue(message, key); | ||
if (Array.isArray(val)) { return val } | ||
if (isNil(val)) { val = message[key]; } | ||
if (isNil(val)) { return null } | ||
if (typeof val !== 'string') { | ||
warn(("Value of key '" + key + "' is not a string!")); | ||
return null | ||
} | ||
function getOldChoiceIndexFixed (choice) { | ||
return choice ? choice > 1 ? 1 : 0 : 1 | ||
// Check for the existance of links within the translated string | ||
if (val.indexOf('@:') >= 0) { | ||
// Match all the links within the local | ||
// We are going to replace each of | ||
// them with its translation | ||
var matches = val.match(/(@:[\w|.]+)/g); | ||
for (var idx in matches) { | ||
var link = matches[idx]; | ||
// Remove the leading @: | ||
var linkPlaceholder = link.substr(2); | ||
// Translate the link | ||
var translatedstring = this$1._interpolate(message, linkPlaceholder, args); | ||
// Replace the link with the translated string | ||
val = val.replace(link, translatedstring); | ||
} | ||
} | ||
function getChoiceIndex (choice, choicesLength) { | ||
choice = Math.abs(choice); | ||
return !args ? val : this._format(val, args) | ||
}; | ||
if (choicesLength === 2) { return getOldChoiceIndexFixed(choice) } | ||
VueI18n.prototype._format = function _format (val) { | ||
var args = [], len = arguments.length - 1; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; | ||
return choice ? Math.min(choice, 2) : 0 | ||
} | ||
return (ref = this._formatter).format.apply(ref, [ val ].concat( args )) | ||
var ref; | ||
}; | ||
function fetchChoice (locale, choice) { | ||
if (!locale && typeof locale !== 'string') { return null } | ||
var choices = locale.split('|'); | ||
VueI18n.prototype._translate = function _translate (messages, locale, fallback, key, args) { | ||
var res = null; | ||
res = this._interpolate(messages[locale], key, args); | ||
if (!isNil(res)) { return res } | ||
choice = getChoiceIndex(choice, choices.length); | ||
if (!choices[choice]) { return locale } | ||
return choices[choice].trim() | ||
res = this._interpolate(messages[fallback], key, args); | ||
if (!isNil(res)) { | ||
{ | ||
warn(("Fall back to translate the keypath '" + key + "' with '" + fallback + "' locale.")); | ||
} | ||
return res | ||
} else { | ||
return null | ||
} | ||
}; | ||
/** | ||
* Vue.t | ||
* | ||
* @param {String} key | ||
* @param {Array} ...args | ||
* @return {String} | ||
*/ | ||
VueI18n.prototype._t = function _t (key, _locale, messages, host) { | ||
var args = [], len = arguments.length - 4; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 4 ]; | ||
Vue.t = function (key) { | ||
var args = [], len = arguments.length - 1; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; | ||
if (!key) { return '' } | ||
if (!key) { return '' } | ||
var ref = parseArgs.apply(void 0, args); | ||
var lang = ref.lang; | ||
var fallback = ref.fallback; | ||
var params = ref.params; | ||
return warnDefault(lang, key, null, translate(getAssetLocale, lang, fallback, key, params)) | ||
}; | ||
var parsedArgs = parseArgs.apply(void 0, args); | ||
var locale = parsedArgs.locale || _locale; | ||
/** | ||
* Vue.tc | ||
* | ||
* @param {String} key | ||
* @param {number|undefined} choice | ||
* @param {Array} ...args | ||
* @return {String} | ||
*/ | ||
var ret = this._translate(messages, locale, this.fallbackLocale, key, parsedArgs.params); | ||
if (this._isFallbackRoot(ret)) { | ||
{ | ||
warn(("Fall back to translate the keypath '" + key + "' with root locale.")); | ||
} | ||
if (!this._root) { throw Error('unexpected error') } | ||
return (ref = this._root).t.apply(ref, [ key ].concat( args )) | ||
} else { | ||
return this._warnDefault(locale, key, ret, host) | ||
} | ||
var ref; | ||
}; | ||
Vue.tc = function (key, choice) { | ||
var args = [], len = arguments.length - 2; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 2 ]; | ||
return fetchChoice(Vue.t.apply(Vue, [ key ].concat( args )), choice) | ||
}; | ||
/** | ||
* Vue.te | ||
* | ||
* @param {String} key | ||
* @param {Array} ...args | ||
* @return {Boolean} | ||
*/ | ||
Vue.te = function (key) { | ||
VueI18n.prototype.t = function t (key) { | ||
var args = [], len = arguments.length - 1; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; | ||
var ref = parseArgs.apply(void 0, args); | ||
var lang = ref.lang; | ||
return exist(getAssetLocale(lang), key) | ||
}; | ||
return (ref = this)._t.apply(ref, [ key, this.locale, this.messages, null ].concat( args )) | ||
var ref; | ||
}; | ||
/** | ||
* $t | ||
* | ||
* @param {String} key | ||
* @param {Array} ...args | ||
* @return {String} | ||
*/ | ||
VueI18n.prototype._tc = function _tc (key, _locale, messages, host, choice) { | ||
var args = [], len = arguments.length - 5; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 5 ]; | ||
Vue.prototype.$t = function (key) { | ||
var args = [], len = arguments.length - 1; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; | ||
if (!key) { return '' } | ||
if (choice !== undefined) { | ||
return fetchChoice((ref = this)._t.apply(ref, [ key, _locale, messages, host ].concat( args )), choice) | ||
} else { | ||
return (ref$1 = this)._t.apply(ref$1, [ key, _locale, messages, host ].concat( args )) | ||
} | ||
var ref; | ||
var ref$1; | ||
}; | ||
if (!key) { return '' } | ||
var ref = parseArgs.apply(void 0, args); | ||
var lang = ref.lang; | ||
var fallback = ref.fallback; | ||
var params = ref.params; | ||
var res = null; | ||
if (this.$options.locales) { | ||
res = translate( | ||
bind(getComponentLocale, this), lang, fallback, key, params | ||
); | ||
if (res) { return res } | ||
} | ||
return warnDefault(lang, key, this, translate(getAssetLocale, lang, fallback, key, params)) | ||
}; | ||
/** | ||
* $tc | ||
* | ||
* @param {String} key | ||
* @param {number|undefined} choice | ||
* @param {Array} ...args | ||
* @return {String} | ||
*/ | ||
Vue.prototype.$tc = function (key, choice) { | ||
VueI18n.prototype.tc = function tc (key, choice) { | ||
var args = [], len = arguments.length - 2; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 2 ]; | ||
if (typeof choice !== 'number' && typeof choice !== 'undefined') { | ||
return key | ||
} | ||
return fetchChoice((ref = this).$t.apply(ref, [ key ].concat( args )), choice) | ||
return (ref = this)._tc.apply(ref, [ key, this.locale, this.messages, null, choice ].concat( args )) | ||
var ref; | ||
}; | ||
}; | ||
/** | ||
* $te | ||
* | ||
* @param {String} key | ||
* @param {Array} ...args | ||
* @return {Boolean} | ||
* | ||
*/ | ||
VueI18n.prototype._te = function _te (key, _locale, messages) { | ||
var args = [], len = arguments.length - 3; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 3 ]; | ||
Vue.prototype.$te = function (key) { | ||
var locale = parseArgs.apply(void 0, args).locale || _locale; | ||
return this._exist(messages[locale], key) | ||
}; | ||
VueI18n.prototype.te = function te (key) { | ||
var args = [], len = arguments.length - 1; | ||
while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; | ||
var ref = parseArgs.apply(void 0, args); | ||
var lang = ref.lang; | ||
var found = false; | ||
if (this.$options.locales) { // exist component locale | ||
found = exist(bind(getComponentLocale)(lang), key); | ||
} | ||
if (!found) { | ||
found = exist(getAssetLocale(lang), key); | ||
} | ||
return found | ||
return (ref = this)._te.apply(ref, [ key, this.locale, this.messages ].concat( args )) | ||
var ref; | ||
}; | ||
Vue.mixin({ | ||
computed: { | ||
$lang: function $lang () { | ||
return Vue.config.lang | ||
} | ||
} | ||
}); | ||
Object.defineProperties( VueI18n.prototype, prototypeAccessors ); | ||
return Vue | ||
}; | ||
VueI18n.install = install; | ||
VueI18n.version = '6.0.0-alpha.1'; | ||
var langVM; // singleton | ||
/** | ||
* plugin | ||
* | ||
* @param {Object} Vue | ||
* @param {Object} opts | ||
*/ | ||
function plugin (Vue, opts) { | ||
if ( opts === void 0 ) opts = {}; | ||
var version = (Vue.version && Number(Vue.version.split('.')[0])) || -1; | ||
if ("development" !== 'production' && plugin.installed) { | ||
warn('already installed.'); | ||
return | ||
} | ||
if ("development" !== 'production' && version < 2) { | ||
warn(("vue-i18n (" + (plugin.version) + ") need to use Vue 2.0 or later (Vue: " + (Vue.version) + ").")); | ||
return | ||
} | ||
var lang = 'en'; | ||
setupLangVM(Vue, lang); | ||
Asset(Vue, langVM); | ||
Override(Vue, langVM); | ||
Config(Vue, langVM, lang); | ||
Extend(Vue); | ||
} | ||
function setupLangVM (Vue, lang) { | ||
var silent = Vue.config.silent; | ||
Vue.config.silent = true; | ||
if (!langVM) { | ||
langVM = new Vue({ data: { lang: lang, locales: {} } }); | ||
} | ||
Vue.config.silent = silent; | ||
} | ||
plugin.version = '5.0.2'; | ||
if (typeof window !== 'undefined' && window.Vue) { | ||
window.Vue.use(plugin); | ||
window.Vue.use(VueI18n); | ||
} | ||
return plugin; | ||
return VueI18n; | ||
}))); |
/*! | ||
* vue-i18n v5.0.2 | ||
* vue-i18n v6.0.0-alpha.1 | ||
* (c) 2017 kazuya kawaguchi | ||
* Released under the MIT License. | ||
*/ | ||
!function(n,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):n.VueI18n=t()}(this,function(){"use strict";function n(n,t){window.console&&(console.warn("[vue-i18n] "+n),t&&console.warn(t.stack))}function t(n,t,r){if("object"==typeof t)r(t);else{var i=t.call(this);if("function"==typeof i)if(i.resolved)r(i.resolved);else if(i.requested)i.pendingCallbacks.push(r);else{i.requested=!0;var o=i.pendingCallbacks=[r];i(function(n){i.resolved=n;for(var t=0,e=o.length;t<e;t++)o[t](n)},function(){r()})}else e(i)&&i.then(function(n){r(n)},function(){r()}).catch(function(n){console.error(n),r()})}}function e(n){return n&&"function"==typeof n.then}function r(n){if(!g){var t=n.$watch("__watcher__",function(n){});g=n._watchers[0].constructor,t()}return g}function i(n){return!v&&n&&n._data&&n._data.__ob__&&n._data.__ob__.dep&&(v=n._data.__ob__.dep.constructor),v}function o(n){return null===n||void 0===n}function a(n){return Z.test(n)}function u(n){var t=n.charCodeAt(0),e=n.charCodeAt(n.length-1);return t!==e||34!==t&&39!==t?n:n.slice(1,-1)}function l(n){if(void 0===n)return"eof";var t=n.charCodeAt(0);switch(t){case 91:case 93:case 46:case 34:case 39:case 48:return n;case 95:case 36:case 45:return"ident";case 32:case 9:case 10:case 13:case 160:case 65279:case 8232:case 8233:return"ws"}return t>=97&&t<=122||t>=65&&t<=90?"ident":t>=49&&t<=57?"number":"else"}function c(n){var t=n.trim();return("0"!==n.charAt(0)||!isNaN(n))&&(a(t)?u(t):"*"+t)}function f(n){function t(){var t=n[d+1];if(p===N&&"'"===t||p===q&&'"'===t)return d++,r="\\"+t,v[j](),!0}var e,r,i,o,a,u,f,s=[],d=-1,p=U,g=0,v=[];for(v[k]=function(){void 0!==i&&(s.push(i),i=void 0)},v[j]=function(){void 0===i?i=r:i+=r},v[P]=function(){v[j](),g++},v[C]=function(){if(g>0)g--,p=H,v[j]();else{if(g=0,i=c(i),i===!1)return!1;v[k]()}};null!=p;)if(d++,e=n[d],"\\"!==e||!t()){if(o=l(e),f=M[p],a=f[o]||f.else||L,a===L)return;if(p=a[0],u=v[a[1]],u&&(r=a[2],r=void 0===r?e:r,u()===!1))return;if(p===z)return s.raw=n,s}}function s(n){var t=O[n];return t||(t=f(n),t&&(O[n]=t)),t}function d(n,t){void 0===t&&(t={});var e=(n.version&&Number(n.version.split(".")[0])||-1,"en");p(n,e),y(n,I),b(n,I),m(n,I,e),D(n)}function p(n,t){var e=n.config.silent;n.config.silent=!0,I||(I=new n({data:{lang:t,locales:{}}})),n.config.silent=e}var g,v,h,y=function(e,r){e.locale=function(e,i,o){return void 0===i?r.locales[e]:void(null===i?(r.locales[e]=void 0,delete r.locales[e]):t(e,i,function(t){t?r.$set(r.locales,e,t):n("failed set `"+e+"` locale"),o&&o()}))}},b=function(n,t){var e=n.prototype._init;n.prototype._init=function(n){var r=this;e.call(this,n),this.$parent||(this._$lang=t,this._langUnwatch=this._$lang.$watch("$data",function(n,t){r.$forceUpdate()},{deep:!0}))};var r=n.prototype._destroy;n.prototype._destroy=function(){!this.$parent&&this._langUnwatch&&(this._langUnwatch(),this._langUnwatch=null,this._$lang=null),r.apply(this,arguments)}},_=null,w=null,m=function(n,t,e){function o(n,t){var e=new l(t,n,null,{lazy:!0});return function(){return e.dirty&&e.evaluate(),c&&c.target&&e.depend(),e.value}}var a=n.util,u=a.bind,l=r(t),c=i(t);Object.defineProperty(n.config,"lang",{enumerable:!0,configurable:!0,get:o(function(){return t.lang},t),set:u(function(n){t.lang=n},t)}),h=e,Object.defineProperty(n.config,"fallbackLang",{enumerable:!0,configurable:!0,get:function(){return h},set:function(n){h=n}}),Object.defineProperty(n.config,"missingHandler",{enumerable:!0,configurable:!0,get:function(){return _},set:function(n){_=n}}),Object.defineProperty(n.config,"i18nFormatter",{enumerable:!0,configurable:!0,get:function(){return w},set:function(n){w=n}})},$=/(%|)\{([0-9a-zA-Z_]+)\}/g,A=function(n){function t(n){for(var t=[],e=arguments.length-1;e-- >0;)t[e]=arguments[e+1];return t=1===t.length&&"object"==typeof t[0]?t[0]:{},t&&t.hasOwnProperty||(t={}),n.replace($,function(e,i,a,u){var l;return"{"===n[u-1]&&"}"===n[u+e.length]?a:(l=r(t,a)?t[a]:e,o(l)?"":l)})}var e=n.util,r=e.hasOwn;return t},O=Object.create(null),j=0,k=1,P=2,C=3,U=0,x=1,V=2,F=3,H=4,N=5,q=6,z=7,L=8,M=[];M[U]={ws:[U],ident:[F,j],"[":[H],eof:[z]},M[x]={ws:[x],".":[V],"[":[H],eof:[z]},M[V]={ws:[V],ident:[F,j],0:[F,j],number:[F,j]},M[F]={ident:[F,j],0:[F,j],number:[F,j],ws:[x,k],".":[V,k],"[":[H,k],eof:[z,k]},M[H]={"'":[N,j],'"':[q,j],"[":[H,P],"]":[x,C],eof:L,else:[H,j]},M[N]={"'":[H,j],eof:L,else:[N,j]},M[q]={'"':[H,j],eof:L,else:[q,j]};var I,Z=/^\s?(true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/,B=function(n){function t(n){if(null===n||void 0===n)return!0;if(Array.isArray(n)){if(n.length>0)return!1;if(0===n.length)return!0}else if(o(n))for(var t in n)if(a(n,t))return!1;return!0}function e(n,e){if(!i(n))return null;var r=s(e);if(t(r))return null;for(var o=r.length,a=null,u=n,l=0;l<o;){var c=u[r[l]];if(void 0===c){u=null;break}u=c,l++}return a=u}var r=n.util,i=r.isObject,o=r.isPlainObject,a=r.hasOwn;return e},D=function(t){function e(){for(var n=[],e=arguments.length;e--;)n[e]=arguments[e];var r=t.config.lang,i=t.config.fallbackLang;return 1===n.length?g(n[0])||Array.isArray(n[0])?n=n[0]:"string"==typeof n[0]&&(r=n[0]):2===n.length&&("string"==typeof n[0]&&(r=n[0]),(g(n[1])||Array.isArray(n[1]))&&(n=n[1])),{lang:r,fallback:i,params:n}}function r(n,t){return!(!n||!t)&&!o(y(n,t))}function i(e,r,a){if(!e)return null;var u=y(e,r);if(Array.isArray(u))return u;if(o(u)&&(u=e[r]),o(u))return null;if("string"!=typeof u)return n("Value of key '"+r+"' is not a string!"),null;if(u.indexOf("@:")>=0){var l=u.match(/(@:[\w|.]+)/g);for(var c in l){var f=l[c],s=f.substr(2),d=i(e,s,a);u=u.replace(f,d)}}return a?t.config.i18nFormatter?t.config.i18nFormatter.apply(null,[u].concat(a)):h(u,a):u}function a(n,t,e,r,a){var u=null;return u=i(n(t),r,a),o(u)?(u=i(n(e),r,a),o(u)?null:u):u}function u(n,e,r,i){return o(i)?(t.config.missingHandler&&t.config.missingHandler.apply(null,[n,e,r]),e):i}function l(n){return t.locale(n)}function c(n){return this.$options.locales[n]}function f(n){return n?n>1?1:0:1}function s(n,t){return n=Math.abs(n),2===t?f(n):n?Math.min(n,2):0}function d(n,t){if(!n&&"string"!=typeof n)return null;var e=n.split("|");return t=s(t,e.length),e[t]?e[t].trim():n}var p=t.util,g=p.isObject,v=p.bind,h=A(t),y=B(t);return t.t=function(n){for(var t=[],r=arguments.length-1;r-- >0;)t[r]=arguments[r+1];if(!n)return"";var i=e.apply(void 0,t),o=i.lang,c=i.fallback,f=i.params;return u(o,n,null,a(l,o,c,n,f))},t.tc=function(n,e){for(var r=[],i=arguments.length-2;i-- >0;)r[i]=arguments[i+2];return d(t.t.apply(t,[n].concat(r)),e)},t.te=function(n){for(var t=[],i=arguments.length-1;i-- >0;)t[i]=arguments[i+1];var o=e.apply(void 0,t),a=o.lang;return r(l(a),n)},t.prototype.$t=function(n){for(var t=[],r=arguments.length-1;r-- >0;)t[r]=arguments[r+1];if(!n)return"";var i=e.apply(void 0,t),o=i.lang,f=i.fallback,s=i.params,d=null;return this.$options.locales&&(d=a(v(c,this),o,f,n,s))?d:u(o,n,this,a(l,o,f,n,s))},t.prototype.$tc=function(n,t){for(var e=[],r=arguments.length-2;r-- >0;)e[r]=arguments[r+2];return"number"!=typeof t&&"undefined"!=typeof t?n:d((i=this).$t.apply(i,[n].concat(e)),t);var i},t.prototype.$te=function(n){for(var t=[],i=arguments.length-1;i-- >0;)t[i]=arguments[i+1];var o=e.apply(void 0,t),a=o.lang,u=!1;return this.$options.locales&&(u=r(v(c)(a),n)),u||(u=r(l(a),n)),u},t.mixin({computed:{$lang:function(){return t.config.lang}}}),t};return d.version="5.0.2","undefined"!=typeof window&&window.Vue&&window.Vue.use(d),d}); | ||
!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):t.VueI18n=n()}(this,function(){"use strict";function t(t,n){"undefined"!=typeof console&&(console.warn("[vue-i18n] "+t),n&&console.warn(n.stack))}function n(t){v=t;v.version&&Number(v.version.split(".")[0])||-1;n.installed=!0,v.mixin(g),m(v)}function e(t){return null===t||void 0===t}function r(){for(var t=[],n=arguments.length;n--;)t[n]=arguments[n];var e=null;return 1===t.length?v.util.isObject(t[0])||Array.isArray(t[0])?t=t[0]:"string"==typeof t[0]&&(e=t[0]):2===t.length&&("string"==typeof t[0]&&(e=t[0]),(v.util.isObject(t[1])||Array.isArray(t[1]))&&(t=t[1])),{locale:e,params:t}}function i(t){return t?t>1?1:0:1}function o(t,n){return t=Math.abs(t),2===n?i(t):t?Math.min(t,2):0}function a(t,n){if(!t&&"string"!=typeof t)return null;var e=t.split("|");return n=o(n,e.length),e[n]?e[n].trim():t}function s(t){for(var n=[],r=arguments.length-1;r-- >0;)n[r]=arguments[r+1];return n=1===n.length&&"object"==typeof n[0]?n[0]:{},n&&n.hasOwnProperty||(n={}),t.replace(d,function(r,i,o,a){var s;return"{"===t[a-1]&&"}"===t[a+r.length]?o:(s=v.util.hasOwn(n,o)?n[o]:r,e(s)?"":s)})}function l(t){return S.test(t)}function u(t){var n=t.charCodeAt(0),e=t.charCodeAt(t.length-1);return n!==e||34!==n&&39!==n?t:t.slice(1,-1)}function c(t){if(void 0===t||null===t)return"eof";var n=t.charCodeAt(0);switch(n){case 91:case 93:case 46:case 34:case 39:case 48:return t;case 95:case 36:case 45:return"ident";case 32:case 9:case 10:case 13:case 160:case 65279:case 8232:case 8233:return"ws"}return n>=97&&n<=122||n>=65&&n<=90?"ident":n>=49&&n<=57?"number":"else"}function f(t){var n=t.trim();return("0"!==t.charAt(0)||!isNaN(t))&&(l(n)?u(n):"*"+n)}function h(t){function n(){var n=t[h+1];if(p===P&&"'"===n||p===M&&'"'===n)return h++,i="\\"+n,g[b](),!0}var e,r,i,o,a,s,l,u=[],h=-1,p=O,v=0,g=[];for(g[w]=function(){void 0!==r&&(u.push(r),r=void 0)},g[b]=function(){void 0===r?r=i:r+=i},g[k]=function(){g[b](),v++},g[A]=function(){if(v>0)v--,p=V,g[b]();else{if(v=0,r=f(r),r===!1)return!1;g[w]()}};null!==p;)if(h++,e=t[h],"\\"!==e||!n()){if(o=c(e),l=N[p],a=l[o]||l.else||C,a===C)return;if(p=a[0],s=g[a[1]],s&&(i=a[2],i=void 0===i?e:i,s()===!1))return;if(p===R)return u}}function p(t){var n=$[t];return n||(n=h(t),n&&($[t]=n)),n||[]}var v,g={computed:{$t:function(){var t=this,n=this.$i18n.locale,e=this.$i18n.messages;return function(r){for(var i=[],o=arguments.length-1;o-- >0;)i[o]=arguments[o+1];return(a=t.$i18n)._t.apply(a,[r,n,e,t].concat(i));var a}},$tc:function(){var t=this,n=this.$i18n.locale,e=this.$i18n.messages;return function(r,i){for(var o=[],a=arguments.length-2;a-- >0;)o[a]=arguments[a+2];return(s=t.$i18n)._tc.apply(s,[r,n,e,t,i].concat(o));var s}},$te:function(){var t=this,n=this.$i18n.locale,e=this.$i18n.messages;return function(r){for(var i=[],o=arguments.length-1;o-- >0;)i[o]=arguments[o+1];return(a=t.$i18n)._te.apply(a,[r,n,e].concat(i));var a}}},beforeCreate:function(){var t=this.$options;t.i18n?t.i18n instanceof F?this.$i18n=t.i18n:(this.$root&&this.$root.$i18n&&this.$root.$i18n instanceof F&&(t.i18n.root=this.$root.$i18n),this.$i18n=new F(t.i18n)):this.$root&&this.$root.$i18n&&this.$root.$i18n instanceof F&&(this.$i18n=this.$root.$i18n)}},m=function(t){var n=t.config.optionMergeStrategies;n&&(n.i18n=function(n,e){if(!e)return n;if(!n)return e;if(!e&!n)return{};var r=Object.create(null);t.extend(r,n);for(var i in e)r[i]=e[i];return r})},_=function(t){void 0===t&&(t={}),this._options=t},y={options:{}};y.options.get=function(){return this._options},y.options.set=function(t){this._options=t},_.prototype.format=function(t){for(var n=[],e=arguments.length-1;e-- >0;)n[e]=arguments[e+1];return s.apply(void 0,[t].concat(n))},Object.defineProperties(_.prototype,y);var d=/(%|)\{([0-9a-zA-Z_]+)\}/g,$=Object.create(null),b=0,w=1,k=2,A=3,O=0,j=1,x=2,L=3,V=4,P=5,M=6,R=7,C=8,N=[];N[O]={ws:[O],ident:[L,b],"[":[V],eof:[R]},N[j]={ws:[j],".":[x],"[":[V],eof:[R]},N[x]={ws:[x],ident:[L,b],0:[L,b],number:[L,b]},N[L]={ident:[L,b],0:[L,b],number:[L,b],ws:[j,w],".":[x,w],"[":[V,w],eof:[R,w]},N[V]={"'":[P,b],'"':[M,b],"[":[V,k],"]":[j,A],eof:C,else:[V,b]},N[P]={"'":[V,b],eof:C,else:[P,b]},N[M]={'"':[V,b],eof:C,else:[M,b]};var S=/^\s?(true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/,D=function(t){function n(t){if(null===t||void 0===t)return!0;if(Array.isArray(t)){if(t.length>0)return!1;if(0===t.length)return!0}else if(o(t))for(var n in t)if(a(t,n))return!1;return!0}function e(t,e){if(!i(t))return null;var r=p(e);if(n(r))return null;for(var o=r.length,a=null,s=t,l=0;l<o;){var u=s[r[l]];if(void 0===u){s=null;break}s=u,l++}return a=s}var r=t.util,i=r.isObject,o=r.isPlainObject,a=r.hasOwn;return e},F=function(t){void 0===t&&(t={});var n=t.locale||"en-US",r=t.messages||{};this._vm=null,this._fallbackLocale=t.fallbackLocale||"en-US",this._formatter=t.formatter||new _,this._missing=t.missing,this._root=t.root||null,this._fallbackRoot=t.fallbackRoot||!1;var i=D(v);this._getPathValue=i,this._exist=function(t,n){return!(!t||!n)&&!e(i(t,n))},this._resetVM({locale:n,messages:r})},U={messages:{},locale:{},fallbackLocale:{},missing:{},formatter:{}};return F.prototype._resetVM=function(t){var n=v.config.silent;v.config.silent=!0,this._vm=new v({data:t}),v.config.silent=n},U.messages.get=function(){return this._vm.$data.messages},U.messages.set=function(t){this._vm.$set(this._vm,"messages",t)},U.locale.get=function(){return this._vm.$data.locale},U.locale.set=function(t){this._vm.$set(this._vm,"locale",t)},U.fallbackLocale.get=function(){return this._fallbackLocale},U.fallbackLocale.set=function(t){this._fallbackLocale=t},U.missing.get=function(){return this._missing},U.missing.set=function(t){this._missing=t},U.formatter.get=function(){return this._formatter},U.formatter.set=function(t){this._formatter=t},F.prototype._warnDefault=function(t,n,r,i){return e(r)?(this.missing&&this.missing.apply(null,[t,n,i]),n):r},F.prototype._isFallbackRoot=function(t){return!t&&!e(this._root)&&this._fallbackRoot},F.prototype._interpolate=function(n,r,i){var o=this;if(!n)return null;var a=this._getPathValue(n,r);if(Array.isArray(a))return a;if(e(a)&&(a=n[r]),e(a))return null;if("string"!=typeof a)return t("Value of key '"+r+"' is not a string!"),null;if(a.indexOf("@:")>=0){var s=a.match(/(@:[\w|.]+)/g);for(var l in s){var u=s[l],c=u.substr(2),f=o._interpolate(n,c,i);a=a.replace(u,f)}}return i?this._format(a,i):a},F.prototype._format=function(t){for(var n=[],e=arguments.length-1;e-- >0;)n[e]=arguments[e+1];return(r=this._formatter).format.apply(r,[t].concat(n));var r},F.prototype._translate=function(t,n,r,i,o){var a=null;return a=this._interpolate(t[n],i,o),e(a)?(a=this._interpolate(t[r],i,o),e(a)?null:a):a},F.prototype._t=function(t,n,e,i){for(var o=[],a=arguments.length-4;a-- >0;)o[a]=arguments[a+4];if(!t)return"";var s=r.apply(void 0,o),l=s.locale||n,u=this._translate(e,l,this.fallbackLocale,t,s.params);if(this._isFallbackRoot(u)){if(!this._root)throw Error("unexpected error");return(c=this._root).t.apply(c,[t].concat(o))}return this._warnDefault(l,t,u,i);var c},F.prototype.t=function(t){for(var n=[],e=arguments.length-1;e-- >0;)n[e]=arguments[e+1];return(r=this)._t.apply(r,[t,this.locale,this.messages,null].concat(n));var r},F.prototype._tc=function(t,n,e,r,i){for(var o=[],s=arguments.length-5;s-- >0;)o[s]=arguments[s+5];return t?void 0!==i?a((l=this)._t.apply(l,[t,n,e,r].concat(o)),i):(u=this)._t.apply(u,[t,n,e,r].concat(o)):"";var l,u},F.prototype.tc=function(t,n){for(var e=[],r=arguments.length-2;r-- >0;)e[r]=arguments[r+2];return(i=this)._tc.apply(i,[t,this.locale,this.messages,null,n].concat(e));var i},F.prototype._te=function(t,n,e){for(var i=[],o=arguments.length-3;o-- >0;)i[o]=arguments[o+3];var a=r.apply(void 0,i).locale||n;return this._exist(e[a],t)},F.prototype.te=function(t){for(var n=[],e=arguments.length-1;e-- >0;)n[e]=arguments[e+1];return(r=this)._te.apply(r,[t,this.locale,this.messages].concat(n));var r},Object.defineProperties(F.prototype,U),F.install=n,F.version="6.0.0-alpha.1","undefined"!=typeof window&&window.Vue&&window.Vue.use(F),F}); |
{ | ||
"name": "vue-i18n", | ||
"description": "Internationalization plugin for Vue.js", | ||
"version": "5.0.2", | ||
"version": "6.0.0-alpha.1", | ||
"author": { | ||
@@ -60,3 +60,3 @@ "name": "kazuya kawaguchi", | ||
"uglify-js": "^2.7.5", | ||
"vue": "^2.1.10", | ||
"vue": "2.0.0", | ||
"webpack": "^2.2.0", | ||
@@ -63,0 +63,0 @@ "webpack-dev-server": "^2.2.1" |
@@ -1,80 +0,19 @@ | ||
import warn from './warn' | ||
export default function (Vue, langVM) { | ||
/** | ||
* Register or retrieve a global locale definition. | ||
* | ||
* @param {String} id | ||
* @param {Object | Function | Promise} definition | ||
* @param {Function} cb | ||
*/ | ||
Vue.locale = (id, definition, cb) => { | ||
if (definition === undefined) { // getter | ||
return langVM.locales[id] | ||
} else { // setter | ||
if (definition === null) { | ||
langVM.locales[id] = undefined | ||
delete langVM.locales[id] | ||
} else { | ||
setLocale(id, definition, locale => { | ||
if (locale) { | ||
langVM.$set(langVM.locales, id, locale) | ||
} else { | ||
warn('failed set `' + id + '` locale') | ||
} | ||
cb && cb() | ||
}) | ||
export default function (Vue) { | ||
const strats = Vue.config.optionMergeStrategies | ||
if (strats) { | ||
strats.i18n = (parent, child) => { | ||
if (!child) { return parent } | ||
if (!parent) { return child } | ||
if (!child & !parent) { | ||
// TODO: should be warn | ||
return {} | ||
} | ||
} | ||
} | ||
} | ||
function setLocale (id, definition, cb) { | ||
if (typeof definition === 'object') { // sync | ||
cb(definition) | ||
} else { | ||
const future = definition.call(this) | ||
if (typeof future === 'function') { | ||
if (future.resolved) { | ||
// cached | ||
cb(future.resolved) | ||
} else if (future.requested) { | ||
// pool callbacks | ||
future.pendingCallbacks.push(cb) | ||
} else { | ||
future.requested = true | ||
const cbs = future.pendingCallbacks = [cb] | ||
future(locale => { // resolve | ||
future.resolved = locale | ||
for (let i = 0, l = cbs.length; i < l; i++) { | ||
cbs[i](locale) | ||
} | ||
}, () => { // reject | ||
cb() | ||
}) | ||
const ret = Object.create(null) | ||
Vue.extend(ret, parent) | ||
for (const key in child) { | ||
ret[key] = child[key] | ||
} | ||
} else if (isPromise(future)) { // promise | ||
future.then(locale => { // resolve | ||
cb(locale) | ||
}, () => { // reject | ||
cb() | ||
}).catch(err => { | ||
console.error(err) | ||
cb() | ||
}) | ||
return ret | ||
} | ||
} | ||
} | ||
/** | ||
* Forgiving check for a promise | ||
* | ||
* @param {Object} p | ||
* @return {Boolean} | ||
*/ | ||
function isPromise (p) { | ||
return p && typeof p.then === 'function' | ||
} |
@@ -0,3 +1,21 @@ | ||
/* @flow */ | ||
import { isNil } from './util' | ||
import { Vue } from './install' | ||
export default class BaseFormatter { | ||
_options: FormatterOptions | ||
constructor (options: FormatterOptions = {}) { | ||
this._options = options | ||
} | ||
get options (): FormatterOptions { return this._options } | ||
set options (options: FormatterOptions): void { this._options = options } | ||
format (message: string, ...args: any): any { | ||
return template(message, ...args) | ||
} | ||
} | ||
/** | ||
@@ -9,45 +27,38 @@ * String format template | ||
const RE_NARGS = /(%|)\{([0-9a-zA-Z_]+)\}/g | ||
const RE_NARGS: RegExp = /(%|)\{([0-9a-zA-Z_]+)\}/g | ||
/** | ||
* template | ||
* | ||
* @param {String} string | ||
* @param {Array} ...args | ||
* @return {String} | ||
*/ | ||
export default function (Vue) { | ||
const { hasOwn } = Vue.util | ||
export function template (str: string, ...args: any): string { | ||
if (args.length === 1 && typeof args[0] === 'object') { | ||
args = args[0] | ||
} else { | ||
args = {} | ||
} | ||
/** | ||
* template | ||
* | ||
* @param {String} string | ||
* @param {Array} ...args | ||
* @return {String} | ||
*/ | ||
if (!args || !args.hasOwnProperty) { | ||
args = {} | ||
} | ||
function template (string, ...args) { | ||
if (args.length === 1 && typeof args[0] === 'object') { | ||
args = args[0] | ||
return str.replace(RE_NARGS, (match, prefix, i, index) => { | ||
let result: string | ||
if (str[index - 1] === '{' && | ||
str[index + match.length] === '}') { | ||
return i | ||
} else { | ||
args = {} | ||
} | ||
result = Vue.util.hasOwn(args, i) ? args[i] : match | ||
if (isNil(result)) { | ||
return '' | ||
} | ||
if (!args || !args.hasOwnProperty) { | ||
args = {} | ||
return result | ||
} | ||
return string.replace(RE_NARGS, (match, prefix, i, index) => { | ||
let result | ||
if (string[index - 1] === '{' && | ||
string[index + match.length] === '}') { | ||
return i | ||
} else { | ||
result = hasOwn(args, i) ? args[i] : match | ||
if (isNil(result)) { | ||
return '' | ||
} | ||
return result | ||
} | ||
}) | ||
} | ||
return template | ||
}) | ||
} |
204
src/index.js
@@ -0,54 +1,186 @@ | ||
/* @flow */ | ||
import { install, Vue } from './install' | ||
import { isNil, parseArgs, fetchChoice } from './util' | ||
import warn from './warn' | ||
import Asset from './asset' | ||
import Override from './override' | ||
import Config from './config' | ||
import Extend from './extend' | ||
import BaseFormatter from './format' | ||
import Path from './path' | ||
import type { PathValue } from './path' | ||
let langVM // singleton | ||
export default class VueI18n { | ||
static install: () => void | ||
static version: string | ||
_vm: any | ||
_formatter: Formatter | ||
_root: ?I18n | ||
_fallbackRoot: boolean | ||
_fallbackLocale: string | ||
_missing: ?MissingHandler | ||
_getPathValue: Function | ||
_exist: Function | ||
/** | ||
* plugin | ||
* | ||
* @param {Object} Vue | ||
* @param {Object} opts | ||
*/ | ||
constructor (options: I18nOptions = {}) { | ||
const locale: string = options.locale || 'en-US' | ||
const messages: Messages = options.messages || {} | ||
this._vm = null | ||
this._fallbackLocale = options.fallbackLocale || 'en-US' | ||
this._formatter = options.formatter || new BaseFormatter() | ||
this._missing = options.missing | ||
this._root = options.root || null | ||
this._fallbackRoot = options.fallbackRoot || false | ||
function plugin (Vue, opts = {}) { | ||
const version = (Vue.version && Number(Vue.version.split('.')[0])) || -1 | ||
const getPathValue: Function = Path(Vue) | ||
this._getPathValue = getPathValue | ||
this._exist = (message: Object, key: string): boolean => { | ||
if (!message || !key) { return false } | ||
return !isNil(getPathValue(message, key)) | ||
} | ||
if (process.env.NODE_ENV !== 'production' && plugin.installed) { | ||
warn('already installed.') | ||
return | ||
this._resetVM({ locale, messages }) | ||
} | ||
if (process.env.NODE_ENV !== 'production' && version < 2) { | ||
warn(`vue-i18n (${plugin.version}) need to use Vue 2.0 or later (Vue: ${Vue.version}).`) | ||
return | ||
_resetVM (data: { locale: string, messages: Messages }): void { | ||
const silent = Vue.config.silent | ||
Vue.config.silent = true | ||
this._vm = new Vue({ data }) | ||
Vue.config.silent = silent | ||
} | ||
const lang = 'en' | ||
setupLangVM(Vue, lang) | ||
get messages (): Messages { return this._vm.$data.messages } | ||
set messages (messages: Messages): void { this._vm.$set(this._vm, 'messages', messages) } | ||
Asset(Vue, langVM) | ||
Override(Vue, langVM) | ||
Config(Vue, langVM, lang) | ||
Extend(Vue) | ||
} | ||
get locale (): string { return this._vm.$data.locale } | ||
set locale (locale: string): void { this._vm.$set(this._vm, 'locale', locale) } | ||
function setupLangVM (Vue, lang) { | ||
const silent = Vue.config.silent | ||
Vue.config.silent = true | ||
if (!langVM) { | ||
langVM = new Vue({ data: { lang, locales: {} } }) | ||
get fallbackLocale (): string { return this._fallbackLocale } | ||
set fallbackLocale (locale: string): void { this._fallbackLocale = locale } | ||
get missing (): ?MissingHandler { return this._missing } | ||
set missing (handler: MissingHandler): void { this._missing = handler } | ||
get formatter (): Formatter { return this._formatter } | ||
set formatter (formatter: Formatter): void { this._formatter = formatter } | ||
_warnDefault (locale: string, key: string, result: ?any, vm: ?any): ?string { | ||
if (!isNil(result)) { return result } | ||
if (this.missing) { | ||
this.missing.apply(null, [locale, key, vm]) | ||
} else { | ||
if (process.env.NODE_ENV !== 'production') { | ||
warn( | ||
`Cannot translate the value of keypath '${key}'. ` + | ||
'Use the value of keypath as default.' | ||
) | ||
} | ||
} | ||
return key | ||
} | ||
Vue.config.silent = silent | ||
_isFallbackRoot (val: any): boolean { | ||
return !val && !isNil(this._root) && this._fallbackRoot | ||
} | ||
_interpolate (message: Messages, key: string, args: any): any { | ||
if (!message) { return null } | ||
let val: PathValue = this._getPathValue(message, key) | ||
if (Array.isArray(val)) { return val } | ||
if (isNil(val)) { val = message[key] } | ||
if (isNil(val)) { return null } | ||
if (typeof val !== 'string') { | ||
warn(`Value of key '${key}' is not a string!`) | ||
return null | ||
} | ||
// Check for the existance of links within the translated string | ||
if (val.indexOf('@:') >= 0) { | ||
// Match all the links within the local | ||
// We are going to replace each of | ||
// them with its translation | ||
const matches: any = val.match(/(@:[\w|.]+)/g) | ||
for (const idx in matches) { | ||
const link = matches[idx] | ||
// Remove the leading @: | ||
const linkPlaceholder = link.substr(2) | ||
// Translate the link | ||
const translatedstring = this._interpolate(message, linkPlaceholder, args) | ||
// Replace the link with the translated string | ||
val = val.replace(link, translatedstring) | ||
} | ||
} | ||
return !args ? val : this._format(val, args) | ||
} | ||
_format (val: any, ...args: any): any { | ||
return this._formatter.format(val, ...args) | ||
} | ||
_translate (messages: Messages, locale: string, fallback: string, key: string, args: any): any { | ||
let res: any = null | ||
res = this._interpolate(messages[locale], key, args) | ||
if (!isNil(res)) { return res } | ||
res = this._interpolate(messages[fallback], key, args) | ||
if (!isNil(res)) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
warn(`Fall back to translate the keypath '${key}' with '${fallback}' locale.`) | ||
} | ||
return res | ||
} else { | ||
return null | ||
} | ||
} | ||
_t (key: string, _locale: string, messages: Messages, host: any, ...args: any): any { | ||
if (!key) { return '' } | ||
const parsedArgs = parseArgs(...args) | ||
const locale = parsedArgs.locale || _locale | ||
const ret: any = this._translate(messages, locale, this.fallbackLocale, key, parsedArgs.params) | ||
if (this._isFallbackRoot(ret)) { | ||
if (process.env.NODE_ENV !== 'production') { | ||
warn(`Fall back to translate the keypath '${key}' with root locale.`) | ||
} | ||
if (!this._root) { throw Error('unexpected error') } | ||
return this._root.t(key, ...args) | ||
} else { | ||
return this._warnDefault(locale, key, ret, host) | ||
} | ||
} | ||
t (key: string, ...args: any): string { | ||
return this._t(key, this.locale, this.messages, null, ...args) | ||
} | ||
_tc (key: string, _locale: string, messages: Messages, host: any, choice?: number, ...args: any): any { | ||
if (!key) { return '' } | ||
if (choice !== undefined) { | ||
return fetchChoice(this._t(key, _locale, messages, host, ...args), choice) | ||
} else { | ||
return this._t(key, _locale, messages, host, ...args) | ||
} | ||
} | ||
tc (key: string, choice?: number, ...args: any): any { | ||
return this._tc(key, this.locale, this.messages, null, choice, ...args) | ||
} | ||
_te (key: string, _locale: string, messages: Messages, ...args: any): boolean { | ||
const locale = parseArgs(...args).locale || _locale | ||
return this._exist(messages[locale], key) | ||
} | ||
te (key: string, ...args: any): boolean { | ||
return this._te(key, this.locale, this.messages, ...args) | ||
} | ||
} | ||
plugin.version = '__VERSION__' | ||
VueI18n.install = install | ||
VueI18n.version = '__VERSION__' | ||
export default plugin | ||
if (typeof window !== 'undefined' && window.Vue) { | ||
window.Vue.use(plugin) | ||
window.Vue.use(VueI18n) | ||
} |
130
src/path.js
@@ -0,1 +1,3 @@ | ||
/* @flow */ | ||
/** | ||
@@ -27,3 +29,3 @@ * Path paerser | ||
const pathStateMachine = [] | ||
const pathStateMachine: any = [] | ||
@@ -84,9 +86,6 @@ pathStateMachine[BEFORE_PATH] = { | ||
* Check if an expression is a literal value. | ||
* | ||
* @param {String} exp | ||
* @return {Boolean} | ||
*/ | ||
const literalValueRE = /^\s?(true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/ | ||
function isLiteral (exp) { | ||
const literalValueRE: RegExp = /^\s?(true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/ | ||
function isLiteral (exp: string): boolean { | ||
return literalValueRE.test(exp) | ||
@@ -97,10 +96,7 @@ } | ||
* Strip quotes from a string | ||
* | ||
* @param {String} str | ||
* @return {String | false} | ||
*/ | ||
function stripQuotes (str) { | ||
const a = str.charCodeAt(0) | ||
const b = str.charCodeAt(str.length - 1) | ||
function stripQuotes (str: string): string | boolean { | ||
const a: number = str.charCodeAt(0) | ||
const b: number = str.charCodeAt(str.length - 1) | ||
return a === b && (a === 0x22 || a === 0x27) | ||
@@ -113,11 +109,8 @@ ? str.slice(1, -1) | ||
* Determine the type of a character in a keypath. | ||
* | ||
* @param {Char} ch | ||
* @return {String} type | ||
*/ | ||
function getPathCharType (ch) { | ||
if (ch === undefined) { return 'eof' } | ||
function getPathCharType (ch: ?string): string { | ||
if (ch === undefined || ch === null) { return 'eof' } | ||
const code = ch.charCodeAt(0) | ||
const code: number = ch.charCodeAt(0) | ||
@@ -164,9 +157,6 @@ switch (code) { | ||
* dynamic indicator (*). | ||
* | ||
* @param {String} path | ||
* @return {String} | ||
*/ | ||
function formatSubPath (path) { | ||
const trimmed = path.trim() | ||
function formatSubPath (path: string): boolean | string { | ||
const trimmed: string = path.trim() | ||
// invalid leading 0 | ||
@@ -180,16 +170,18 @@ if (path.charAt(0) === '0' && isNaN(path)) { return false } | ||
* Parse a string path into an array of segments | ||
* | ||
* @param {String} path | ||
* @return {Array|undefined} | ||
*/ | ||
function parse (path) { | ||
const keys = [] | ||
let index = -1 | ||
let mode = BEFORE_PATH | ||
let subPathDepth = 0 | ||
let c, newChar, key, type, transition, action, typeMap | ||
function parse (path): ?Array<string> { | ||
const keys: Array<string> = [] | ||
let index: number = -1 | ||
let mode: number = BEFORE_PATH | ||
let subPathDepth: number = 0 | ||
let c: ?string | ||
let key: any | ||
let newChar: any | ||
let type: string | ||
let transition: number | ||
let action: Function | ||
let typeMap: any | ||
const actions: Array<Function> = [] | ||
const actions = [] | ||
actions[PUSH] = function () { | ||
@@ -231,4 +223,4 @@ if (key !== undefined) { | ||
function maybeUnescapeQuote () { | ||
const nextChar = path[index + 1] | ||
function maybeUnescapeQuote (): ?boolean { | ||
const nextChar: string = path[index + 1] | ||
if ((mode === IN_SINGLE_QUOTE && nextChar === "'") || | ||
@@ -243,3 +235,3 @@ (mode === IN_DOUBLE_QUOTE && nextChar === '"')) { | ||
while (mode != null) { | ||
while (mode !== null) { | ||
index++ | ||
@@ -273,3 +265,2 @@ c = path[index] | ||
if (mode === AFTER_PATH) { | ||
keys.raw = path | ||
return keys | ||
@@ -282,9 +273,6 @@ } | ||
* External parse that check for a cache hit first | ||
* | ||
* @param {String} path | ||
* @return {Array|undefined} | ||
*/ | ||
function parsePath (path) { | ||
let hit = pathCache[path] | ||
function parsePath (path: string): Array<string> { | ||
let hit: ?Array<string> = pathCache[path] | ||
if (!hit) { | ||
@@ -296,9 +284,13 @@ hit = parse(path) | ||
} | ||
return hit | ||
return hit || [] | ||
} | ||
export default function (Vue) { | ||
export type PathValue = | string | number | boolean | null | PathValueObject | PathValueArray | ||
export type PathValueObject = Dictionary<PathValue> | ||
export type PathValueArray = Array<PathValue> | ||
export default function (Vue: any): Function { | ||
const { isObject, isPlainObject, hasOwn } = Vue.util | ||
function empty (target) { | ||
function empty (target: any): boolean { | ||
if (target === null || target === undefined) { return true } | ||
@@ -321,35 +313,33 @@ | ||
/** | ||
* Get value from path string | ||
* | ||
* @param {Object} obj | ||
* @param {String} path | ||
* @return value | ||
* Get path value from path string | ||
*/ | ||
function getValue (obj, path) { | ||
function getPathValue (obj: Object, path: string): PathValue { | ||
if (!isObject(obj)) { return null } | ||
const paths = parsePath(path) | ||
if (empty(paths)) { return null } | ||
const paths: Array<string> = parsePath(path) | ||
if (empty(paths)) { | ||
return null | ||
} else { | ||
const length = paths.length | ||
let ret: any = null | ||
let last: any = obj | ||
let i = 0 | ||
while (i < length) { | ||
const value: any = last[paths[i]] | ||
if (value === undefined) { | ||
last = null | ||
break | ||
} | ||
last = value | ||
i++ | ||
} | ||
const length = paths.length | ||
let ret = null | ||
let last = obj | ||
let i = 0 | ||
while (i < length) { | ||
const value = last[paths[i]] | ||
if (value === undefined) { | ||
last = null | ||
break | ||
} | ||
last = value | ||
i++ | ||
ret = last | ||
return ret | ||
} | ||
ret = last | ||
return ret | ||
} | ||
return getValue | ||
return getPathValue | ||
} | ||
@@ -0,1 +1,5 @@ | ||
/* @flow */ | ||
import { Vue } from './install' | ||
/** | ||
@@ -5,10 +9,49 @@ * utilites | ||
/** | ||
* isNil | ||
* | ||
* @param {*} val | ||
* @return Boolean | ||
*/ | ||
export function isNil (val) { | ||
export function isNil (val: mixed): boolean { | ||
return val === null || val === undefined | ||
} | ||
export function parseArgs (...args: any): Object { | ||
let locale = null | ||
if (args.length === 1) { | ||
if (Vue.util.isObject(args[0]) || Array.isArray(args[0])) { | ||
args = args[0] | ||
} else if (typeof args[0] === 'string') { | ||
locale = args[0] | ||
} | ||
} else if (args.length === 2) { | ||
if (typeof args[0] === 'string') { | ||
locale = args[0] | ||
} | ||
if (Vue.util.isObject(args[1]) || Array.isArray(args[1])) { | ||
args = args[1] | ||
} | ||
} | ||
return { locale, params: args } | ||
} | ||
function getOldChoiceIndexFixed (choice: number): number { | ||
return choice | ||
? choice > 1 | ||
? 1 | ||
: 0 | ||
: 1 | ||
} | ||
function getChoiceIndex (choice: number, choicesLength: number): number { | ||
choice = Math.abs(choice) | ||
if (choicesLength === 2) { return getOldChoiceIndexFixed(choice) } | ||
return choice ? Math.min(choice, 2) : 0 | ||
} | ||
export function fetchChoice (message: any, choice: number): ?string { | ||
if (!message && typeof message !== 'string') { return null } | ||
const choices: Array<string> = message.split('|') | ||
choice = getChoiceIndex(choice, choices.length) | ||
if (!choices[choice]) { return message } | ||
return choices[choice].trim() | ||
} |
@@ -1,11 +0,5 @@ | ||
/** | ||
* warn | ||
* | ||
* @param {String} msg | ||
* @param {Error} [err] | ||
* | ||
*/ | ||
/* @flow */ | ||
export default function warn (msg, err) { | ||
if (window.console) { | ||
export default function warn (msg: string, err: ?Error) { | ||
if (typeof console !== 'undefined') { | ||
console.warn('[vue-i18n] ' + msg) | ||
@@ -12,0 +6,0 @@ if (err) { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
87490
16
1929
1
5
1