@backstage/core-plugin-api 1.6.0-next.3 → 1.7.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # @backstage/core-plugin-api
2
2
 
3
+ ## 1.7.0-next.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 322bbcae24: Removed the exprimental plugin configuration API. The `__experimentalReconfigure()` from the plugin options as well as the `__experimentalConfigure()` method on plugin instances have both been removed.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies
12
+ - @backstage/config@1.1.0
13
+ - @backstage/types@1.1.1
14
+ - @backstage/version-bridge@1.0.5
15
+
16
+ ## 1.6.0
17
+
18
+ ### Minor Changes
19
+
20
+ - 18619f793c94: Added the optional `expiresAt` field that may now be part of a `BackstageIdentityResponse`.
21
+ - 6e30769cc627: Introduced experimental support for internationalization.
22
+
23
+ ### Patch Changes
24
+
25
+ - 406b786a2a2c: Mark package as being free of side effects, allowing more optimized Webpack builds.
26
+ - 8cec7664e146: Removed `@types/node` dependency
27
+ - Updated dependencies
28
+ - @backstage/config@1.1.0
29
+ - @backstage/types@1.1.1
30
+ - @backstage/version-bridge@1.0.5
31
+
3
32
  ## 1.6.0-next.3
4
33
 
5
34
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/core-plugin-api",
3
- "version": "1.6.0-next.3",
3
+ "version": "1.7.0-next.0",
4
4
  "main": "../dist/alpha.esm.js",
5
5
  "module": "../dist/alpha.esm.js",
6
6
  "types": "../dist/alpha.d.ts"
package/dist/alpha.d.ts CHANGED
@@ -1,78 +1,394 @@
1
- import { BackstagePlugin, ApiRef } from '@backstage/core-plugin-api';
2
- import { ReactNode } from 'react';
3
- import { i18n } from 'i18next';
1
+ import { TranslationRef as TranslationRef$1, TranslationMessages as TranslationMessages$1 } from '@backstage/core-plugin-api/alpha';
2
+ import { ApiRef } from '@backstage/core-plugin-api';
3
+ import { Observable } from '@backstage/types';
4
4
 
5
5
  /**
6
- * Properties for the PluginProvider component.
6
+ * Represents a collection of messages to be provided for a given translation ref.
7
7
  *
8
8
  * @alpha
9
+ * @remarks
10
+ *
11
+ * This collection of messages can either be used directly as an override for the
12
+ * default messages, or it can be used to provide translations for a language by
13
+ * by being referenced by a {@link TranslationResource}.
9
14
  */
10
- interface PluginOptionsProviderProps {
11
- children: ReactNode;
12
- plugin?: BackstagePlugin;
15
+ interface TranslationMessages<TId extends string = string, TMessages extends {
16
+ [key in string]: string;
17
+ } = {
18
+ [key in string]: string;
19
+ }, TFull extends boolean = boolean> {
20
+ $$type: '@backstage/TranslationMessages';
21
+ /** The ID of the translation ref that these messages are for */
22
+ id: TId;
23
+ /** Whether or not these messages override all known messages */
24
+ full: TFull;
25
+ /** The messages provided for the given translation ref */
26
+ messages: TMessages;
13
27
  }
14
28
  /**
15
- * Contains the plugin configuration.
29
+ * Options for {@link createTranslationMessages}.
16
30
  *
17
31
  * @alpha
18
32
  */
19
- declare const PluginProvider: (props: PluginOptionsProviderProps) => JSX.Element;
33
+ interface TranslationMessagesOptions<TId extends string, TMessages extends {
34
+ [key in string]: string;
35
+ }, TFull extends boolean> {
36
+ ref: TranslationRef$1<TId, TMessages>;
37
+ full?: TFull;
38
+ messages: false extends TFull ? {
39
+ [key in keyof TMessages]?: string | null;
40
+ } : {
41
+ [key in keyof TMessages]: string | null;
42
+ };
43
+ }
20
44
  /**
21
- * Grab the current entity from the context, throws if the entity has not yet been loaded
22
- * or is not available.
45
+ * Creates a collection of messages for a given translation ref.
23
46
  *
24
47
  * @alpha
25
48
  */
26
- declare function usePluginOptions<TPluginOptions extends {} = {}>(): TPluginOptions;
49
+ declare function createTranslationMessages<TId extends string, TMessages extends {
50
+ [key in string]: string;
51
+ }, TFull extends boolean>(options: TranslationMessagesOptions<TId, TMessages, TFull>): TranslationMessages<TId, TMessages, TFull>;
27
52
 
28
53
  /** @alpha */
29
- interface TranslationRefConfig<Messages extends Record<keyof Messages, string>> {
30
- id: string;
31
- messages: Messages;
32
- lazyResources?: Record<string, () => Promise<{
33
- messages: Messages;
34
- }>>;
35
- resources?: Record<string, Messages>;
54
+ interface TranslationResource<TId extends string = string> {
55
+ $$type: '@backstage/TranslationResource';
56
+ id: TId;
36
57
  }
37
58
  /** @alpha */
38
- interface TranslationRef<Messages extends Record<keyof Messages, string> = Record<string, string>> {
39
- getId(): string;
40
- getDefaultMessages(): Messages;
41
- getResources(): Record<string, Messages> | undefined;
42
- getLazyResources(): Record<string, () => Promise<{
43
- messages: Messages;
44
- }>> | undefined;
59
+ interface TranslationResourceOptions<TId extends string, TMessages extends {
60
+ [key in string]: string;
61
+ }, TTranslations extends {
62
+ [language in string]: () => Promise<{
63
+ default: TranslationMessages$1<TId> | {
64
+ [key in keyof TMessages]: string | null;
65
+ };
66
+ }>;
67
+ }> {
68
+ ref: TranslationRef$1<TId, TMessages>;
69
+ translations: TTranslations;
45
70
  }
46
71
  /** @alpha */
47
- type TranslationOptions<Messages extends Record<keyof Messages, string> = Record<string, string>> = Messages;
72
+ declare function createTranslationResource<TId extends string, TMessages extends {
73
+ [key in string]: string;
74
+ }, TTranslations extends {
75
+ [language in string]: () => Promise<{
76
+ default: TranslationMessages$1<TId> | {
77
+ [key in keyof TMessages]: string | null;
78
+ };
79
+ }>;
80
+ }>(options: TranslationResourceOptions<TId, TMessages, TTranslations>): TranslationResource<TId>;
48
81
 
49
82
  /** @alpha */
50
- declare class TranslationRefImpl<Messages extends Record<keyof Messages, string>> implements TranslationRef<Messages> {
51
- private readonly config;
52
- static create<Messages extends Record<keyof Messages, string>>(config: TranslationRefConfig<Messages>): TranslationRefImpl<Messages>;
53
- getId(): string;
54
- getDefaultMessages(): Messages;
55
- getLazyResources(): Record<string, () => Promise<{
56
- messages: Messages;
57
- }>> | undefined;
58
- getResources(): Record<string, Messages> | undefined;
59
- toString(): string;
60
- private constructor();
83
+ interface TranslationRef<TId extends string = string, TMessages extends {
84
+ [key in string]: string;
85
+ } = {
86
+ [key in string]: string;
87
+ }> {
88
+ $$type: '@backstage/TranslationRef';
89
+ id: TId;
90
+ T: TMessages;
91
+ }
92
+ /** @alpha */
93
+ interface TranslationRefOptions<TId extends string, TMessages extends {
94
+ [key in string]: string;
95
+ }, TTranslations extends {
96
+ [language in string]: () => Promise<{
97
+ default: {
98
+ [key in keyof TMessages]: string | null;
99
+ };
100
+ }>;
101
+ }> {
102
+ id: TId;
103
+ messages: TMessages;
104
+ translations?: TTranslations;
61
105
  }
62
106
  /** @alpha */
63
- declare const createTranslationRef: <Messages extends Record<keyof Messages, string> = {}>(config: TranslationRefConfig<Messages>) => TranslationRef<Messages>;
107
+ declare function createTranslationRef<TId extends string, const TMessages extends {
108
+ [key in string]: string;
109
+ }, TTranslations extends {
110
+ [language in string]: () => Promise<{
111
+ default: {
112
+ [key in keyof TMessages]: string | null;
113
+ };
114
+ }>;
115
+ }>(config: TranslationRefOptions<TId, TMessages, TTranslations>): TranslationRef<TId, TMessages>;
64
116
 
117
+ /**
118
+ * Base translation options.
119
+ *
120
+ * @alpha
121
+ */
122
+ interface BaseOptions {
123
+ interpolation?: {
124
+ /** Whether to HTML escape provided values, defaults to false */
125
+ escapeValue?: boolean;
126
+ };
127
+ }
128
+ /**
129
+ * All pluralization suffixes supported by i18next
130
+ *
131
+ * @ignore
132
+ */
133
+ type TranslationPlural = 'zero' | 'one' | 'two' | 'few' | 'many' | 'other';
134
+ /**
135
+ * A mapping of i18n formatting types to their corresponding types and options.
136
+ * @ignore
137
+ */
138
+ type I18nextFormatMap = {
139
+ number: {
140
+ type: number;
141
+ options: Intl.NumberFormatOptions;
142
+ };
143
+ currency: {
144
+ type: number;
145
+ options: Intl.NumberFormatOptions;
146
+ };
147
+ datetime: {
148
+ type: Date;
149
+ options: Intl.DateTimeFormatOptions;
150
+ };
151
+ relativetime: {
152
+ type: number;
153
+ options: {
154
+ range?: Intl.RelativeTimeFormatUnit;
155
+ } & Intl.RelativeTimeFormatOptions;
156
+ };
157
+ list: {
158
+ type: string[];
159
+ options: Intl.ListFormatOptions;
160
+ };
161
+ };
162
+ /**
163
+ * Extracts all pluralized keys from the message map.
164
+ *
165
+ * @example
166
+ * ```
167
+ * { foo: 'foo', bar_one: 'bar', bar_other: 'bars' } -> 'bar'
168
+ * ```
169
+ *
170
+ * @ignore
171
+ */
172
+ type PluralKeys<TMessages extends {
173
+ [key in string]: string;
174
+ }> = {
175
+ [Key in keyof TMessages]: Key extends `${infer K}_${TranslationPlural}` ? K : never;
176
+ }[keyof TMessages];
177
+ /**
178
+ * Collapses a message map into normalized keys with union values.
179
+ *
180
+ * @example
181
+ * ```
182
+ * { foo_one: 'foo', foo_other: 'foos' } -> { foo: 'foo' | 'foos' }
183
+ * ```
184
+ *
185
+ * @ignore
186
+ */
187
+ type CollapsedMessages<TMessages extends {
188
+ [key in string]: string;
189
+ }> = {
190
+ [key in keyof TMessages as key extends `${infer K}_${TranslationPlural}` ? K : key]: TMessages[key];
191
+ };
192
+ /**
193
+ * Helper type that expands type hints
194
+ *
195
+ * @ignore
196
+ */
197
+ type Expand<T> = T extends infer O ? {
198
+ [K in keyof O]: O[K];
199
+ } : never;
200
+ /**
201
+ * Helper type that expands type hints recursively
202
+ *
203
+ * @ignore
204
+ */
205
+ type ExpandRecursive<T> = T extends infer O ? {
206
+ [K in keyof O]: ExpandRecursive<O[K]>;
207
+ } : never;
208
+ /**
209
+ * Trim away whitespace
210
+ *
211
+ * @ignore
212
+ */
213
+ type Trim<T> = T extends ` ${infer U}` ? Trim<U> : T extends `${infer U} ` ? Trim<U> : T;
214
+ /**
215
+ * Extracts the key and format from a replacement string.
216
+ *
217
+ * @example
218
+ * ```
219
+ * 'foo, number' -> { foo: number }, 'foo' -> { foo: undefined }
220
+ * ```
221
+ */
222
+ type ExtractFormat<Replacement extends string> = Replacement extends `${infer Key},${infer FullFormat}` ? {
223
+ [key in Trim<Key>]: Lowercase<Trim<FullFormat extends `${infer Format}(${string})${string}` ? Format : FullFormat>>;
224
+ } : {
225
+ [key in Trim<Replacement>]: undefined;
226
+ };
227
+ /**
228
+ * Expand the keys in a flat map to nested objects.
229
+ *
230
+ * @example
231
+ * ```
232
+ * { 'a.b': 'foo', 'a.c': 'bar' } -> { a: { b: 'foo', c: 'bar' }
233
+ * ```
234
+ *
235
+ * @ignore
236
+ */
237
+ type ExpandKeys<TMap extends {}> = {
238
+ [Key in keyof TMap as Key extends `${infer Prefix}.${string}` ? Prefix : Key]: Key extends `${string}.${infer Rest}` ? ExpandKeys<{
239
+ [key in Rest]: TMap[Key];
240
+ }> : TMap[Key];
241
+ };
242
+ /**
243
+ * Extracts all option keys and their format from a message string.
244
+ *
245
+ * @example
246
+ * ```
247
+ * 'foo {{bar}} {{baz, number}}' -> { 'bar': undefined, 'baz': 'number' }
248
+ * ```
249
+ *
250
+ * @ignore
251
+ */
252
+ type ReplaceFormatsFromMessage<TMessage> = TMessage extends `${string}{{${infer Replacement}}}${infer Tail}` ? ExpandKeys<ExtractFormat<Replacement>> & ReplaceFormatsFromMessage<Tail> : {};
253
+ /**
254
+ * Generates the replace options structure
255
+ *
256
+ * @ignore
257
+ */
258
+ type ReplaceOptionsFromFormats<TFormats extends {}> = {
259
+ [Key in keyof TFormats]: TFormats[Key] extends keyof I18nextFormatMap ? I18nextFormatMap[TFormats[Key]]['type'] : TFormats[Key] extends {} ? Expand<ReplaceOptionsFromFormats<TFormats[Key]>> : string;
260
+ };
261
+ /**
262
+ * Generates the formatParams options structure
263
+ *
264
+ * @ignore
265
+ */
266
+ type ReplaceFormatParamsFromFormats<TFormats extends {}> = {
267
+ [Key in keyof TFormats]?: TFormats[Key] extends keyof I18nextFormatMap ? I18nextFormatMap[TFormats[Key]]['options'] : TFormats[Key] extends {} ? Expand<ReplaceFormatParamsFromFormats<TFormats[Key]>> : undefined;
268
+ };
269
+ /**
270
+ * Extracts all nesting keys from a message string.
271
+ *
272
+ * @example
273
+ * ```
274
+ * 'foo $t(bar) $t(baz)' -> 'bar' | 'baz'
275
+ * ```
276
+ *
277
+ * @ignore
278
+ */
279
+ type NestingKeysFromMessage<TMessage extends string> = TMessage extends `${string}$t(${infer Key})${infer Tail}` ? Trim<Key> | NestingKeysFromMessage<Tail> : never;
280
+ /**
281
+ * Find all referenced keys, given a starting key and the full set of messages.
282
+ *
283
+ * This will only discover keys up to 3 levels deep.
284
+ *
285
+ * @example
286
+ * ```
287
+ * <'x', { x: '$t(y) $t(z)', y: 'y', z: '$t(w)', w: 'w', foo: 'foo' }> -> 'x' | 'y' | 'z' | 'w'
288
+ * ```
289
+ *
290
+ * @ignore
291
+ */
292
+ type NestedMessageKeys<TKey extends keyof TMessages, TMessages extends {
293
+ [key in string]: string;
294
+ }> = TKey | NestedMessageKeys2<NestingKeysFromMessage<TMessages[TKey]>, TMessages>;
295
+ type NestedMessageKeys2<TKey extends keyof TMessages, TMessages extends {
296
+ [key in string]: string;
297
+ }> = TKey | NestedMessageKeys3<NestingKeysFromMessage<TMessages[TKey]>, TMessages>;
298
+ type NestedMessageKeys3<TKey extends keyof TMessages, TMessages extends {
299
+ [key in string]: string;
300
+ }> = TKey | NestingKeysFromMessage<TMessages[TKey]>;
301
+ /**
302
+ * Converts a union type to an intersection type.
303
+ *
304
+ * @example
305
+ * ```
306
+ * { foo: 'foo' } | { bar: 'bar' } -> { foo: 'foo' } & { bar: 'bar' }
307
+ * ```
308
+ *
309
+ * @ignore
310
+ */
311
+ type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
312
+ /**
313
+ * Collects different types of options into a single object
314
+ *
315
+ * @ignore
316
+ */
317
+ type CollectOptions<TCount extends {
318
+ count?: number;
319
+ }, TFormats extends {}> = TCount & (keyof Omit<TFormats, 'count'> extends never ? {} : (Expand<Omit<ReplaceOptionsFromFormats<TFormats>, 'count'>> | {
320
+ replace: Expand<Omit<ReplaceOptionsFromFormats<TFormats>, 'count'>>;
321
+ }) & {
322
+ formatParams?: Expand<ReplaceFormatParamsFromFormats<TFormats>>;
323
+ });
324
+ /**
325
+ * Helper type to only require options argument if needed
326
+ *
327
+ * @ignore
328
+ */
329
+ type OptionArgs<TOptions extends {}> = keyof TOptions extends never ? [options?: BaseOptions] : [options: BaseOptions & TOptions];
330
+ /**
331
+ * @ignore
332
+ */
333
+ type TranslationFunctionOptions<TKeys extends keyof TMessages, // All normalized message keys to be considered, i.e. included nested ones
334
+ TPluralKeys extends keyof TMessages, // All keys in the message map that are pluralized
335
+ TMessages extends {
336
+ [key in string]: string;
337
+ }> = OptionArgs<Expand<CollectOptions<TKeys & TPluralKeys extends never ? {} : {
338
+ count: number;
339
+ }, ExpandRecursive<UnionToIntersection<ReplaceFormatsFromMessage<TMessages[TKeys]>>>>>>;
65
340
  /** @alpha */
66
- declare const useTranslationRef: <Messages extends Record<keyof Messages, string>>(translationRef: TranslationRef<Messages>) => <Tkey extends keyof Messages>(key: Tkey, options?: TranslationOptions) => Messages[Tkey];
341
+ interface TranslationFunction<TMessages extends {
342
+ [key in string]: string;
343
+ }> {
344
+ <TKey extends keyof CollapsedMessages<TMessages>>(key: TKey, ...[args]: TranslationFunctionOptions<NestedMessageKeys<TKey, CollapsedMessages<TMessages>>, PluralKeys<TMessages>, CollapsedMessages<TMessages>>): CollapsedMessages<TMessages>[TKey];
345
+ }
346
+ /** @alpha */
347
+ type TranslationSnapshot<TMessages extends {
348
+ [key in string]: string;
349
+ }> = {
350
+ ready: false;
351
+ } | {
352
+ ready: true;
353
+ t: TranslationFunction<TMessages>;
354
+ };
355
+ /** @alpha */
356
+ type TranslationApi = {
357
+ getTranslation<TMessages extends {
358
+ [key in string]: string;
359
+ }>(translationRef: TranslationRef<string, TMessages>): TranslationSnapshot<TMessages>;
360
+ translation$<TMessages extends {
361
+ [key in string]: string;
362
+ }>(translationRef: TranslationRef<string, TMessages>): Observable<TranslationSnapshot<TMessages>>;
363
+ };
364
+ /**
365
+ * @alpha
366
+ */
367
+ declare const translationApiRef: ApiRef<TranslationApi>;
67
368
 
68
369
  /** @alpha */
69
- type AppTranslationApi = {
70
- getI18n(): i18n;
71
- addResourcesByRef<Messages extends Record<string, string>>(translationRef: TranslationRef<Messages>): void;
370
+ type AppLanguageApi = {
371
+ getAvailableLanguages(): {
372
+ languages: string[];
373
+ };
374
+ setLanguage(language?: string): void;
375
+ getLanguage(): {
376
+ language: string;
377
+ };
378
+ language$(): Observable<{
379
+ language: string;
380
+ }>;
72
381
  };
73
382
  /**
74
383
  * @alpha
75
384
  */
76
- declare const appTranslationApiRef: ApiRef<AppTranslationApi>;
385
+ declare const appLanguageApiRef: ApiRef<AppLanguageApi>;
386
+
387
+ /** @alpha */
388
+ declare const useTranslationRef: <TMessages extends {
389
+ [x: string]: string;
390
+ }>(translationRef: TranslationRef<string, TMessages>) => {
391
+ t: TranslationFunction<TMessages>;
392
+ };
77
393
 
78
- export { AppTranslationApi, PluginOptionsProviderProps, PluginProvider, TranslationOptions, TranslationRef, TranslationRefConfig, TranslationRefImpl, appTranslationApiRef, createTranslationRef, usePluginOptions, useTranslationRef };
394
+ export { AppLanguageApi, TranslationApi, TranslationFunction, TranslationMessages, TranslationMessagesOptions, TranslationRef, TranslationRefOptions, TranslationResource, TranslationResourceOptions, TranslationSnapshot, appLanguageApiRef, createTranslationMessages, createTranslationRef, createTranslationResource, translationApiRef, useTranslationRef };
package/dist/alpha.esm.js CHANGED
@@ -1,46 +1,178 @@
1
- import { u as useApi } from './esm/usePluginOptions-6dc02fab.esm.js';
2
- export { P as PluginProvider, y as usePluginOptions } from './esm/usePluginOptions-6dc02fab.esm.js';
3
- import { useTranslation } from 'react-i18next';
1
+ import { useState, useMemo, useCallback, useEffect, useRef } from 'react';
2
+ import { u as useApi, r as errorApiRef } from './esm/StorageApi-2de4f480.esm.js';
4
3
  import { createApiRef } from '@backstage/core-plugin-api';
5
- import 'react';
6
4
  import '@backstage/version-bridge';
7
5
 
6
+ function createTranslationMessages(options) {
7
+ return {
8
+ $$type: "@backstage/TranslationMessages",
9
+ id: options.ref.id,
10
+ full: Boolean(options.full),
11
+ messages: options.messages
12
+ };
13
+ }
14
+
15
+ function createTranslationResource(options) {
16
+ return {
17
+ $$type: "@backstage/TranslationResource",
18
+ version: "v1",
19
+ id: options.ref.id,
20
+ resources: Object.entries(options.translations).map(
21
+ ([language, loader]) => ({
22
+ language,
23
+ loader: () => loader().then((m) => {
24
+ const value = m.default;
25
+ return {
26
+ messages: (value == null ? void 0 : value.$$type) === "@backstage/TranslationMessages" ? value.messages : value
27
+ };
28
+ })
29
+ })
30
+ )
31
+ };
32
+ }
33
+
34
+ var __defProp = Object.defineProperty;
35
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
36
+ var __publicField = (obj, key, value) => {
37
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
38
+ return value;
39
+ };
40
+ var __accessCheck = (obj, member, msg) => {
41
+ if (!member.has(obj))
42
+ throw TypeError("Cannot " + msg);
43
+ };
44
+ var __privateGet = (obj, member, getter) => {
45
+ __accessCheck(obj, member, "read from private field");
46
+ return getter ? getter.call(obj) : member.get(obj);
47
+ };
48
+ var __privateAdd = (obj, member, value) => {
49
+ if (member.has(obj))
50
+ throw TypeError("Cannot add the same private member more than once");
51
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
52
+ };
53
+ var __privateSet = (obj, member, value, setter) => {
54
+ __accessCheck(obj, member, "write to private field");
55
+ setter ? setter.call(obj, value) : member.set(obj, value);
56
+ return value;
57
+ };
58
+ var _id, _messages, _resources;
8
59
  class TranslationRefImpl {
9
- constructor(config) {
10
- this.config = config;
60
+ constructor(options) {
61
+ __privateAdd(this, _id, void 0);
62
+ __privateAdd(this, _messages, void 0);
63
+ __privateAdd(this, _resources, void 0);
64
+ __publicField(this, "$$type", "@backstage/TranslationRef");
65
+ __publicField(this, "version", "v1");
66
+ __privateSet(this, _id, options.id);
67
+ __privateSet(this, _messages, options.messages);
11
68
  }
12
- static create(config) {
13
- return new TranslationRefImpl(config);
69
+ get id() {
70
+ return __privateGet(this, _id);
14
71
  }
15
- getId() {
16
- return this.config.id;
72
+ get T() {
73
+ throw new Error("Not implemented");
17
74
  }
18
75
  getDefaultMessages() {
19
- return this.config.messages;
76
+ return __privateGet(this, _messages);
20
77
  }
21
- getLazyResources() {
22
- return this.config.lazyResources;
78
+ setDefaultResource(resources) {
79
+ __privateSet(this, _resources, resources);
23
80
  }
24
- getResources() {
25
- return this.config.resources;
81
+ getDefaultResource() {
82
+ return __privateGet(this, _resources);
26
83
  }
27
84
  toString() {
28
- return `TranslationRef(${this.getId()})`;
85
+ return `TranslationRef{id=${this.id}}`;
86
+ }
87
+ }
88
+ _id = new WeakMap();
89
+ _messages = new WeakMap();
90
+ _resources = new WeakMap();
91
+ function createTranslationRef(config) {
92
+ const ref = new TranslationRefImpl(config);
93
+ if (config.translations) {
94
+ ref.setDefaultResource(
95
+ createTranslationResource({
96
+ ref,
97
+ translations: config.translations
98
+ })
99
+ );
29
100
  }
101
+ return ref;
30
102
  }
31
- const createTranslationRef = (config) => TranslationRefImpl.create(config);
32
103
 
33
- const appTranslationApiRef = createApiRef({
34
- id: "core.apptranslation"
104
+ const translationApiRef = createApiRef({
105
+ id: "core.translation"
35
106
  });
36
107
 
108
+ const appLanguageApiRef = createApiRef({
109
+ id: "core.applanguage"
110
+ });
111
+
112
+ const loggedRefs = /* @__PURE__ */ new WeakSet();
37
113
  const useTranslationRef = (translationRef) => {
38
- const appTranslationApi = useApi(appTranslationApiRef);
39
- appTranslationApi.addResourcesByRef(translationRef);
40
- const { t } = useTranslation(translationRef.getId());
41
- const defaulteMessage = translationRef.getDefaultMessages();
42
- return (key, options) => t(key, defaulteMessage[key], options);
114
+ const errorApi = useApi(errorApiRef);
115
+ const translationApi = useApi(translationApiRef);
116
+ const [snapshot, setSnapshot] = useState(
117
+ () => translationApi.getTranslation(translationRef)
118
+ );
119
+ const observable = useMemo(
120
+ () => translationApi.translation$(translationRef),
121
+ [translationApi, translationRef]
122
+ );
123
+ const onError = useCallback(
124
+ (error) => {
125
+ if (!loggedRefs.has(translationRef)) {
126
+ const errMsg = `Failed to load translation resource '${translationRef.id}'; caused by ${error}`;
127
+ console.error(errMsg);
128
+ errorApi.post(new Error(errMsg));
129
+ loggedRefs.add(translationRef);
130
+ }
131
+ },
132
+ [errorApi, translationRef]
133
+ );
134
+ useEffect(() => {
135
+ const subscription = observable.subscribe({
136
+ next(next) {
137
+ if (next.ready) {
138
+ setSnapshot(next);
139
+ }
140
+ },
141
+ error(error) {
142
+ onError(error);
143
+ }
144
+ });
145
+ return () => {
146
+ subscription.unsubscribe();
147
+ };
148
+ }, [observable, onError]);
149
+ const initialRenderRef = useRef(true);
150
+ useEffect(() => {
151
+ if (initialRenderRef.current) {
152
+ initialRenderRef.current = false;
153
+ } else {
154
+ setSnapshot(translationApi.getTranslation(translationRef));
155
+ }
156
+ }, [translationApi, translationRef]);
157
+ if (!snapshot.ready) {
158
+ throw new Promise((resolve) => {
159
+ const subscription = observable.subscribe({
160
+ next(next) {
161
+ if (next.ready) {
162
+ subscription.unsubscribe();
163
+ resolve();
164
+ }
165
+ },
166
+ error(error) {
167
+ subscription.unsubscribe();
168
+ onError(error);
169
+ resolve();
170
+ }
171
+ });
172
+ });
173
+ }
174
+ return { t: snapshot.t };
43
175
  };
44
176
 
45
- export { TranslationRefImpl, appTranslationApiRef, createTranslationRef, useTranslationRef };
177
+ export { appLanguageApiRef, createTranslationMessages, createTranslationRef, createTranslationResource, translationApiRef, useTranslationRef };
46
178
  //# sourceMappingURL=alpha.esm.js.map