Emby is Jellyfin's upstream ancestor and speaks a near-identical MediaBrowser
API, so the existing Jellyfin stack is parameterised by a `MediaBrowserDialect`
rather than forked. `JellyfinClient`, its auth service, endpoint discovery, LAN
discovery, and the add/edit connection screens all take the dialect and keep one
implementation; `MediaBackend.emby` and `ConnectionKind.emby` carry it through
the neutral models, the Drift `kind` discriminator, downloads, and caches.
Every divergence below was measured against a live Emby 4.9.5 server, not
inferred from documentation, and each is documented at its capability getter.
Jellyfin's request strings stay byte-identical so nothing about its behaviour
changes.
Routes and auth
- Emby only accepts the pre-10.9 user-scoped item routes (`/Users/{id}/Items/…`,
`/Users/{id}/PlayedItems/…`, `/Users/{id}/FavoriteItems/…`); the unprefixed
forms Jellyfin 10.11 added return 404.
- The API is also served under a legacy `/emby` prefix, and both dialects accept
the token as `X-Emby-Token` or `api_key=`.
- Emby answers only its own LAN discovery datagram ("who is EmbyServer?") and
ignores Jellyfin's; its default HTTPS port is 8920.
- No `/QuickConnect` route exists, so Quick Connect stays Jellyfin-only.
Row fields Emby withholds
- `ProductionYear`, `OfficialRating`, `PremiereDate` and `DateCreated` are absent
from list rows unless named in `Fields`, which would otherwise strip the year
and age-rating badge from every card in the app.
- `UserData.LastPlayedDate` never appears on a list row under `Fields=UserData`,
`EnableUserData=true` or the user-scoped `Ids=` form — only on the single-item
detail route, or when the Emby-specific `UserDataLastPlayedDate` token is
requested. Without it every recency-ordered surface silently degrades to
library-add time, and `JellyfinApiCache.applyWatchState` stamps
`DateTime.now()` on watched rows, so an offline watch-state pull would rewrite
the cached play time of everything it walked.
Continue Watching and Next Up
- Emby computes Next Up per series only: the library-wide `/Shows/NextUp` query
returns nothing under every parameter combination tried. The shelf is
therefore reconstructed from a played-episode recency scan plus one
`/Shows/NextUp?SeriesId=` per distinct series, bounded by a shared wall clock
that covers the scan as well — per-request timeouts cannot bound the pass
because `MediaServerHttpClient` times the connect and receive phases
independently. Rows are stamped with their series' newest play from the same
response that ordered them, so no per-series enrichment request is needed.
- `/Shows/NextUp` ignores `NextUpDateCutoff`, and no server-side played-date
filter exists to delegate to (`MinDatePlayed` and `MinDateLastPlayed` are
ignored; `MinDateLastSaved`, `MinDateCreated` and `MinPremiereDate` filter
unrelated dates), so the 365-day window is applied to the scanned dates.
- The resume route returns items with no saved position, including plain next
episodes, so the Emby resume leg reads from `/Items?Filters=IsResumable`.
- Emby is ahead of Jellyfin in one place: `/Users/{id}/Items/{id}/HideFromResume`
makes Continue Watching removal a real capability.
Everything else
- `/Sessions/Playing` and `/Sessions/Playing/Progress` reject a body with no
`PlaySessionId` (HTTP 400), so playback reporting always sends one.
- Passing any `MediaTypes` value to the playlist query returns an empty list.
- There is no aggregate `/Items/Filters` route; the four filter facets are
reassembled from `/Genres`, `/OfficialRatings`, `/Studios` and `/Tags`.
- Metadata writes take name-pair lists (`Genres: [{'Name': 'Action'}]`); the
plain string array is accepted and then silently discarded.
- Custom artwork uploads must be base64 text, not raw bytes — which was broken
for Jellyfin too and is fixed for both.
- Trickplay, media segments and lyrics 404 on Emby, so scrub previews are absent
and intro/credit markers fall back to chapter names.
Verified against a local Emby 4.9.5 and a Jellyfin 10.11.11 control server:
onboarding, browse, detail, playable stream URLs serving real bytes, subtitle
sidecars, watch-state write and restore, hubs, cross-server aggregation and
search across both backends simultaneously.
482 lines
15 KiB
Dart
482 lines
15 KiB
Dart
/// Generated file. Do not edit.
|
|
///
|
|
/// Source: lib/i18n
|
|
/// To regenerate, run: `dart run slang`
|
|
///
|
|
/// Locales: 22
|
|
/// Strings: 32736 (1488 per locale)
|
|
|
|
// coverage:ignore-file
|
|
// ignore_for_file: type=lint, unused_import
|
|
// dart format off
|
|
|
|
import 'package:flutter/widgets.dart';
|
|
import 'package:intl/intl.dart';
|
|
import 'package:slang/generated.dart';
|
|
import 'package:slang_flutter/slang_flutter.dart';
|
|
export 'package:slang_flutter/slang_flutter.dart';
|
|
|
|
import 'strings_az.g.dart' deferred as l_az;
|
|
import 'strings_bg.g.dart' deferred as l_bg;
|
|
import 'strings_da.g.dart' deferred as l_da;
|
|
import 'strings_de.g.dart' deferred as l_de;
|
|
import 'strings_es.g.dart' deferred as l_es;
|
|
import 'strings_fr.g.dart' deferred as l_fr;
|
|
import 'strings_hu.g.dart' deferred as l_hu;
|
|
import 'strings_it.g.dart' deferred as l_it;
|
|
import 'strings_ja.g.dart' deferred as l_ja;
|
|
import 'strings_kk.g.dart' deferred as l_kk;
|
|
import 'strings_ko.g.dart' deferred as l_ko;
|
|
import 'strings_nb.g.dart' deferred as l_nb;
|
|
import 'strings_nl.g.dart' deferred as l_nl;
|
|
import 'strings_pl.g.dart' deferred as l_pl;
|
|
import 'strings_pt.g.dart' deferred as l_pt;
|
|
import 'strings_ru.g.dart' deferred as l_ru;
|
|
import 'strings_sv.g.dart' deferred as l_sv;
|
|
import 'strings_tr.g.dart' deferred as l_tr;
|
|
import 'strings_uz.g.dart' deferred as l_uz;
|
|
import 'strings_zh.g.dart' deferred as l_zh;
|
|
import 'strings_zh_Hant.g.dart' deferred as l_zh_Hant;
|
|
part 'strings_en.g.dart';
|
|
|
|
/// Supported locales.
|
|
///
|
|
/// Usage:
|
|
/// - LocaleSettings.setLocale(AppLocale.en) // set locale
|
|
/// - Locale locale = AppLocale.en.flutterLocale // get flutter locale from enum
|
|
/// - if (LocaleSettings.currentLocale == AppLocale.en) // locale check
|
|
enum AppLocale with BaseAppLocale<AppLocale, Translations> {
|
|
en(languageCode: 'en'),
|
|
az(languageCode: 'az'),
|
|
bg(languageCode: 'bg'),
|
|
da(languageCode: 'da'),
|
|
de(languageCode: 'de'),
|
|
es(languageCode: 'es'),
|
|
fr(languageCode: 'fr'),
|
|
hu(languageCode: 'hu'),
|
|
it(languageCode: 'it'),
|
|
ja(languageCode: 'ja'),
|
|
kk(languageCode: 'kk'),
|
|
ko(languageCode: 'ko'),
|
|
nb(languageCode: 'nb'),
|
|
nl(languageCode: 'nl'),
|
|
pl(languageCode: 'pl'),
|
|
pt(languageCode: 'pt'),
|
|
ru(languageCode: 'ru'),
|
|
sv(languageCode: 'sv'),
|
|
tr(languageCode: 'tr'),
|
|
uz(languageCode: 'uz'),
|
|
zh(languageCode: 'zh'),
|
|
zhHant(languageCode: 'zh', scriptCode: 'Hant');
|
|
|
|
const AppLocale({
|
|
required this.languageCode,
|
|
this.scriptCode, // ignore: unused_element, unused_element_parameter
|
|
this.countryCode, // ignore: unused_element, unused_element_parameter
|
|
});
|
|
|
|
@override final String languageCode;
|
|
@override final String? scriptCode;
|
|
@override final String? countryCode;
|
|
|
|
@override
|
|
Future<Translations> build({
|
|
Map<String, Node>? overrides,
|
|
PluralResolver? cardinalResolver,
|
|
PluralResolver? ordinalResolver,
|
|
}) async {
|
|
switch (this) {
|
|
case AppLocale.en:
|
|
return TranslationsEn(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.az:
|
|
await l_az.loadLibrary();
|
|
return l_az.TranslationsAz(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.bg:
|
|
await l_bg.loadLibrary();
|
|
return l_bg.TranslationsBg(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.da:
|
|
await l_da.loadLibrary();
|
|
return l_da.TranslationsDa(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.de:
|
|
await l_de.loadLibrary();
|
|
return l_de.TranslationsDe(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.es:
|
|
await l_es.loadLibrary();
|
|
return l_es.TranslationsEs(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.fr:
|
|
await l_fr.loadLibrary();
|
|
return l_fr.TranslationsFr(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.hu:
|
|
await l_hu.loadLibrary();
|
|
return l_hu.TranslationsHu(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.it:
|
|
await l_it.loadLibrary();
|
|
return l_it.TranslationsIt(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.ja:
|
|
await l_ja.loadLibrary();
|
|
return l_ja.TranslationsJa(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.kk:
|
|
await l_kk.loadLibrary();
|
|
return l_kk.TranslationsKk(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.ko:
|
|
await l_ko.loadLibrary();
|
|
return l_ko.TranslationsKo(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.nb:
|
|
await l_nb.loadLibrary();
|
|
return l_nb.TranslationsNb(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.nl:
|
|
await l_nl.loadLibrary();
|
|
return l_nl.TranslationsNl(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.pl:
|
|
await l_pl.loadLibrary();
|
|
return l_pl.TranslationsPl(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.pt:
|
|
await l_pt.loadLibrary();
|
|
return l_pt.TranslationsPt(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.ru:
|
|
await l_ru.loadLibrary();
|
|
return l_ru.TranslationsRu(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.sv:
|
|
await l_sv.loadLibrary();
|
|
return l_sv.TranslationsSv(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.tr:
|
|
await l_tr.loadLibrary();
|
|
return l_tr.TranslationsTr(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.uz:
|
|
await l_uz.loadLibrary();
|
|
return l_uz.TranslationsUz(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.zh:
|
|
await l_zh.loadLibrary();
|
|
return l_zh.TranslationsZh(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.zhHant:
|
|
await l_zh_Hant.loadLibrary();
|
|
return l_zh_Hant.TranslationsZhHant(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
}
|
|
}
|
|
|
|
@override
|
|
Translations buildSync({
|
|
Map<String, Node>? overrides,
|
|
PluralResolver? cardinalResolver,
|
|
PluralResolver? ordinalResolver,
|
|
}) {
|
|
switch (this) {
|
|
case AppLocale.en:
|
|
return TranslationsEn(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.az:
|
|
return l_az.TranslationsAz(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.bg:
|
|
return l_bg.TranslationsBg(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.da:
|
|
return l_da.TranslationsDa(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.de:
|
|
return l_de.TranslationsDe(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.es:
|
|
return l_es.TranslationsEs(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.fr:
|
|
return l_fr.TranslationsFr(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.hu:
|
|
return l_hu.TranslationsHu(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.it:
|
|
return l_it.TranslationsIt(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.ja:
|
|
return l_ja.TranslationsJa(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.kk:
|
|
return l_kk.TranslationsKk(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.ko:
|
|
return l_ko.TranslationsKo(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.nb:
|
|
return l_nb.TranslationsNb(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.nl:
|
|
return l_nl.TranslationsNl(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.pl:
|
|
return l_pl.TranslationsPl(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.pt:
|
|
return l_pt.TranslationsPt(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.ru:
|
|
return l_ru.TranslationsRu(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.sv:
|
|
return l_sv.TranslationsSv(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.tr:
|
|
return l_tr.TranslationsTr(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.uz:
|
|
return l_uz.TranslationsUz(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.zh:
|
|
return l_zh.TranslationsZh(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
case AppLocale.zhHant:
|
|
return l_zh_Hant.TranslationsZhHant(
|
|
overrides: overrides,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Gets current instance managed by [LocaleSettings].
|
|
Translations get translations => LocaleSettings.instance.getTranslations(this);
|
|
}
|
|
|
|
/// Method A: Simple
|
|
///
|
|
/// No rebuild after locale change.
|
|
/// Translation happens during initialization of the widget (call of t).
|
|
/// Configurable via 'translate_var'.
|
|
///
|
|
/// Usage:
|
|
/// String a = t.someKey.anotherKey;
|
|
/// String b = t['someKey.anotherKey']; // Only for edge cases!
|
|
Translations get t => LocaleSettings.instance.currentTranslations;
|
|
|
|
/// Method B: Advanced
|
|
///
|
|
/// All widgets using this method will trigger a rebuild when locale changes.
|
|
/// Use this if you have e.g. a settings page where the user can select the locale during runtime.
|
|
///
|
|
/// Step 1:
|
|
/// wrap your App with
|
|
/// TranslationProvider(
|
|
/// child: MyApp()
|
|
/// );
|
|
///
|
|
/// Step 2:
|
|
/// final t = Translations.of(context); // Get t variable.
|
|
/// String a = t.someKey.anotherKey; // Use t variable.
|
|
/// String b = t['someKey.anotherKey']; // Only for edge cases!
|
|
class TranslationProvider extends BaseTranslationProvider<AppLocale, Translations> {
|
|
TranslationProvider({required super.child}) : super(settings: LocaleSettings.instance);
|
|
|
|
static InheritedLocaleData<AppLocale, Translations> of(BuildContext context) => InheritedLocaleData.of<AppLocale, Translations>(context);
|
|
}
|
|
|
|
/// Method B shorthand via [BuildContext] extension method.
|
|
/// Configurable via 'translate_var'.
|
|
///
|
|
/// Usage (e.g. in a widget's build method):
|
|
/// context.t.someKey.anotherKey
|
|
extension BuildContextTranslationsExtension on BuildContext {
|
|
Translations get t => TranslationProvider.of(this).translations;
|
|
}
|
|
|
|
/// Manages all translation instances and the current locale
|
|
class LocaleSettings extends BaseFlutterLocaleSettings<AppLocale, Translations> {
|
|
LocaleSettings._() : super(
|
|
utils: AppLocaleUtils.instance,
|
|
lazy: true,
|
|
);
|
|
|
|
static final instance = LocaleSettings._();
|
|
|
|
// static aliases (checkout base methods for documentation)
|
|
static AppLocale get currentLocale => instance.currentLocale;
|
|
static Stream<AppLocale> getLocaleStream() => instance.getLocaleStream();
|
|
static Future<AppLocale> setLocale(AppLocale locale, {bool? listenToDeviceLocale = false}) => instance.setLocale(locale, listenToDeviceLocale: listenToDeviceLocale);
|
|
static Future<AppLocale> setLocaleRaw(String rawLocale, {bool? listenToDeviceLocale = false}) => instance.setLocaleRaw(rawLocale, listenToDeviceLocale: listenToDeviceLocale);
|
|
static Future<AppLocale> useDeviceLocale() => instance.useDeviceLocale();
|
|
static Future<void> setPluralResolver({String? language, AppLocale? locale, PluralResolver? cardinalResolver, PluralResolver? ordinalResolver}) => instance.setPluralResolver(
|
|
language: language,
|
|
locale: locale,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
|
|
// synchronous versions
|
|
static AppLocale setLocaleSync(AppLocale locale, {bool? listenToDeviceLocale = false}) => instance.setLocaleSync(locale, listenToDeviceLocale: listenToDeviceLocale);
|
|
static AppLocale setLocaleRawSync(String rawLocale, {bool? listenToDeviceLocale = false}) => instance.setLocaleRawSync(rawLocale, listenToDeviceLocale: listenToDeviceLocale);
|
|
static AppLocale useDeviceLocaleSync() => instance.useDeviceLocaleSync();
|
|
static void setPluralResolverSync({String? language, AppLocale? locale, PluralResolver? cardinalResolver, PluralResolver? ordinalResolver}) => instance.setPluralResolverSync(
|
|
language: language,
|
|
locale: locale,
|
|
cardinalResolver: cardinalResolver,
|
|
ordinalResolver: ordinalResolver,
|
|
);
|
|
}
|
|
|
|
/// Provides utility functions without any side effects.
|
|
class AppLocaleUtils extends BaseAppLocaleUtils<AppLocale, Translations> {
|
|
AppLocaleUtils._() : super(
|
|
baseLocale: AppLocale.en,
|
|
locales: AppLocale.values,
|
|
);
|
|
|
|
static final instance = AppLocaleUtils._();
|
|
|
|
// static aliases (checkout base methods for documentation)
|
|
static AppLocale parse(String rawLocale) => instance.parse(rawLocale);
|
|
static AppLocale parseLocaleParts({required String languageCode, String? scriptCode, String? countryCode}) => instance.parseLocaleParts(languageCode: languageCode, scriptCode: scriptCode, countryCode: countryCode);
|
|
static AppLocale findDeviceLocale() => instance.findDeviceLocale();
|
|
static List<Locale> get supportedLocales => instance.supportedLocales;
|
|
static List<String> get supportedLocalesRaw => instance.supportedLocalesRaw;
|
|
}
|