1 |
|
2 | 'use strict'
|
3 |
|
4 | var assign = require('object-assign')
|
5 | var parse = require('format-message-parse')
|
6 | var interpret = require('format-message-interpret')
|
7 | var lookupClosestLocale = require('lookup-closest-locale')
|
8 | var formats = require('format-message-formats')
|
9 |
|
10 | var number = formats.number
|
11 | var date = formats.date
|
12 | var time = formats.time
|
13 | var cache = {}
|
14 |
|
15 | var currentLocale = 'en'
|
16 | var translations = null
|
17 | var generateId = function (pattern) { return pattern }
|
18 | var missingReplacement = null
|
19 | var missingTranslation = 'warning'
|
20 |
|
21 | module.exports = formatMessage
|
22 | function 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 |
|
33 | function generateFormat (locale, pattern, id) {
|
34 | pattern = translate(locale, pattern, id)
|
35 | return interpret(locale, parse(pattern))
|
36 | }
|
37 |
|
38 | function 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 |
|
51 | } else if (missingTranslation === 'warning') {
|
52 | if (typeof console !== 'undefined') console.warn(message)
|
53 | } else {
|
54 | throw new Error(message)
|
55 | }
|
56 |
|
57 | return replacement
|
58 | }
|
59 |
|
60 | formatMessage.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 |
|
74 | formatMessage.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 |
|
85 | formatMessage.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 |
|
96 | formatMessage.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 | }
|