UNPKG

3.52 kBJavaScriptView Raw
1/* globals Intl */
2'use strict'
3
4var assign = require('object-assign')
5var parse = require('format-message-parse')
6var interpret = require('format-message-interpret')
7var lookupClosestLocale = require('lookup-closest-locale')
8var formats = require('format-message-formats')
9
10var number = formats.number
11var date = formats.date
12var time = formats.time
13var cache = {}
14
15var currentLocale = 'en'
16var translations = null
17var generateId = function (pattern) { return pattern }
18var missingReplacement = null
19var missingTranslation = 'warning'
20
21module.exports = formatMessage
22function formatMessage (msg, args, locale) {
23 locale = locale || currentLocale
24 var pattern = typeof msg === 'string' ? msg : msg.default
25 var id = typeof msg === 'object' && msg.id || generateId(pattern)
26 var key = locale + ':' + id
27 var format = cache[key] ||
28 (cache[key] = generateFormat(locale, pattern, id))
29 if (typeof format === 'string') return format
30 return format(args)
31}
32
33function generateFormat (locale, pattern, id) {
34 pattern = translate(locale, pattern, id)
35 return interpret(locale, parse(pattern))
36}
37
38function translate (locale, pattern, id) {
39 if (!translations) return pattern
40
41 locale = lookupClosestLocale(locale, translations)
42 var translated = translations[locale] && translations[locale][id]
43 if (translated && translated.message) translated = translated.message
44 if (translated != null) return translated
45
46 var replacement = missingReplacement || pattern
47 var message = 'Translation for "' + id + '" in "' + locale + '" is missing'
48
49 if (missingTranslation === 'ignore') {
50 // do nothing
51 } else if (missingTranslation === 'warning') {
52 if (typeof console !== 'undefined') console.warn(message)
53 } else { // 'error'
54 throw new Error(message)
55 }
56
57 return replacement
58}
59
60formatMessage.setup = function setup (opt) {
61 opt = opt || {}
62 if (opt.locale) currentLocale = opt.locale
63 if ('translations' in opt) translations = opt.translations
64 if (opt.generateId) generateId = opt.generateId
65 if ('missingReplacement' in opt) missingReplacement = opt.missingReplacement
66 if (opt.missingTranslation) missingTranslation = opt.missingTranslation
67 if (opt.formats) {
68 if (opt.formats.number) assign(number, opt.formats.number)
69 if (opt.formats.date) assign(date, opt.formats.date)
70 if (opt.formats.time) assign(time, opt.formats.time)
71 }
72}
73
74formatMessage.number = function (locale, value, style) {
75 var options = number[style] || number.decimal
76 if (typeof Intl === 'undefined') {
77 return Number(value).toLocaleString(locale, options)
78 }
79 var cache = options.cache || (options.cache = {})
80 var format = cache[locale] ||
81 (cache[locale] = new Intl.NumberFormat(locale, options).format)
82 return format(value)
83}
84
85formatMessage.date = function (locale, value, style) {
86 var options = date[style] || date.medium
87 if (typeof Intl === 'undefined') {
88 return new Date(value).toLocaleDateString(locale, options)
89 }
90 var cache = options.cache || (options.cache = {})
91 var format = cache[locale] ||
92 (cache[locale] = new Intl.DateTimeFormat(locale, options).format)
93 return format(value)
94}
95
96formatMessage.time = function (locale, value, style) {
97 var options = time[style] || time.medium
98 if (typeof Intl === 'undefined') {
99 return new Date(value).toLocaleTimeString(locale, options)
100 }
101 var cache = options.cache || (options.cache = {})
102 var format = cache[locale] ||
103 (cache[locale] = new Intl.DateTimeFormat(locale, options).format)
104 return format(value)
105}