Skip to content

Commit fbd877e

Browse files
committed
feat(no-vue): ability to use interpolation outside without vue
1 parent d20bb7e commit fbd877e

File tree

4 files changed

+149
-122
lines changed

4 files changed

+149
-122
lines changed

dist/vue-gettext.js

Lines changed: 133 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,126 @@
184184

185185
};
186186

187+
// Ensure to always use the same Vue instance throughout the plugin.
188+
//
189+
// This was previously done in `index.js` using both named and default exports.
190+
// However, this currently must be kept in a separate file because we are using
191+
// Rollup to build the dist files and it has a drawback when using named and
192+
// default exports together, see:
193+
// https://github.com/rollup/rollup/blob/fca14d/src/utils/getExportMode.js#L27
194+
// https://github.com/rollup/rollup/wiki/JavaScript-API#exports
195+
//
196+
// If we had kept named and default exports in `index.js`, a user would have to
197+
// do something like this to access the default export: GetTextPlugin['default']
198+
199+
var _Vue;
200+
201+
function shareVueInstance (Vue) {
202+
_Vue = Vue;
203+
}
204+
205+
var EVALUATION_RE = /[[\].]{1,2}/g;
206+
207+
/* Interpolation RegExp.
208+
*
209+
* Because interpolation inside attributes are deprecated in Vue 2 we have to
210+
* use another set of delimiters to be able to use `translate-plural` etc.
211+
* We use %{ } delimiters.
212+
*
213+
* /
214+
* %\{ => Starting delimiter: `%{`
215+
* ( => Start capture
216+
* (?:.|\n) => Non-capturing group: any character or newline
217+
* +? => One or more times (ungreedy)
218+
* ) => End capture
219+
* \} => Ending delimiter: `}`
220+
* /g => Global: don't return after first match
221+
*/
222+
var INTERPOLATION_RE = /%\{((?:.|\n)+?)\}/g;
223+
224+
var MUSTACHE_SYNTAX_RE = /\{\{((?:.|\n)+?)\}\}/g;
225+
226+
/**
227+
* Evaluate a piece of template string containing %{ } placeholders.
228+
* E.g.: 'Hi %{ user.name }' => 'Hi Bob'
229+
*
230+
* This is a vm.$interpolate alternative for Vue 2.
231+
* https://vuejs.org/v2/guide/migration.html#vm-interpolate-removed
232+
*
233+
* @param {String} msgid - The translation key containing %{ } placeholders
234+
* @param {Object} context - An object whose elements are put in their corresponding placeholders
235+
*
236+
* @return {String} The interpolated string
237+
*/
238+
var interpolate = function (msgid, context, disableHtmlEscaping) {
239+
if ( context === void 0 ) context = {};
240+
if ( disableHtmlEscaping === void 0 ) disableHtmlEscaping = false;
241+
242+
243+
if (_Vue && !_Vue.config.getTextPluginSilent && MUSTACHE_SYNTAX_RE.test(msgid)) {
244+
console.warn(("Mustache syntax cannot be used with vue-gettext. Please use \"%{}\" instead of \"{{}}\" in: " + msgid));
245+
}
246+
247+
var result = msgid.replace(INTERPOLATION_RE, function (match, token) {
248+
249+
var expression = token.trim();
250+
var evaluated;
251+
252+
var escapeHtmlMap = {
253+
'&': '&',
254+
'<': '&lt;',
255+
'>': '&gt;',
256+
'"': '&quot;',
257+
'\'': '&#039;',
258+
};
259+
260+
// Avoid eval() by splitting `expression` and looping through its different properties if any, see #55.
261+
function getProps (obj, expression) {
262+
var arr = expression.split(EVALUATION_RE).filter(function (x) { return x; });
263+
while (arr.length) {
264+
obj = obj[arr.shift()];
265+
}
266+
return obj
267+
}
268+
269+
function evalInContext (expression) {
270+
try {
271+
evaluated = getProps(this, expression);
272+
} catch (e) {
273+
// Ignore errors, because this function may be called recursively later.
274+
}
275+
if (evaluated === undefined) {
276+
if (this.$parent) {
277+
// Recursively climb the $parent chain to allow evaluation inside nested components, see #23 and #24.
278+
return evalInContext.call(this.$parent, expression)
279+
} else {
280+
console.warn(("Cannot evaluate expression: " + expression));
281+
evaluated = expression;
282+
}
283+
}
284+
var result = evaluated.toString();
285+
if (disableHtmlEscaping) {
286+
// Do not escape HTML, see #78.
287+
return result
288+
}
289+
// Escape HTML, see #78.
290+
return result.replace(/[&<>"']/g, function (m) { return escapeHtmlMap[m] })
291+
}
292+
293+
return evalInContext.call(context, expression)
294+
295+
});
296+
297+
return result
298+
299+
};
300+
301+
// Store this values as function attributes for easy access elsewhere to bypass a Rollup
302+
// weak point with `export`:
303+
// https://github.com/rollup/rollup/blob/fca14d/src/utils/getExportMode.js#L27
304+
interpolate.INTERPOLATION_RE = INTERPOLATION_RE;
305+
interpolate.INTERPOLATION_PREFIX = '%{';
306+
187307
var SPACING_RE = /\s{2,}/g;
188308

189309
// Default configuration if only the translation is passed.
@@ -371,6 +491,19 @@
371491
}
372492
},
373493

