mirror of
https://github.com/bitwarden/browser
synced 2025-12-13 23:03:32 +00:00
Add lang attr on desktop and browser (#14691)
This commit is contained in:
36
libs/angular/src/platform/i18n/document-lang.setter.spec.ts
Normal file
36
libs/angular/src/platform/i18n/document-lang.setter.spec.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { mock } from "jest-mock-extended";
|
||||
import { Subject } from "rxjs";
|
||||
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
|
||||
import { DocumentLangSetter } from "./document-lang.setter";
|
||||
|
||||
describe("DocumentLangSetter", () => {
|
||||
const document = mock<Document>();
|
||||
const i18nService = mock<I18nService>();
|
||||
|
||||
const sut = new DocumentLangSetter(document, i18nService);
|
||||
|
||||
describe("start", () => {
|
||||
it("reacts to locale changes while start called with a non-closed subscription", async () => {
|
||||
const localeSubject = new Subject<string>();
|
||||
i18nService.locale$ = localeSubject;
|
||||
|
||||
localeSubject.next("en");
|
||||
|
||||
expect(document.documentElement.lang).toBeFalsy();
|
||||
|
||||
const sub = sut.start();
|
||||
|
||||
localeSubject.next("es");
|
||||
|
||||
expect(document.documentElement.lang).toBe("es");
|
||||
|
||||
sub.unsubscribe();
|
||||
|
||||
localeSubject.next("ar");
|
||||
|
||||
expect(document.documentElement.lang).toBe("es");
|
||||
});
|
||||
});
|
||||
});
|
||||
26
libs/angular/src/platform/i18n/document-lang.setter.ts
Normal file
26
libs/angular/src/platform/i18n/document-lang.setter.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { Subscription } from "rxjs";
|
||||
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
|
||||
/**
|
||||
* A service for managing the setting of the `lang="<locale>" attribute on the
|
||||
* main document for the application.
|
||||
*/
|
||||
export class DocumentLangSetter {
|
||||
constructor(
|
||||
private readonly document: Document,
|
||||
private readonly i18nService: I18nService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Starts listening to an upstream source for the best locale for the user
|
||||
* and applies it to the application document.
|
||||
* @returns A subscription that can be unsubscribed if you wish to stop
|
||||
* applying lang attribute updates to the application document.
|
||||
*/
|
||||
start(): Subscription {
|
||||
return this.i18nService.locale$.subscribe((locale) => {
|
||||
this.document.documentElement.lang = locale;
|
||||
});
|
||||
}
|
||||
}
|
||||
1
libs/angular/src/platform/i18n/index.ts
Normal file
1
libs/angular/src/platform/i18n/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { DocumentLangSetter } from "./document-lang.setter";
|
||||
@@ -21,6 +21,7 @@ import { SafeInjectionToken } from "@bitwarden/ui-common";
|
||||
export { SafeInjectionToken } from "@bitwarden/ui-common";
|
||||
|
||||
export const WINDOW = new SafeInjectionToken<Window>("WINDOW");
|
||||
export const DOCUMENT = new SafeInjectionToken<Document>("DOCUMENT");
|
||||
export const OBSERVABLE_MEMORY_STORAGE = new SafeInjectionToken<
|
||||
AbstractStorageService & ObservableStorageService
|
||||
>("OBSERVABLE_MEMORY_STORAGE");
|
||||
|
||||
@@ -337,6 +337,7 @@ import {
|
||||
import { DeviceTrustToastService as DeviceTrustToastServiceAbstraction } from "../auth/services/device-trust-toast.service.abstraction";
|
||||
import { DeviceTrustToastService } from "../auth/services/device-trust-toast.service.implementation";
|
||||
import { FormValidationErrorsService as FormValidationErrorsServiceAbstraction } from "../platform/abstractions/form-validation-errors.service";
|
||||
import { DocumentLangSetter } from "../platform/i18n";
|
||||
import { FormValidationErrorsService } from "../platform/services/form-validation-errors.service";
|
||||
import { LoggingErrorHandler } from "../platform/services/logging-error-handler";
|
||||
import { AngularThemingService } from "../platform/services/theming/angular-theming.service";
|
||||
@@ -349,6 +350,7 @@ import { NoopViewCacheService } from "../platform/view-cache/internal";
|
||||
import {
|
||||
CLIENT_TYPE,
|
||||
DEFAULT_VAULT_TIMEOUT,
|
||||
DOCUMENT,
|
||||
ENV_ADDITIONAL_REGIONS,
|
||||
HTTP_OPERATIONS,
|
||||
INTRAPROCESS_MESSAGING_SUBJECT,
|
||||
@@ -378,6 +380,7 @@ const safeProviders: SafeProvider[] = [
|
||||
safeProvider(ModalService),
|
||||
safeProvider(PasswordRepromptService),
|
||||
safeProvider({ provide: WINDOW, useValue: window }),
|
||||
safeProvider({ provide: DOCUMENT, useValue: document }),
|
||||
safeProvider({
|
||||
provide: LOCALE_ID as SafeInjectionToken<string>,
|
||||
useFactory: (i18nService: I18nServiceAbstraction) => i18nService.translationLocale,
|
||||
@@ -1542,6 +1545,11 @@ const safeProviders: SafeProvider[] = [
|
||||
useClass: MasterPasswordApiService,
|
||||
deps: [ApiServiceAbstraction, LogService],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: DocumentLangSetter,
|
||||
useClass: DocumentLangSetter,
|
||||
deps: [DOCUMENT, I18nServiceAbstraction],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: CipherEncryptionService,
|
||||
useClass: DefaultCipherEncryptionService,
|
||||
|
||||
Reference in New Issue
Block a user