0
# Localization
1
2
Complete internationalization support with auto-pluralization, locale-specific number formatting, and extensible locale definitions for duration unit labels and time notation templates.
3
4
## Capabilities
5
6
### Locale Extension System
7
8
Moment Duration Format extends moment.js locale objects with duration-specific localization data.
9
10
```javascript { .api }
11
/**
12
* Extend moment locale with duration formatting data
13
* @param locale - Locale identifier (e.g., 'en', 'de', 'fr')
14
* @param localeData - Duration-specific locale configuration
15
*/
16
moment.updateLocale(locale: string, localeData: {
17
durationLabelsStandard?: DurationLabels;
18
durationLabelsShort?: DurationLabels;
19
durationTimeTemplates?: TimeTemplates;
20
durationLabelTypes?: LabelType[];
21
durationPluralKey?: PluralKeyFunction;
22
}): void;
23
24
interface DurationLabels {
25
S: string; // millisecond singular
26
SS: string; // millisecond plural
27
s: string; // second singular
28
ss: string; // second plural
29
m: string; // minute singular
30
mm: string; // minute plural
31
h: string; // hour singular
32
hh: string; // hour plural
33
d: string; // day singular
34
dd: string; // day plural
35
w: string; // week singular
36
ww: string; // week plural
37
M: string; // month singular
38
MM: string; // month plural
39
y: string; // year singular
40
yy: string; // year plural
41
}
42
43
interface TimeTemplates {
44
HMS: string; // hour:minute:second template
45
HM: string; // hour:minute template
46
MS: string; // minute:second template
47
[key: string]: string; // custom templates
48
}
49
50
interface LabelType {
51
type: string; // label type name
52
string: string; // replacement marker
53
}
54
55
type PluralKeyFunction = (
56
token: string,
57
integerValue: number,
58
decimalValue: number | null
59
) => string;
60
```
61
62
### Default English Locale
63
64
Built-in English locale configuration that serves as fallback for all locales.
65
66
```javascript { .api }
67
// Default English locale extensions
68
moment.updateLocale('en', {
69
durationLabelsStandard: {
70
S: 'millisecond',
71
SS: 'milliseconds',
72
s: 'second',
73
ss: 'seconds',
74
m: 'minute',
75
mm: 'minutes',
76
h: 'hour',
77
hh: 'hours',
78
d: 'day',
79
dd: 'days',
80
w: 'week',
81
ww: 'weeks',
82
M: 'month',
83
MM: 'months',
84
y: 'year',
85
yy: 'years'
86
},
87
durationLabelsShort: {
88
S: 'msec',
89
SS: 'msecs',
90
s: 'sec',
91
ss: 'secs',
92
m: 'min',
93
mm: 'mins',
94
h: 'hr',
95
hh: 'hrs',
96
d: 'dy',
97
dd: 'dys',
98
w: 'wk',
99
ww: 'wks',
100
M: 'mo',
101
MM: 'mos',
102
y: 'yr',
103
yy: 'yrs'
104
},
105
durationTimeTemplates: {
106
HMS: 'h:mm:ss',
107
HM: 'h:mm',
108
MS: 'm:ss'
109
},
110
durationLabelTypes: [
111
{ type: "standard", string: "__" },
112
{ type: "short", string: "_" }
113
],
114
durationPluralKey: function (token, integerValue, decimalValue) {
115
// Singular for value of 1, but not for 1.0
116
if (integerValue === 1 && decimalValue === null) {
117
return token;
118
}
119
return token + token;
120
}
121
});
122
```
123
124
## Auto-Localization Features
125
126
### Unit Label Replacement
127
128
Automatic replacement of underscore markers with localized unit labels.
129
130
**Usage Examples:**
131
132
```javascript
133
// Single underscore - short labels
134
moment.duration(2, "minutes").format("m _");
135
// "2 mins"
136
137
moment.duration(1, "hour").format("h _");
138
// "1 hr"
139
140
// Double underscore - standard labels
141
moment.duration(2, "minutes").format("m __");
142
// "2 minutes"
143
144
moment.duration(1, "hour").format("h __");
145
// "1 hour"
146
147
// Auto-pluralization
148
moment.duration(1, "minute").format("m __");
149
// "1 minute" (automatic singular)
150
151
moment.duration(2, "minutes").format("m __");
152
// "2 minutes" (automatic plural)
153
```
154
155
### Time Notation Templates
156
157
Localized time notation patterns for common duration display formats.
158
159
**Usage Examples:**
160
161
```javascript
162
// HMS - full time notation
163
moment.duration(3661, "seconds").format("_HMS_");
164
// "1:01:01"
165
166
// HM - hour:minute notation
167
moment.duration(3661, "seconds").format("_HM_");
168
// "1:01"
169
170
// MS - minute:second notation
171
moment.duration(61, "seconds").format("_MS_");
172
// "1:01"
173
174
// Combined with other elements
175
moment.duration(7322, "seconds").format("_HMS_ [elapsed]");
176
// "2:02:02 elapsed"
177
```
178
179
### Pluralization System
180
181
Intelligent pluralization based on numeric values and decimal precision.
182
183
**Usage Examples:**
184
185
```javascript
186
// Integer values
187
moment.duration(1, "minutes").format("m [minutes]");
188
// "1 minute" (singular)
189
190
moment.duration(2, "minutes").format("m [minutes]");
191
// "2 minutes" (plural)
192
193
moment.duration(0, "minutes").format("m [minutes]");
194
// "0 minutes" (plural for zero)
195
196
// Decimal values (always plural by default)
197
moment.duration(1, "minutes").format("m [minutes]", 2);
198
// "1.00 minutes" (plural due to decimal precision)
199
200
// Custom pluralization with manual labels
201
moment.duration(1, "minutes").format("m [minute]");
202
// "1 minutes" (corrected to plural automatically)
203
204
moment.duration(2, "minutes").format("m [minute]");
205
// "2 minutes" (corrected to plural)
206
```
207
208
## Creating Custom Locales
209
210
### Basic Locale Extension
211
212
Extending existing locales with duration-specific labels.
213
214
**Usage Examples:**
215
216
```javascript
217
// French locale extension
218
moment.updateLocale('fr', {
219
durationLabelsStandard: {
220
S: 'milliseconde',
221
SS: 'millisecondes',
222
s: 'seconde',
223
ss: 'secondes',
224
m: 'minute',
225
mm: 'minutes',
226
h: 'heure',
227
hh: 'heures',
228
d: 'jour',
229
dd: 'jours',
230
w: 'semaine',
231
ww: 'semaines',
232
M: 'mois',
233
MM: 'mois',
234
y: 'année',
235
yy: 'années'
236
},
237
durationLabelsShort: {
238
S: 'ms',
239
SS: 'ms',
240
s: 'sec',
241
ss: 'sec',
242
m: 'min',
243
mm: 'min',
244
h: 'h',
245
hh: 'h',
246
d: 'j',
247
dd: 'j',
248
w: 'sem',
249
ww: 'sem',
250
M: 'mois',
251
MM: 'mois',
252
y: 'an',
253
yy: 'ans'
254
}
255
});
256
257
// Using French locale
258
moment.locale('fr');
259
moment.duration(2, "minutes").format("m __");
260
// "2 minutes"
261
262
moment.duration(1, "hour").format("h _");
263
// "1 h"
264
```
265
266
### Advanced Locale with Custom Pluralization
267
268
Complex locale with multiple plural forms and custom time templates.
269
270
**Usage Examples:**
271
272
```javascript
273
// Example: Custom locale with three plural forms
274
moment.updateLocale('sample', {
275
durationLabelsLong: {
276
s: 'singular long second',
277
ss: 'first plural long seconds',
278
sss: 'many plural long seconds'
279
},
280
durationLabelsStandard: {
281
s: 'singular second',
282
ss: 'first plural seconds',
283
sss: 'many plural seconds'
284
},
285
durationLabelsShort: {
286
s: 'singular sec',
287
ss: 'first plural secs',
288
sss: 'many plural secs'
289
},
290
durationTimeTemplates: {
291
HMS: 'h[h]:mm[m]:ss[s]', // Custom time template
292
HS: 'hh[h].ssss[s]' // Custom template
293
},
294
durationLabelTypes: [
295
{ type: "long", string: "___" }, // Triple underscore
296
{ type: "standard", string: "__" }, // Double underscore
297
{ type: "short", string: "_" } // Single underscore
298
],
299
durationPluralKey: function (token, integerValue, decimalValue) {
300
// Custom pluralization logic
301
if (integerValue === 1 && decimalValue === null) {
302
return token; // "s" for exactly 1
303
} else if (integerValue === 2) {
304
return token + token; // "ss" for exactly 2
305
} else {
306
return token + token + token; // "sss" for all others
307
}
308
}
309
});
310
311
// Using custom locale
312
moment.locale('sample');
313
moment.duration(1, "second").format("s ___");
314
// "1 singular long second"
315
316
moment.duration(2, "seconds").format("s ___");
317
// "2 first plural long seconds"
318
319
moment.duration(5, "seconds").format("s ___");
320
// "5 many plural long seconds"
321
```
322
323
### Custom Time Templates
324
325
Adding specialized time notation templates to locales.
326
327
**Usage Examples:**
328
329
```javascript
330
// Add custom time templates
331
moment.updateLocale('en', {
332
durationTimeTemplates: {
333
HMS: 'h:mm:ss',
334
HM: 'h:mm',
335
MS: 'm:ss',
336
DHMS: 'd[d] h:mm:ss', // Custom: days + time
337
PRECISION: 'h:mm:ss.SSS' // Custom: with milliseconds
338
}
339
});
340
341
// Using custom templates
342
moment.duration(90061, "seconds").format("_DHMS_");
343
// "1d 1:01:01"
344
345
moment.duration(3661789, "milliseconds").format("_PRECISION_");
346
// "1:01:01.789"
347
```
348
349
## Locale-Specific Number Formatting
350
351
### User Locale Setting
352
353
Override moment locale for numerical formatting only.
354
355
**Usage Examples:**
356
357
```javascript
358
// Using German locale for numbers, English for labels
359
moment.locale('en'); // English labels
360
moment.duration(1234567, "seconds").format({
361
template: "m [minutes]",
362
precision: 3,
363
userLocale: "de-DE" // German number formatting
364
});
365
// "20.576,117 minutes"
366
367
// Compare with English number formatting
368
moment.duration(1234567, "seconds").format({
369
template: "m [minutes]",
370
precision: 3,
371
userLocale: "en-US"
372
});
373
// "20,576.117 minutes"
374
```
375
376
### Locale Detection and Fallback
377
378
Automatic fallback to English locale when duration extensions are missing.
379
380
**Usage Examples:**
381
382
```javascript
383
// Set moment to unsupported locale
384
moment.locale('xyz-unknown');
385
386
// Duration formatting falls back to English
387
moment.duration(2, "minutes").format("m __");
388
// "2 minutes" (English fallback)
389
390
// But uses locale for number formatting if available
391
moment.duration(1234, "seconds").format("s [seconds]");
392
// Number formatting may vary based on system locale
393
```
394
395
## Pluralization Function Details
396
397
### Plural Key Function Interface
398
399
Function signature for custom pluralization logic.
400
401
```javascript { .api }
402
/**
403
* Determines the appropriate label key for a duration value
404
* @param token - Single character unit token (s, m, h, d, w, M, y, S)
405
* @param integerValue - Integer portion of the duration value
406
* @param decimalValue - Decimal portion (null if no decimal part)
407
* @returns Label key to use for lookup (e.g., "s", "ss", "sss")
408
*/
409
type PluralKeyFunction = (
410
token: string,
411
integerValue: number,
412
decimalValue: number | null
413
) => string;
414
```
415
416
**Usage Examples:**
417
418
```javascript
419
// Default English pluralization
420
function englishPluralKey(token, integerValue, decimalValue) {
421
// Singular only for exactly 1 with no decimal
422
if (integerValue === 1 && decimalValue === null) {
423
return token; // "s" -> singular label
424
}
425
return token + token; // "ss" -> plural label
426
}
427
428
// Custom: Slavic-style pluralization
429
function slavicPluralKey(token, integerValue, decimalValue) {
430
// Complex Slavic plural rules (simplified example)
431
if (integerValue === 1 && decimalValue === null) {
432
return token; // 1 -> singular
433
} else if (integerValue >= 2 && integerValue <= 4) {
434
return token + token; // 2-4 -> first plural
435
} else {
436
return token + token + token; // 5+ -> second plural
437
}
438
}
439
440
// Custom: Always plural
441
function alwaysPluralKey(token, integerValue, decimalValue) {
442
return token + token; // Always use plural form
443
}
444
```
445
446
### Integration with Label Types
447
448
Pluralization works in conjunction with label types for complete localization.
449
450
**Usage Examples:**
451
452
```javascript
453
// Set up locale with multiple label types and custom pluralization
454
moment.updateLocale('multi', {
455
durationLabelsVerbose: {
456
s: 'one verbose second',
457
ss: 'few verbose seconds',
458
sss: 'many verbose seconds'
459
},
460
durationLabelsStandard: {
461
s: 'one second',
462
ss: 'few seconds',
463
sss: 'many seconds'
464
},
465
durationLabelsShort: {
466
s: 'one sec',
467
ss: 'few secs',
468
sss: 'many secs'
469
},
470
durationLabelTypes: [
471
{ type: "verbose", string: "____" }, // 4 underscores
472
{ type: "standard", string: "__" }, // 2 underscores
473
{ type: "short", string: "_" } // 1 underscore
474
],
475
durationPluralKey: function(token, integerValue, decimalValue) {
476
if (integerValue === 1 && decimalValue === null) return token;
477
if (integerValue >= 2 && integerValue <= 4) return token + token;
478
return token + token + token;
479
}
480
});
481
482
// Using different label types with pluralization
483
moment.locale('multi');
484
moment.duration(1, "second").format("s ____"); // "1 one verbose second"
485
moment.duration(3, "seconds").format("s ____"); // "3 few verbose seconds"
486
moment.duration(7, "seconds").format("s ____"); // "7 many verbose seconds"
487
```