494+
/**
495+
* Allows to use interpolation outside the Vue
496+
*
497+
* @example
498+
* import {translate} from 'vue-gettext';
499+
*
500+
* const {gettext, gettextInterpolate} = translate;
501+
*
502+
* let translated = gettext('%{ n } foos', n)
503+
* let interpolated = gettextInterpolate(translated, {n: 5})
504+
*/
505+
gettextInterpolate: interpolate.bind(interpolate),
506+
374507
};
375508

376509
// UUID v4 generator (RFC4122 compliant).
@@ -395,24 +528,6 @@
395528

396529
}
397530

398-
// Ensure to always use the same Vue instance throughout the plugin.
399-
//
400-
// This was previously done in `index.js` using both named and default exports.
401-
// However, this currently must be kept in a separate file because we are using
402-
// Rollup to build the dist files and it has a drawback when using named and
403-
// default exports together, see:
404-
// https://github.com/rollup/rollup/blob/fca14d/src/utils/getExportMode.js#L27
405-
// https://github.com/rollup/rollup/wiki/JavaScript-API#exports
406-
//
407-
// If we had kept named and default exports in `index.js`, a user would have to
408-
// do something like this to access the default export: GetTextPlugin['default']
409-
410-
var _Vue;
411-
412-
function shareVueInstance (Vue) {
413-
_Vue = Vue;
414-
}
415-
416531
/**
417532
* Translate content according to the current language.
418533
*/
@@ -510,108 +625,6 @@
510625

511626
};
512627

513-
var EVALUATION_RE = /[[\].]{1,2}/g;
514-
515-
/* Interpolation RegExp.
516-
*
517-
* Because interpolation inside attributes are deprecated in Vue 2 we have to
518-
* use another set of delimiters to be able to use `translate-plural` etc.
519-
* We use %{ } delimiters.
520-
*
521-
* /
522-
* %\{ => Starting delimiter: `%{`
523-
* ( => Start capture
524-
* (?:.|\n) => Non-capturing group: any character or newline
525-
* +? => One or more times (ungreedy)
526-
* ) => End capture
527-
* \} => Ending delimiter: `}`
528-
* /g => Global: don't return after first match
529-
*/
530-
var INTERPOLATION_RE = /%\{((?:.|\n)+?)\}/g;
531-
532-
var MUSTACHE_SYNTAX_RE = /\{\{((?:.|\n)+?)\}\}/g;
533-
534-
/**
535-
* Evaluate a piece of template string containing %{ } placeholders.
536-
* E.g.: 'Hi %{ user.name }' => 'Hi Bob'
537-
*
538-
* This is a vm.$interpolate alternative for Vue 2.
539-
* https://vuejs.org/v2/guide/migration.html#vm-interpolate-removed
540-
*
541-
* @param {String} msgid - The translation key containing %{ } placeholders
542-
* @param {Object} context - An object whose elements are put in their corresponding placeholders
543-
*
544-
* @return {String} The interpolated string
545-
*/
546-
var interpolate = function (msgid, context, disableHtmlEscaping) {
547-
if ( context === void 0 ) context = {};
548-
if ( disableHtmlEscaping === void 0 ) disableHtmlEscaping = false;
549-
550-
551-
if (!_Vue.config.getTextPluginSilent && MUSTACHE_SYNTAX_RE.test(msgid)) {
552-
console.warn(("Mustache syntax cannot be used with vue-gettext. Please use \"%{}\" instead of \"{{}}\" in: " + msgid));
553-
}
554-
555-
var result = msgid.replace(INTERPOLATION_RE, function (match, token) {
556-
557-
var expression = token.trim();
558-
var evaluated;
559-
560-
var escapeHtmlMap = {
561-
'&': '&amp;',
562-
'<': '&lt;',
563-
'>': '&gt;',
564-
'"': '&quot;',
565-
'\'': '&#039;',
566-
};
567-
568-
// Avoid eval() by splitting `expression` and looping through its different properties if any, see #55.
569-
function getProps (obj, expression) {
570-
var arr = expression.split(EVALUATION_RE).filter(function (x) { return x; });
571-
while (arr.length) {
572-
obj = obj[arr.shift()];
573-
}
574-
return obj
575-
}
576-
577-
function evalInContext (expression) {
578-
try {
579-
evaluated = getProps(this, expression);
580-
} catch (e) {
581-
// Ignore errors, because this function may be called recursively later.
582-
}
583-
if (evaluated === undefined) {
584-
if (this.$parent) {
585-
// Recursively climb the $parent chain to allow evaluation inside nested components, see #23 and #24.
586-
return evalInContext.call(this.$parent, expression)
587-
} else {
588-
console.warn(("Cannot evaluate expression: " + expression));
589-
evaluated = expression;
590-
}
591-
}
592-
var result = evaluated.toString();
593-
if (disableHtmlEscaping) {
594-
// Do not escape HTML, see #78.
595-
return result
596-
}
597-
// Escape HTML, see #78.
598-
return result.replace(/[&<>"']/g, function (m) { return escapeHtmlMap[m] })
599-
}
600-
601-
return evalInContext.call(context, expression)
602-
603-
});
604-
605-
return result
606-
607-
};
608-
609-
// Store this values as function attributes for easy access elsewhere to bypass a Rollup
610-
// weak point with `export`:
611-
// https://github.com/rollup/rollup/blob/fca14d/src/utils/getExportMode.js#L27
612-
interpolate.INTERPOLATION_RE = INTERPOLATION_RE;
613-
interpolate.INTERPOLATION_PREFIX = '%{';
614-
615628
// Check if two values are loosely equal - that is,
616629
// if they are plain objects, do they have the same shape?
617630
// https://github.com/vuejs/vue/blob/v2.6.11/src/shared/util.js#L285

0 commit comments

Comments
 (0)