-
Notifications
You must be signed in to change notification settings - Fork 77
/
localization.js
78 lines (66 loc) · 2.03 KB
/
localization.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import { mapBundleSync } from "@fluent/sequence";
import { CachedSyncIterable } from "cached-iterable";
/*
* `ReactLocalization` handles translation formatting and fallback.
*
* The current negotiated fallback chain of languages is stored in the
* `ReactLocalization` instance in form of an iterable of `FluentBundle`
* instances. This iterable is used to find the best existing translation for
* a given identifier.
*
* `Localized` components must subscribe to the changes of the
* `ReactLocalization`'s fallback chain. When the fallback chain changes (the
* `bundles` iterable is set anew), all subscribed compontent must relocalize.
*
* The `ReactLocalization` class instances are exposed to `Localized` elements
* via the `LocalizationProvider` component.
*/
export default class ReactLocalization {
constructor(bundles) {
this.bundles = CachedSyncIterable.from(bundles);
this.subs = new Set();
}
/*
* Subscribe a `Localized` component to changes of `bundles`.
*/
subscribe(comp) {
this.subs.add(comp);
}
/*
* Unsubscribe a `Localized` component from `bundles` changes.
*/
unsubscribe(comp) {
this.subs.delete(comp);
}
/*
* Set a new `bundles` iterable and trigger the retranslation.
*/
setBundles(bundles) {
this.bundles = CachedSyncIterable.from(bundles);
// Update all subscribed Localized components.
this.subs.forEach(comp => comp.relocalize());
}
getBundle(id) {
return mapBundleSync(this.bundles, id);
}
/*
* Find a translation by `id` and format it to a string using `args`.
*/
getString(id, args, fallback) {
const bundle = this.getBundle(id);
if (bundle === null) {
return fallback || id;
}
const msg = bundle.getMessage(id);
return bundle.format(msg, args);
}
}
export function isReactLocalization(props, propName) {
const prop = props[propName];
if (prop instanceof ReactLocalization) {
return null;
}
return new Error(
`The ${propName} context field must be an instance of ReactLocalization.`
);
}