Fix languages not being set for SDK

This commit is contained in:
Bill Thornton committed 2026-09-14 12:33:06 -04:00
1 parent 47045e757a
commit 288b5ea3d8
6 files changed
+74 -45

No files matched your search

+3
View File
@@ -1,5 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
declare module 'jellyfin-apiclient' {
import type { Api } from '@jellyfin/sdk';
import type {
AllThemeMediaResult,
AuthenticationResult,
@@ -70,6 +71,8 @@ declare module 'jellyfin-apiclient' {
import type { ConnectionState } from 'lib/jellyfin-apiclient';
class ApiClient {
_sdk?: Api;
constructor(serverAddress: string, appName: string, appVersion: string, deviceName: string, deviceId: string);
accessToken(): string;
+2
View File
@@ -3,6 +3,8 @@
*/
export enum EventType {
HEADER_RENDERED = 'HEADER_RENDERED',
/** The user's language has changed. */
LANGUAGE_CHANGE = 'LANGUAGE_CHANGE',
/** Items have been updated/deleted and the UI should refresh. */
REFRESH_NEEDED = 'REFRESH_NEEDED',
SET_TABS = 'SET_TABS',
+10
View File
@@ -13,6 +13,7 @@ import loading from 'components/loading/loading';
import { pluginManager } from './components/pluginManager';
import { appRouter } from './components/router/appRouter';
import { AppFeature } from 'constants/appFeature';
import { EventType } from 'constants/eventType';
import globalize from './lib/globalize';
import { loadCoreDictionary } from 'lib/globalize/loader';
import getServerAddress from 'lib/jellyfin-apiclient/utils/getServerAddress';
@@ -23,6 +24,7 @@ import { getPlugins } from './scripts/settings/webSettings';
import taskButton from './scripts/taskbutton';
import { pageClassOn, serverAddress } from './utils/dashboard';
import Events from './utils/events';
import { updateApiClientSdk } from 'utils/jellyfin-apiclient/compat';
import { initializeServerConnections } from './scripts/serverNotifications';
import RootApp from './RootApp';
@@ -89,6 +91,14 @@ build: ${__JF_BUILD_VERSION__}`);
// Update localization on user changes
Events.on(ServerConnections, 'localusersignedin', globalize.updateCurrentCulture);
Events.on(ServerConnections, 'localusersignedout', globalize.updateCurrentCulture);
// Update sdk language on language changes
Events.on(document, EventType.LANGUAGE_CHANGE, () => {
ServerConnections.getCurrentApiClientAsync()
.then(updateApiClientSdk)
.catch(err => {
console.error('Failed to update ApiClient SDK on language change', err);
});
});
// Load the font styles
loadFonts();
+20 -2
View File
@@ -1,5 +1,6 @@
import isEmpty from 'lodash-es/isEmpty';
import { EventType } from 'constants/eventType';
import { currentSettings as userSettings } from 'scripts/settings/userSettings';
import Events from 'utils/events';
import { updateLocale } from 'utils/dateFnsLocale';
@@ -13,6 +14,10 @@ export const FALLBACK_CULTURE = 'en-us';
const RTL_LANGS = ['ar', 'fa', 'ur', 'he'];
const allTranslations = {};
/**
* The current application locale/language.
* @type {string|undefined}
*/
let currentCulture;
let currentDateTimeCulture;
let isRTL = false;
@@ -21,6 +26,16 @@ export function getCurrentLocale() {
return currentCulture;
}
export function getLanguages() {
const culture = currentCulture || FALLBACK_CULTURE;
const [ baseLang ] = culture.split('-');
if (baseLang && baseLang !== culture) {
return [ culture, baseLang ];
}
return [ culture ];
}
export function getCurrentDateTimeLocale() {
return currentDateTimeCulture;
}
@@ -76,6 +91,7 @@ export function getIsElementRTL(element) {
}
export function updateCurrentCulture() {
const lastCulture = currentCulture;
let culture;
try {
culture = userSettings.language();
@@ -87,7 +103,10 @@ export function updateCurrentCulture() {
currentCulture = normalizeLocaleName(culture);
document.documentElement.setAttribute('lang', currentCulture);
if (lastCulture !== currentCulture) {
document.documentElement.setAttribute('lang', currentCulture);
Events.trigger(document, EventType.LANGUAGE_CHANGE, [ currentCulture ]);
}
let dateTimeCulture;
try {
@@ -299,4 +318,3 @@ export default {
getIsRTL,
getIsElementRTL
};
@@ -6,10 +6,9 @@ import { compareVersions } from '@jellyfin/sdk/lib/utils/versioning';
import events from 'utils/events';
import { ajax } from 'utils/fetch';
import { toApi } from 'utils/jellyfin-apiclient/compat';
import { toApi, updateApiClientSdk } from 'utils/jellyfin-apiclient/compat';
import { createApiClient } from 'utils/jellyfin-apiclient/createApiClient';
import { equalsIgnoreCase } from 'utils/string';
import { safeDecodeURIComponent } from 'utils/url';
import { ConnectionMode } from './connectionMode';
import { ConnectionState } from './connectionState';
@@ -187,18 +186,7 @@ export default class ConnectionManager {
apiClient.setAuthenticationInfo(result.AccessToken, result.User.Id);
// Update SDK Api instance
apiClient._sdk?.update({
basePath: apiClient.serverAddress(),
accessToken: apiClient.accessToken(),
clientInfo: {
name: safeDecodeURIComponent(apiClient.appName()),
version: safeDecodeURIComponent(apiClient.appVersion())
},
deviceInfo: {
name: safeDecodeURIComponent(apiClient.deviceName()),
id: safeDecodeURIComponent(apiClient.deviceId())
}
});
updateApiClientSdk(apiClient);
afterConnected(apiClient, options);
@@ -621,18 +609,7 @@ export default class ConnectionManager {
result.ApiClient.setAuthenticationInfo(server.AccessToken, server.UserId);
// Update SDK Api instance
result.ApiClient._sdk?.update({
basePath: result.ApiClient.serverAddress(),
accessToken: result.ApiClient.accessToken(),
clientInfo: {
name: safeDecodeURIComponent(result.ApiClient.appName()),
version: safeDecodeURIComponent(result.ApiClient.appVersion())
},
deviceInfo: {
name: safeDecodeURIComponent(result.ApiClient.deviceName()),
id: safeDecodeURIComponent(result.ApiClient.deviceId())
}
});
updateApiClientSdk(result.ApiClient);
const resolveActions = function () {
resolve(result);
+36 -17
View File
@@ -1,27 +1,46 @@
import { Api, Jellyfin } from '@jellyfin/sdk';
import { ApiClient } from 'jellyfin-apiclient';
import { type Api, Jellyfin, type JellyfinParameters } from '@jellyfin/sdk';
import type { ApiClient } from 'jellyfin-apiclient';
import { getLanguages } from 'lib/globalize';
import { safeDecodeURIComponent } from 'utils/url';
const getParameters = (apiClient: ApiClient): JellyfinParameters => ({
// The SDK encodes these values when creating the authorization header,
// so we need to decode them here to avoid double encoding.
clientInfo: {
name: safeDecodeURIComponent(apiClient.appName()),
version: safeDecodeURIComponent(apiClient.appVersion())
},
deviceInfo: {
name: safeDecodeURIComponent(apiClient.deviceName()),
id: safeDecodeURIComponent(apiClient.deviceId()),
languages: getLanguages()
}
});
/**
* Returns an SDK Api instance using the same parameters as the provided ApiClient.
* @param {ApiClient} apiClient The (legacy) ApiClient.
* @returns {Api} An equivalent SDK Api instance.
*/
export const toApi = (apiClient: ApiClient): Api => {
return (new Jellyfin({
// The SDK encodes these values when creating the authorization header,
// so we need to decode them here to avoid double encoding.
clientInfo: {
name: safeDecodeURIComponent(apiClient.appName()),
version: safeDecodeURIComponent(apiClient.appVersion())
},
deviceInfo: {
name: safeDecodeURIComponent(apiClient.deviceName()),
id: safeDecodeURIComponent(apiClient.deviceId())
}
})).createApi(
apiClient.serverAddress(),
apiClient.accessToken()
);
return (new Jellyfin(getParameters(apiClient)))
.createApi(
apiClient.serverAddress(),
apiClient.accessToken()
);
};
/**
* Updates the SDK Api instance of the provided ApiClient with the same parameters as the ApiClient.
* @param {ApiClient} apiClient The (legacy) ApiClient.
*/
export const updateApiClientSdk = (apiClient: ApiClient) => {
const { clientInfo, deviceInfo } = getParameters(apiClient);
apiClient._sdk?.update({
basePath: apiClient.serverAddress(),
accessToken: apiClient.accessToken(),
clientInfo,
deviceInfo
});
};