• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mozilla / blurts-server / #11485

pending completion
#11485

push

circleci

web-flow
Merge pull request #2719 from mozilla/MNTOR-954

Mntor-954: fluent error

278 of 1063 branches covered (26.15%)

Branch coverage included in aggregate %.

4 of 4 new or added lines in 2 files covered. (100.0%)

948 of 2880 relevant lines covered (32.92%)

2.6 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/utils/fluent.js
1
import { join, resolve } from 'node:path'
2
import { readdirSync } from 'node:fs'
3
import { readFile } from 'node:fs/promises'
4
import { FluentBundle, FluentResource } from '@fluent/bundle'
5
import { negotiateLanguages } from '@fluent/langneg'
6
import AppConstants from '../app-constants.js'
7
import { localStorage } from './local-storage.js'
8

9
const supportedLocales = AppConstants.SUPPORTED_LOCALES?.split(',')
×
10
const fluentBundles = {}
×
11

12
/**
13
* Create Fluent bundles for all supported locales.
14
* Reads .ftl files in parallel for better server start performance.
15
*/
16
async function initFluentBundles () {
17
  const promises = supportedLocales.map(async locale => {
×
18
    const bundle = new FluentBundle(locale, { useIsolating: false })
×
19
    const dirname = resolve('../locales', locale)
×
20

21
    try {
×
22
      const filenames = readdirSync(dirname).filter(item => item.endsWith('.ftl'))
×
23

24
      await Promise.all(filenames.map(async filename => {
×
25
        const str = await readFile(join(dirname, filename), 'utf8')
×
26

27
        bundle.addResource(new FluentResource(str))
×
28
      }))
29
    } catch (e) {
30
      console.error('Could not read Fluent file:', e)
×
31
      throw new Error(e)
×
32
    }
33

34
    fluentBundles[locale] = bundle
×
35
  })
36

37
  await Promise.allSettled(promises)
×
38

39
  console.log('Fluent bundles created:', Object.keys(fluentBundles))
×
40
}
41

42
/**
43
* Set the locale used for translations negotiated between requested and available
44
* @param {Array} requestedLocales - Locales requested by client.
45
*/
46
function updateLocale (requestedLocales) {
47
  return negotiateLanguages(
×
48
    requestedLocales,
49
    supportedLocales,
50
    { strategy: 'lookup', defaultLocale: 'en' }
51
  )
52
}
53

54
/**
55
* Translate a message and return the raw string
56
* Defaults to en if message id not found in requested locale
57
* @param {string} id - The Fluent message id.
58
*/
59
function getRawMessage (id) {
60
  const locale = localStorage.getStore()?.get('locale') || 'en'
×
61
  let bundle = fluentBundles[locale]
×
62

63
  if (!bundle.hasMessage(id)) bundle = fluentBundles.en
×
64

65
  if (bundle.hasMessage(id)) return bundle.getMessage(id).value
×
66

67
  return id
×
68
}
69

70
/**
71
* Translate and transform a message pattern
72
* Defaults to en if message id not found in requested locale
73
* @param {string} id - The Fluent message id.
74
* @param {object} args - key/value pairs corresponding to pattern in Fluent resource.
75
* @example
76
* // Given FluentResource("hello = Hello, {$name}!")
77
* getMessage (hello, {name: "Jane"})
78
* // Returns "Hello, Jane!"
79
*/
80
function getMessage (id, args) {
81
  const locale = localStorage.getStore()?.get('locale') || 'en'
×
82
  let bundle = fluentBundles[locale]
×
83

84
  if (!bundle.hasMessage(id)) bundle = fluentBundles.en
×
85

86
  if (bundle.hasMessage(id)) return bundle.formatPattern(bundle.getMessage(id).value, args)
×
87

88
  return id
×
89
}
90

91
function fluentError (id) {
92
  return new Error(getMessage(id))
×
93
}
94

95
export { initFluentBundles, updateLocale, getMessage, getRawMessage, fluentError }
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc