@backstage/core-app-api 1.10.0-next.3 → 1.10.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,24 @@
1
1
  # @backstage/core-app-api
2
2
 
3
+ ## 1.10.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 18619f793c94: Fixed two bugs in how the `OAuth2Session` type represents the underlying data. The `expiresAt` and `backstageIdentity` are now both optional, since that's what they are in practice. This is not considered a breaking change since it was effectively a bug in the modelling of the state that this type represents, and the type was not used in any other external contract.
8
+ - 18619f793c94: The `OAuth` class which is used by all OAuth providers will now consider both the session expiration of both the Backstage identity as well as the upstream identity provider, and refresh the session with either of them is about to expire.
9
+ - 6e30769cc627: Introduced experimental support for internationalization.
10
+
11
+ ### Patch Changes
12
+
13
+ - 406b786a2a2c: Mark package as being free of side effects, allowing more optimized Webpack builds.
14
+ - 9fe827b380e1: Internal refactor
15
+ - 8cec7664e146: Removed `@types/node` dependency
16
+ - Updated dependencies
17
+ - @backstage/config@1.1.0
18
+ - @backstage/core-plugin-api@1.6.0
19
+ - @backstage/types@1.1.1
20
+ - @backstage/version-bridge@1.0.5
21
+
3
22
  ## 1.10.0-next.3
4
23
 
5
24
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -6,7 +6,6 @@ import * as _backstage_types from '@backstage/types';
6
6
  import { Observable, JsonValue } from '@backstage/types';
7
7
  import { Config, AppConfig } from '@backstage/config';
8
8
  export { ConfigReader } from '@backstage/config';
9
- import { TranslationRef } from '@backstage/core-plugin-api/alpha';
10
9
 
11
10
  /**
12
11
  * Prop types for the ApiProvider component.
@@ -803,13 +802,6 @@ type TargetRouteMap<ExternalRoutes extends {
803
802
  type AppRouteBinder = <ExternalRoutes extends {
804
803
  [name: string]: ExternalRouteRef;
805
804
  }>(externalRoutes: ExternalRoutes, targetRoutes: PartialKeys<TargetRouteMap<ExternalRoutes>, KeysWithType<ExternalRoutes, ExternalRouteRef<any, true>>>) => void;
806
- /**
807
- * TODO: To be remove when TranslationMessages in packages/core-app-api/src/app/TranslationResource.ts
808
- * come to be public
809
- *
810
- * @ignore
811
- * */
812
- type TranslationMessages<T> = T extends TranslationRef<infer R> ? Partial<R> : never;
813
805
  /**
814
806
  * The options accepted by {@link createSpecializedApp}.
815
807
  *
@@ -908,19 +900,17 @@ type AppOptions = {
908
900
  bindRoutes?(context: {
909
901
  bind: AppRouteBinder;
910
902
  }): void;
911
- /**
912
- * TODO: Change to ExperimentalI18n type when packages/core-app-api/src/apis/implementations/AppTranslationApi/AppTranslationImpl.ts
913
- * become to public
914
- */
915
- __experimentalI18n?: {
916
- supportedLanguages: string[];
917
- fallbackLanguage?: string | string[];
918
- messages?: Array<{
919
- ref: TranslationRef;
920
- messages?: Record<string, TranslationMessages<TranslationRef>>;
921
- lazyMessages: Record<string, () => Promise<{
922
- messages: TranslationMessages<TranslationRef>;
923
- }>>;
903
+ __experimentalTranslations?: {
904
+ defaultLanguage?: string;
905
+ availableLanguages?: string[];
906
+ resources?: Array<{
907
+ $$type: '@backstage/TranslationResource';
908
+ id: string;
909
+ } | {
910
+ $$type: '@backstage/TranslationMessages';
911
+ id: string;
912
+ full: boolean;
913
+ messages: Record<string, string>;
924
914
  }>;
925
915
  };
926
916
  };
package/dist/index.esm.js CHANGED
@@ -8,12 +8,9 @@ import { ConfigReader } from '@backstage/config';
8
8
  export { ConfigReader } from '@backstage/config';
9
9
  import { createRoutesFromChildren, Route, useLocation, matchRoutes, Routes, generatePath, useRoutes } from 'react-router-dom';
10
10
  import useAsync from 'react-use/lib/useAsync';
11
- import { appTranslationApiRef } from '@backstage/core-plugin-api/alpha';
11
+ import { appLanguageApiRef, translationApiRef } from '@backstage/core-plugin-api/alpha';
12
12
  import useObservable from 'react-use/lib/useObservable';
13
- import { I18nextProvider } from 'react-i18next';
14
- import { A as AppTranslationApiImpl } from './esm/AppTranslationImpl-8a2e981b.esm.js';
15
- import 'i18next';
16
- import 'i18next-browser-languagedetector';
13
+ import { createInstance } from 'i18next';
17
14
 
18
15
  var __defProp$l = Object.defineProperty;
19
16
  var __defNormalProp$l = (obj, key, value) => key in obj ? __defProp$l(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -1562,7 +1559,7 @@ var __publicField$8 = (obj, key, value) => {
1562
1559
  __defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
1563
1560
  return value;
1564
1561
  };
1565
- const STORAGE_KEY = "theme";
1562
+ const STORAGE_KEY$1 = "theme";
1566
1563
  class AppThemeSelector {
1567
1564
  constructor(themes) {
1568
1565
  this.themes = themes;
@@ -1575,19 +1572,19 @@ class AppThemeSelector {
1575
1572
  if (!window.localStorage) {
1576
1573
  return selector;
1577
1574
  }
1578
- const initialThemeId = (_a = window.localStorage.getItem(STORAGE_KEY)) != null ? _a : void 0;
1575
+ const initialThemeId = (_a = window.localStorage.getItem(STORAGE_KEY$1)) != null ? _a : void 0;
1579
1576
  selector.setActiveThemeId(initialThemeId);
1580
1577
  selector.activeThemeId$().subscribe((themeId) => {
1581
1578
  if (themeId) {
1582
- window.localStorage.setItem(STORAGE_KEY, themeId);
1579
+ window.localStorage.setItem(STORAGE_KEY$1, themeId);
1583
1580
  } else {
1584
- window.localStorage.removeItem(STORAGE_KEY);
1581
+ window.localStorage.removeItem(STORAGE_KEY$1);
1585
1582
  }
1586
1583
  });
1587
1584
  window.addEventListener("storage", (event) => {
1588
1585
  var _a2;
1589
- if (event.key === STORAGE_KEY) {
1590
- const themeId = (_a2 = localStorage.getItem(STORAGE_KEY)) != null ? _a2 : void 0;
1586
+ if (event.key === STORAGE_KEY$1) {
1587
+ const themeId = (_a2 = localStorage.getItem(STORAGE_KEY$1)) != null ? _a2 : void 0;
1591
1588
  selector.setActiveThemeId(themeId);
1592
1589
  }
1593
1590
  });
@@ -3185,11 +3182,407 @@ function resolveRouteBindings(bindRoutes) {
3185
3182
  return result;
3186
3183
  }
3187
3184
 
3188
- function AppTranslationProvider({ children }) {
3189
- const appTranslationAPi = useApi(appTranslationApiRef);
3190
- const i18n = appTranslationAPi.getI18n();
3191
- return /* @__PURE__ */ React.createElement(I18nextProvider, { i18n }, children);
3185
+ var __accessCheck$2 = (obj, member, msg) => {
3186
+ if (!member.has(obj))
3187
+ throw TypeError("Cannot " + msg);
3188
+ };
3189
+ var __privateGet$2 = (obj, member, getter) => {
3190
+ __accessCheck$2(obj, member, "read from private field");
3191
+ return getter ? getter.call(obj) : member.get(obj);
3192
+ };
3193
+ var __privateAdd$2 = (obj, member, value) => {
3194
+ if (member.has(obj))
3195
+ throw TypeError("Cannot add the same private member more than once");
3196
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
3197
+ };
3198
+ var __privateSet$2 = (obj, member, value, setter) => {
3199
+ __accessCheck$2(obj, member, "write to private field");
3200
+ setter ? setter.call(obj, value) : member.set(obj, value);
3201
+ return value;
3202
+ };
3203
+ var _languages, _language$1, _subject;
3204
+ const STORAGE_KEY = "language";
3205
+ const DEFAULT_LANGUAGE = "en";
3206
+ const _AppLanguageSelector = class _AppLanguageSelector {
3207
+ constructor(languages, initialLanguage) {
3208
+ __privateAdd$2(this, _languages, void 0);
3209
+ __privateAdd$2(this, _language$1, void 0);
3210
+ __privateAdd$2(this, _subject, void 0);
3211
+ __privateSet$2(this, _languages, languages);
3212
+ __privateSet$2(this, _language$1, initialLanguage);
3213
+ __privateSet$2(this, _subject, new BehaviorSubject({
3214
+ language: __privateGet$2(this, _language$1)
3215
+ }));
3216
+ }
3217
+ static create(options) {
3218
+ var _a, _b;
3219
+ const languages = (_a = options == null ? void 0 : options.availableLanguages) != null ? _a : [DEFAULT_LANGUAGE];
3220
+ if (languages.length !== new Set(languages).size) {
3221
+ throw new Error(
3222
+ `Supported languages may not contain duplicates, got '${languages.join(
3223
+ "', '"
3224
+ )}'`
3225
+ );
3226
+ }
3227
+ if (!languages.includes(DEFAULT_LANGUAGE)) {
3228
+ throw new Error(`Supported languages must include '${DEFAULT_LANGUAGE}'`);
3229
+ }
3230
+ const initialLanguage = (_b = options == null ? void 0 : options.defaultLanguage) != null ? _b : DEFAULT_LANGUAGE;
3231
+ if (!languages.includes(initialLanguage)) {
3232
+ throw new Error(
3233
+ `Initial language must be one of the supported languages, got '${initialLanguage}'`
3234
+ );
3235
+ }
3236
+ return new _AppLanguageSelector(languages, initialLanguage);
3237
+ }
3238
+ static createWithStorage(options) {
3239
+ const selector = _AppLanguageSelector.create(options);
3240
+ if (!window.localStorage) {
3241
+ return selector;
3242
+ }
3243
+ const storedLanguage = window.localStorage.getItem(STORAGE_KEY);
3244
+ const { languages } = selector.getAvailableLanguages();
3245
+ if (storedLanguage && languages.includes(storedLanguage)) {
3246
+ selector.setLanguage(storedLanguage);
3247
+ }
3248
+ selector.language$().subscribe(({ language }) => {
3249
+ if (language !== window.localStorage.getItem(STORAGE_KEY)) {
3250
+ window.localStorage.setItem(STORAGE_KEY, language);
3251
+ }
3252
+ });
3253
+ window.addEventListener("storage", (event) => {
3254
+ var _a;
3255
+ if (event.key === STORAGE_KEY) {
3256
+ const language = (_a = localStorage.getItem(STORAGE_KEY)) != null ? _a : void 0;
3257
+ if (language) {
3258
+ selector.setLanguage(language);
3259
+ }
3260
+ }
3261
+ });
3262
+ return selector;
3263
+ }
3264
+ getAvailableLanguages() {
3265
+ return { languages: __privateGet$2(this, _languages).slice() };
3266
+ }
3267
+ setLanguage(language) {
3268
+ const lng = language != null ? language : DEFAULT_LANGUAGE;
3269
+ if (lng === __privateGet$2(this, _language$1)) {
3270
+ return;
3271
+ }
3272
+ if (lng && !__privateGet$2(this, _languages).includes(lng)) {
3273
+ throw new Error(
3274
+ `Failed to change language to '${lng}', available languages are '${__privateGet$2(this, _languages).join(
3275
+ "', '"
3276
+ )}'`
3277
+ );
3278
+ }
3279
+ __privateSet$2(this, _language$1, lng);
3280
+ __privateGet$2(this, _subject).next({ language: lng });
3281
+ }
3282
+ getLanguage() {
3283
+ return { language: __privateGet$2(this, _language$1) };
3284
+ }
3285
+ language$() {
3286
+ return __privateGet$2(this, _subject);
3287
+ }
3288
+ };
3289
+ _languages = new WeakMap();
3290
+ _language$1 = new WeakMap();
3291
+ _subject = new WeakMap();
3292
+ let AppLanguageSelector = _AppLanguageSelector;
3293
+
3294
+ function toInternalTranslationResource(resource) {
3295
+ const r = resource;
3296
+ if (r.$$type !== "@backstage/TranslationResource") {
3297
+ throw new Error(`Invalid translation resource, bad type '${r.$$type}'`);
3298
+ }
3299
+ if (r.version !== "v1") {
3300
+ throw new Error(`Invalid translation resource, bad version '${r.version}'`);
3301
+ }
3302
+ return r;
3303
+ }
3304
+
3305
+ function toInternalTranslationRef(ref) {
3306
+ const r = ref;
3307
+ if (r.$$type !== "@backstage/TranslationRef") {
3308
+ throw new Error(`Invalid translation ref, bad type '${r.$$type}'`);
3309
+ }
3310
+ if (r.version !== "v1") {
3311
+ throw new Error(`Invalid translation ref, bad version '${r.version}'`);
3312
+ }
3313
+ return r;
3314
+ }
3315
+
3316
+ var __accessCheck$1 = (obj, member, msg) => {
3317
+ if (!member.has(obj))
3318
+ throw TypeError("Cannot " + msg);
3319
+ };
3320
+ var __privateGet$1 = (obj, member, getter) => {
3321
+ __accessCheck$1(obj, member, "read from private field");
3322
+ return getter ? getter.call(obj) : member.get(obj);
3323
+ };
3324
+ var __privateAdd$1 = (obj, member, value) => {
3325
+ if (member.has(obj))
3326
+ throw TypeError("Cannot add the same private member more than once");
3327
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
3328
+ };
3329
+ var __privateSet$1 = (obj, member, value, setter) => {
3330
+ __accessCheck$1(obj, member, "write to private field");
3331
+ setter ? setter.call(obj, value) : member.set(obj, value);
3332
+ return value;
3333
+ };
3334
+ var __privateMethod = (obj, member, method) => {
3335
+ __accessCheck$1(obj, member, "access private method");
3336
+ return method;
3337
+ };
3338
+ var _loaded, _loading, _loaders, _getLoaderKey, getLoaderKey_fn, _i18n, _loader, _language, _registeredRefs, _languageChangeListeners, _changeLanguage, changeLanguage_fn, _createSnapshot, createSnapshot_fn, _registerDefaults, registerDefaults_fn;
3339
+ function removeNulls(messages) {
3340
+ return Object.fromEntries(
3341
+ Object.entries(messages).filter(
3342
+ (e) => e[1] !== null
3343
+ )
3344
+ );
3192
3345
  }
3346
+ class ResourceLoader {
3347
+ constructor(onLoad) {
3348
+ this.onLoad = onLoad;
3349
+ __privateAdd$1(this, _getLoaderKey);
3350
+ /** Loaded resources by loader key */
3351
+ __privateAdd$1(this, _loaded, /* @__PURE__ */ new Set());
3352
+ /** Resource loading promises by loader key */
3353
+ __privateAdd$1(this, _loading, /* @__PURE__ */ new Map());
3354
+ /** Loaders for each resource language */
3355
+ __privateAdd$1(this, _loaders, /* @__PURE__ */ new Map());
3356
+ }
3357
+ addTranslationResource(resource) {
3358
+ const internalResource = toInternalTranslationResource(resource);
3359
+ for (const entry of internalResource.resources) {
3360
+ const key = __privateMethod(this, _getLoaderKey, getLoaderKey_fn).call(this, entry.language, internalResource.id);
3361
+ if (!__privateGet$1(this, _loaders).has(key)) {
3362
+ __privateGet$1(this, _loaders).set(key, entry.loader);
3363
+ }
3364
+ }
3365
+ }
3366
+ needsLoading(language, namespace) {
3367
+ const key = __privateMethod(this, _getLoaderKey, getLoaderKey_fn).call(this, language, namespace);
3368
+ const loader = __privateGet$1(this, _loaders).get(key);
3369
+ if (!loader) {
3370
+ return false;
3371
+ }
3372
+ return !__privateGet$1(this, _loaded).has(key);
3373
+ }
3374
+ async load(language, namespace) {
3375
+ const key = __privateMethod(this, _getLoaderKey, getLoaderKey_fn).call(this, language, namespace);
3376
+ const loader = __privateGet$1(this, _loaders).get(key);
3377
+ if (!loader) {
3378
+ return;
3379
+ }
3380
+ if (__privateGet$1(this, _loaded).has(key)) {
3381
+ return;
3382
+ }
3383
+ const loading = __privateGet$1(this, _loading).get(key);
3384
+ if (loading) {
3385
+ await loading;
3386
+ return;
3387
+ }
3388
+ const load = loader().then(
3389
+ (result) => {
3390
+ this.onLoad({ language, namespace, messages: result.messages });
3391
+ __privateGet$1(this, _loaded).add(key);
3392
+ },
3393
+ (error) => {
3394
+ __privateGet$1(this, _loaded).add(key);
3395
+ throw error;
3396
+ }
3397
+ );
3398
+ __privateGet$1(this, _loading).set(key, load);
3399
+ await load;
3400
+ }
3401
+ }
3402
+ _loaded = new WeakMap();
3403
+ _loading = new WeakMap();
3404
+ _loaders = new WeakMap();
3405
+ _getLoaderKey = new WeakSet();
3406
+ getLoaderKey_fn = function(language, namespace) {
3407
+ return `${language}/${namespace}`;
3408
+ };
3409
+ const _I18nextTranslationApi = class _I18nextTranslationApi {
3410
+ constructor(i18n, loader, language) {
3411
+ __privateAdd$1(this, _changeLanguage);
3412
+ __privateAdd$1(this, _createSnapshot);
3413
+ __privateAdd$1(this, _registerDefaults);
3414
+ __privateAdd$1(this, _i18n, void 0);
3415
+ __privateAdd$1(this, _loader, void 0);
3416
+ __privateAdd$1(this, _language, void 0);
3417
+ /** Keep track of which refs we have registered default resources for */
3418
+ __privateAdd$1(this, _registeredRefs, /* @__PURE__ */ new Set());
3419
+ /** Notify observers when language changes */
3420
+ __privateAdd$1(this, _languageChangeListeners, /* @__PURE__ */ new Set());
3421
+ __privateSet$1(this, _i18n, i18n);
3422
+ __privateSet$1(this, _loader, loader);
3423
+ __privateSet$1(this, _language, language);
3424
+ }
3425
+ static create(options) {
3426
+ const { languages } = options.languageApi.getAvailableLanguages();
3427
+ const i18n = createInstance({
3428
+ fallbackLng: DEFAULT_LANGUAGE,
3429
+ supportedLngs: languages,
3430
+ interpolation: {
3431
+ escapeValue: false
3432
+ },
3433
+ ns: [],
3434
+ defaultNS: false,
3435
+ fallbackNS: false,
3436
+ // Disable resource loading on init, meaning i18n will be ready to use immediately
3437
+ initImmediate: false
3438
+ });
3439
+ i18n.init();
3440
+ if (!i18n.isInitialized) {
3441
+ throw new Error("i18next was unexpectedly not initialized");
3442
+ }
3443
+ const { language: initialLanguage } = options.languageApi.getLanguage();
3444
+ if (initialLanguage !== DEFAULT_LANGUAGE) {
3445
+ i18n.changeLanguage(initialLanguage);
3446
+ }
3447
+ const loader = new ResourceLoader((loaded) => {
3448
+ i18n.addResourceBundle(
3449
+ loaded.language,
3450
+ loaded.namespace,
3451
+ removeNulls(loaded.messages),
3452
+ false,
3453
+ // do not merge with existing translations
3454
+ true
3455
+ // overwrite translations
3456
+ );
3457
+ });
3458
+ const resources = (options == null ? void 0 : options.resources) || [];
3459
+ for (let i = resources.length - 1; i >= 0; i--) {
3460
+ const resource = resources[i];
3461
+ if (resource.$$type === "@backstage/TranslationResource") {
3462
+ loader.addTranslationResource(resource);
3463
+ } else if (resource.$$type === "@backstage/TranslationMessages") {
3464
+ i18n.addResourceBundle(
3465
+ DEFAULT_LANGUAGE,
3466
+ resource.id,
3467
+ removeNulls(resource.messages),
3468
+ true,
3469
+ // merge with existing translations
3470
+ false
3471
+ // do not overwrite translations
3472
+ );
3473
+ }
3474
+ }
3475
+ const instance = new _I18nextTranslationApi(
3476
+ i18n,
3477
+ loader,
3478
+ options.languageApi.getLanguage().language
3479
+ );
3480
+ options.languageApi.language$().subscribe(({ language }) => {
3481
+ var _a;
3482
+ __privateMethod(_a = instance, _changeLanguage, changeLanguage_fn).call(_a, language);
3483
+ });
3484
+ return instance;
3485
+ }
3486
+ getTranslation(translationRef) {
3487
+ const internalRef = toInternalTranslationRef(translationRef);
3488
+ __privateMethod(this, _registerDefaults, registerDefaults_fn).call(this, internalRef);
3489
+ return __privateMethod(this, _createSnapshot, createSnapshot_fn).call(this, internalRef);
3490
+ }
3491
+ translation$(translationRef) {
3492
+ const internalRef = toInternalTranslationRef(translationRef);
3493
+ __privateMethod(this, _registerDefaults, registerDefaults_fn).call(this, internalRef);
3494
+ return new ObservableImpl((subscriber) => {
3495
+ let loadTicket = {};
3496
+ let lastSnapshotWasReady = false;
3497
+ const loadResource = () => {
3498
+ loadTicket = {};
3499
+ const ticket = loadTicket;
3500
+ __privateGet$1(this, _loader).load(__privateGet$1(this, _language), internalRef.id).then(
3501
+ () => {
3502
+ if (ticket === loadTicket) {
3503
+ const snapshot = __privateMethod(this, _createSnapshot, createSnapshot_fn).call(this, internalRef);
3504
+ if (snapshot.ready || lastSnapshotWasReady) {
3505
+ lastSnapshotWasReady = snapshot.ready;
3506
+ subscriber.next(snapshot);
3507
+ }
3508
+ }
3509
+ },
3510
+ (error) => {
3511
+ if (ticket === loadTicket) {
3512
+ subscriber.error(Array.isArray(error) ? error[0] : error);
3513
+ }
3514
+ }
3515
+ );
3516
+ };
3517
+ const onChange = () => {
3518
+ const snapshot = __privateMethod(this, _createSnapshot, createSnapshot_fn).call(this, internalRef);
3519
+ if (lastSnapshotWasReady && !snapshot.ready) {
3520
+ lastSnapshotWasReady = snapshot.ready;
3521
+ subscriber.next(snapshot);
3522
+ }
3523
+ if (!snapshot.ready) {
3524
+ loadResource();
3525
+ }
3526
+ };
3527
+ if (__privateGet$1(this, _loader).needsLoading(__privateGet$1(this, _language), internalRef.id)) {
3528
+ loadResource();
3529
+ }
3530
+ __privateGet$1(this, _languageChangeListeners).add(onChange);
3531
+ return () => {
3532
+ __privateGet$1(this, _languageChangeListeners).delete(onChange);
3533
+ };
3534
+ });
3535
+ }
3536
+ };
3537
+ _i18n = new WeakMap();
3538
+ _loader = new WeakMap();
3539
+ _language = new WeakMap();
3540
+ _registeredRefs = new WeakMap();
3541
+ _languageChangeListeners = new WeakMap();
3542
+ _changeLanguage = new WeakSet();
3543
+ changeLanguage_fn = function(language) {
3544
+ if (__privateGet$1(this, _language) !== language) {
3545
+ __privateSet$1(this, _language, language);
3546
+ __privateGet$1(this, _i18n).changeLanguage(language);
3547
+ __privateGet$1(this, _languageChangeListeners).forEach((listener) => listener());
3548
+ }
3549
+ };
3550
+ _createSnapshot = new WeakSet();
3551
+ createSnapshot_fn = function(internalRef) {
3552
+ if (__privateGet$1(this, _loader).needsLoading(__privateGet$1(this, _language), internalRef.id)) {
3553
+ return { ready: false };
3554
+ }
3555
+ const t = __privateGet$1(this, _i18n).getFixedT(
3556
+ null,
3557
+ internalRef.id
3558
+ );
3559
+ return {
3560
+ ready: true,
3561
+ t
3562
+ };
3563
+ };
3564
+ _registerDefaults = new WeakSet();
3565
+ registerDefaults_fn = function(internalRef) {
3566
+ if (__privateGet$1(this, _registeredRefs).has(internalRef.id)) {
3567
+ return;
3568
+ }
3569
+ __privateGet$1(this, _registeredRefs).add(internalRef.id);
3570
+ const defaultMessages = internalRef.getDefaultMessages();
3571
+ __privateGet$1(this, _i18n).addResourceBundle(
3572
+ DEFAULT_LANGUAGE,
3573
+ internalRef.id,
3574
+ defaultMessages,
3575
+ true,
3576
+ // merge with existing translations
3577
+ false
3578
+ // do not overwrite translations
3579
+ );
3580
+ const defaultResource = internalRef.getDefaultResource();
3581
+ if (defaultResource) {
3582
+ __privateGet$1(this, _loader).addTranslationResource(defaultResource);
3583
+ }
3584
+ };
3585
+ let I18nextTranslationApi = _I18nextTranslationApi;
3193
3586
 
3194
3587
  function createLocalBaseUrl(fullUrl) {
3195
3588
  const url = new URL(fullUrl);
@@ -3315,11 +3708,12 @@ class AppManager {
3315
3708
  __publicField(this, "configLoader");
3316
3709
  __publicField(this, "defaultApis");
3317
3710
  __publicField(this, "bindRoutes");
3318
- __publicField(this, "appTranslationApi");
3711
+ __publicField(this, "appLanguageApi");
3712
+ __publicField(this, "translationResources");
3319
3713
  __publicField(this, "appIdentityProxy", new AppIdentityProxy());
3320
3714
  __publicField(this, "apiFactoryRegistry");
3321
3715
  __privateAdd(this, _getProviderCalled, false);
3322
- var _a, _b, _c, _d, _e;
3716
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
3323
3717
  this.apis = (_a = options.apis) != null ? _a : [];
3324
3718
  this.icons = options.icons;
3325
3719
  this.plugins = new Set((_b = options.plugins) != null ? _b : []);
@@ -3330,9 +3724,11 @@ class AppManager {
3330
3724
  this.defaultApis = (_e = options.defaultApis) != null ? _e : [];
3331
3725
  this.bindRoutes = options.bindRoutes;
3332
3726
  this.apiFactoryRegistry = new ApiFactoryRegistry();
3333
- this.appTranslationApi = AppTranslationApiImpl.create(
3334
- options.__experimentalI18n
3335
- );
3727
+ this.appLanguageApi = AppLanguageSelector.createWithStorage({
3728
+ defaultLanguage: (_f = options.__experimentalTranslations) == null ? void 0 : _f.defaultLanguage,
3729
+ availableLanguages: (_g = options.__experimentalTranslations) == null ? void 0 : _g.availableLanguages
3730
+ });
3731
+ this.translationResources = (_i = (_h = options.__experimentalTranslations) == null ? void 0 : _h.resources) != null ? _i : [];
3336
3732
  }
3337
3733
  getPlugins() {
3338
3734
  return Array.from(this.plugins);
@@ -3446,7 +3842,7 @@ class AppManager {
3446
3842
  }
3447
3843
  }
3448
3844
  const { ThemeProvider = AppThemeProvider } = this.components;
3449
- return /* @__PURE__ */ React.createElement(ApiProvider, { apis: this.getApiHolder() }, /* @__PURE__ */ React.createElement(AppContextProvider, { appContext }, /* @__PURE__ */ React.createElement(AppTranslationProvider, null, /* @__PURE__ */ React.createElement(ThemeProvider, null, /* @__PURE__ */ React.createElement(
3845
+ return /* @__PURE__ */ React.createElement(ApiProvider, { apis: this.getApiHolder() }, /* @__PURE__ */ React.createElement(AppContextProvider, { appContext }, /* @__PURE__ */ React.createElement(ThemeProvider, null, /* @__PURE__ */ React.createElement(
3450
3846
  RoutingProvider,
3451
3847
  {
3452
3848
  routePaths: routing.paths,
@@ -3465,7 +3861,7 @@ class AppManager {
3465
3861
  },
3466
3862
  children
3467
3863
  )
3468
- )))));
3864
+ ))));
3469
3865
  };
3470
3866
  return Provider;
3471
3867
  }
@@ -3510,9 +3906,17 @@ class AppManager {
3510
3906
  factory: () => this.appIdentityProxy
3511
3907
  });
3512
3908
  this.apiFactoryRegistry.register("static", {
3513
- api: appTranslationApiRef,
3909
+ api: appLanguageApiRef,
3514
3910
  deps: {},
3515
- factory: () => this.appTranslationApi
3911
+ factory: () => this.appLanguageApi
3912
+ });
3913
+ this.apiFactoryRegistry.register("default", {
3914
+ api: translationApiRef,
3915
+ deps: { languageApi: appLanguageApiRef },
3916
+ factory: ({ languageApi }) => I18nextTranslationApi.create({
3917
+ languageApi,
3918
+ resources: this.translationResources
3919
+ })
3516
3920
  });
3517
3921
  this.apiFactoryRegistry.register("default", {
3518
3922
  api: featureFlagsApiRef,