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

i18next / i18next / 19837025733

01 Dec 2025 08:47PM UTC coverage: 95.348% (+11.4%) from 83.922%
19837025733

push

github

adrai
TS: remove wrong signature #2372

1072 of 1172 branches covered (91.47%)

2480 of 2601 relevant lines covered (95.35%)

1091.51 hits per line

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

84.81
/src/PluralResolver.js
1
import baseLogger from './logger.js';
2✔
2
import { getCleanedCode } from './utils.js'
2✔
3

4
const suffixesOrder = {
2✔
5
  zero: 0,
2✔
6
  one: 1,
2✔
7
  two: 2,
2✔
8
  few: 3,
2✔
9
  many: 4,
2✔
10
  other: 5,
2✔
11
};
2✔
12

13
const dummyRule = {
2✔
14
  select: (count) => count === 1 ? 'one' : 'other',
2!
15
  resolvedOptions: () => ({
2✔
16
    pluralCategories: ['one', 'other']
×
17
  })
×
18
};
2✔
19

20
class PluralResolver {
2✔
21
  constructor(languageUtils, options = {}) {
2✔
22
    this.languageUtils = languageUtils;
253✔
23
    this.options = options;
253✔
24

25
    this.logger = baseLogger.create('pluralResolver');
253✔
26

27
    // Cache calls to Intl.PluralRules, since repeated calls can be slow in runtimes like React Native
253✔
28
    // and the memory usage difference is negligible
253✔
29
    this.pluralRulesCache = {};
253✔
30
  }
253✔
31

32
  addRule(lng, obj) {
2✔
33
    this.rules[lng] = obj;
×
34
  }
×
35

36
  clearCache() {
2✔
37
    this.pluralRulesCache = {};
1✔
38
  }
1✔
39

40
  getRule(code, options = {}) {
2✔
41
    const cleanedCode = getCleanedCode(code === 'dev' ? 'en' : code);
237!
42
    const type = options.ordinal ? 'ordinal' : 'cardinal';
237✔
43
    const cacheKey = JSON.stringify({ cleanedCode, type });
237✔
44

45
    if (cacheKey in this.pluralRulesCache) {
237✔
46
      return this.pluralRulesCache[cacheKey];
197✔
47
    }
197✔
48

49
    let rule;
40✔
50

51
    try {
40✔
52
      rule = new Intl.PluralRules(cleanedCode, { type });
40✔
53
    } catch (err) {
237✔
54
      if (!Intl) {
2!
55
        this.logger.error('No Intl support, please use an Intl polyfill!');
×
56
        return dummyRule;
×
57
      }
×
58
      if (!code.match(/-|_/)) return dummyRule;
2!
59
      const lngPart = this.languageUtils.getLanguagePartFromCode(code);
×
60
      rule = this.getRule(lngPart, options);
×
61
    }
✔
62

63
    this.pluralRulesCache[cacheKey] = rule;
38✔
64
    return rule;
38✔
65
  }
237✔
66

67
  needsPlural(code, options = {}) {
2✔
68
    let rule = this.getRule(code, options);
2✔
69
    if (!rule) rule = this.getRule('dev', options);
2!
70
    return rule?.resolvedOptions().pluralCategories.length > 1;
2✔
71
  }
2✔
72

73
  getPluralFormsOfKey(code, key, options = {}) {
2✔
74
    return this.getSuffixes(code, options).map((suffix) => `${key}${suffix}`);
1✔
75
  }
1✔
76

77
  getSuffixes(code, options = {}) {
2✔
78
    let rule = this.getRule(code, options);
11✔
79
    if (!rule) rule = this.getRule('dev', options);
11!
80
    if (!rule) return [];
11!
81

82
    return rule.resolvedOptions().pluralCategories
11✔
83
      .sort((pluralCategory1, pluralCategory2) => suffixesOrder[pluralCategory1] - suffixesOrder[pluralCategory2])
11✔
84
      .map(pluralCategory => `${this.options.prepend}${options.ordinal ? `ordinal${this.options.prepend}` : ''}${pluralCategory}`);
11✔
85
  }
11✔
86

87
  getSuffix(code, count, options = {}) {
2✔
88
    const rule = this.getRule(code, options);
222✔
89

90
    if (rule) {
222✔
91
      return `${this.options.prepend}${options.ordinal ? `ordinal${this.options.prepend}` : ''}${rule.select(count)}`;
222✔
92
    }
222!
93

94
    this.logger.warn(`no plural rule found for: ${code}`);
×
95
    return this.getSuffix('dev', count, options);
×
96
  }
222✔
97
}
2✔
98

99
export default PluralResolver;
2✔
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

© 2026 Coveralls, Inc