1/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6dictionary L10nFileSourceMockFile {
7  required UTF8String path;
8  required UTF8String source;
9};
10
11enum L10nFileSourceHasFileStatus {
12    "present",
13    "missing",
14    "unknown"
15};
16
17dictionary FileSourceOptions {
18  FluentBundleAddResourceOptions addResourceOptions = {};
19};
20
21/**
22 * A `ResourceId` refers to a localization resource that is either required
23 * or optional. The default for a `ResourceId` is that the resource is required.
24 *
25 * If a required resource is missing for a given locale, then the L10nRegistry
26 * will not generate a bundle for that locale, because the resource is required
27 * to be present in order for the bundle to be considered valid.
28 *
29 * If an optional resource is missing for a given locale, then the L10nRegistry
30 * will still generate a bundle for that locale, but entries for the missing
31 * optional resource will be missing in the bundle.
32 *
33 * It is recommended to only use this sparingly, since marking many resources as
34 * optional will increase the state space that the L10nRegistry solver has to cover,
35 * and it will have a negative impact on performance.
36 *
37 * We should also strive to have valid resources for all supported locales, so using
38 * optional resources should be reserved for exceptional circumstances such as
39 * experimental features and features under development.
40 */
41dictionary ResourceId {
42  required UTF8String path;
43  boolean _optional = false;
44};
45
46typedef (UTF8String or ResourceId) L10nResourceId;
47
48/**
49 * The interface represents a single source location for
50 * the registry.
51 *
52 * Examples of sources are:
53 *  * Toolkit omni.ja Localization Directory
54 *  * Browser omni.ja Localization Directory
55 *  * Language Pack Toolkit Localization Directory
56 *  * Language Pack Browser Localization Directory
57 */
58[ChromeOnly,
59 Exposed=Window]
60interface L10nFileSource {
61  /**
62   * The `name` is the name of the `L10nFileSource`.
63   *
64   * The `metaSource` is the name of the package that contains the
65   * `L10nFileSource`, e.g. `app` for sources packaged with the browser, or
66   * `langpack` for sources packaged in an addon.
67   *
68   * The `locales` is a list of locales for which resources are contained in
69   * the `L10nFileSource`.
70   *
71   * The `prePath` is the path prefix for files contained in the `L10nFileSource`.
72   *
73   * Optional argument `index` can be used to provide a list
74   * of files available in the source.
75   *
76   * This is particularly useful for custom file sources which
77   * provide a small number of known override files allowing the
78   * registry to avoid trying I/O on the source for all
79   * files not available in the source.
80   */
81  [Throws]
82  constructor(UTF8String name, UTF8String metaSource, sequence<UTF8String> locales, UTF8String prePath, optional FileSourceOptions options = {}, optional sequence<UTF8String> index);
83
84  /**
85   * Tests may want to introduce custom file sources and
86   * register them in a custom `L10nRegistry` to mock
87   * behavior of using localization with test file sources.
88   *
89   * # Example:
90   *
91   * ```
92   * let fs = [
93   *   {
94   *     "path": "/localization/en-US/test.ftl",
95   *     "source": "key = Hello World!",
96   *   }
97   * ];
98   * let mockSource = L10nFileSource.createMock("mock", "app", ["en-US"], "/localization/{locale}/", fs);
99   *
100   * let reg = new L10nRegistry();
101   * reg.registerSources([mockSource]);
102   *
103   * let loc = new Localization(["test.ftl"], reg);
104   * let value = await loc.formatValue("key");
105   * assert(value, "Hello World!");
106   * ```
107   */
108  [Throws]
109  static L10nFileSource createMock(UTF8String name, UTF8String metasource, sequence<UTF8String> locales, UTF8String prePath, sequence<L10nFileSourceMockFile> fs);
110
111  readonly attribute UTF8String name;
112  readonly attribute UTF8String metaSource;
113  [Pure, Cached, Frozen]
114  readonly attribute sequence<UTF8String> locales;
115  /**
116   * `prePath` is the root path used together with a relative path to construct the full path used to retrieve a file
117   * out of a file source.
118   *
119   * The `prePath` will usually contain a placeholder `{locale}` which gets replaced with a given locale.
120   */
121  readonly attribute UTF8String prePath;
122  [Pure, Cached, Frozen]
123  readonly attribute sequence<UTF8String>? index;
124
125  [Throws]
126  L10nFileSourceHasFileStatus hasFile(UTF8String locale, UTF8String path);
127  [Throws]
128  Promise<FluentResource?> fetchFile(UTF8String locale, UTF8String path);
129  [Throws]
130  FluentResource? fetchFileSync(UTF8String locale, UTF8String path);
131};
132
133dictionary FluentBundleIteratorResult
134{
135  required FluentBundle? value;
136  required boolean done;
137};
138
139[LegacyNoInterfaceObject, Exposed=Window]
140interface FluentBundleIterator {
141  FluentBundleIteratorResult next();
142  [Alias="@@iterator"] FluentBundleIterator values();
143};
144
145[LegacyNoInterfaceObject, Exposed=Window]
146interface FluentBundleAsyncIterator {
147  Promise<FluentBundleIteratorResult> next();
148  [Alias="@@asyncIterator"] FluentBundleAsyncIterator values();
149};
150
151dictionary L10nRegistryOptions {
152  FluentBundleOptions bundleOptions = {};
153};
154
155[ChromeOnly, Exposed=Window]
156interface L10nRegistry {
157  constructor(optional L10nRegistryOptions aOptions = {});
158
159  static L10nRegistry getInstance();
160
161  sequence<UTF8String> getAvailableLocales();
162
163  void registerSources(sequence<L10nFileSource> aSources);
164  void updateSources(sequence<L10nFileSource> aSources);
165  void removeSources(sequence<UTF8String> aSources);
166
167  [Throws]
168  boolean hasSource(UTF8String aName);
169  [Throws]
170  L10nFileSource? getSource(UTF8String aName);
171  sequence<UTF8String> getSourceNames();
172  void clearSources();
173
174  [Throws, NewObject]
175  FluentBundleIterator generateBundlesSync(sequence<UTF8String> aLocales, sequence<L10nResourceId> aResourceIds);
176
177  [Throws, NewObject]
178  FluentBundleAsyncIterator generateBundles(sequence<UTF8String> aLocales, sequence<L10nResourceId> aResourceIds);
179};
180