(core) User language switcher

Summary:
New language selector on the Account page for logged-in users.
New icon for switching language for an anonymous user.

For anonymous users, language is stored in a cookie grist_user_locale.
Language is stored in user settings for authenticated users and takes
precedence over what is stored in the cookie.

Test Plan: New tests

Reviewers: paulfitz

Reviewed By: paulfitz

Differential Revision: https://phab.getgrist.com/D3766
This commit is contained in:
Jarosław Sadziński
2023-01-24 14:13:18 +01:00
parent abea735470
commit 90d3ee037a
36 changed files with 696 additions and 74 deletions

View File

@@ -68,3 +68,17 @@ try {
}
currencies = [...currencies].sort((a, b) => nativeCompare(a.code, b.code));
export function getCountryCode(locale: string) {
// We have some defaults defined.
if (locale === 'en') { return 'US'; }
let countryCode = locale.split(/[-_]/)[1];
if (countryCode) { return countryCode.toUpperCase(); }
countryCode = locale.toUpperCase();
// Test if we can use language as a country code.
if (localeCodes.map(code => code.split(/[-_]/)[1]).includes(countryCode)) {
return countryCode;
}
return null;
}

View File

@@ -6,6 +6,7 @@ export interface UserProfile {
anonymous?: boolean; // when present, asserts whether user is anonymous (not authorized).
connectId?: string|null, // used by GristConnect to identify user in external provider.
loginMethod?: 'Google'|'Email + Password'|'External';
locale?: string|null;
}
// User profile including user id and user ref. All information in it should

View File

@@ -31,6 +31,8 @@ export interface UserPrefs extends Prefs {
behavioralPrompts?: BehavioralPromptPrefs;
// Welcome popups a user has dismissed.
dismissedWelcomePopups?: DismissedReminder[];
// Localization support.
locale?: string;
}
// A collection of preferences related to a combination of user and org.

View File

@@ -141,6 +141,8 @@ export interface UserOptions {
// Whether user is a consultant. Consultant users can be added to sites
// without being counted for billing. Defaults to false if unset.
isConsultant?: boolean;
// Locale selected by the user. Defaults to 'en' if unset.
locale?: string;
}
export interface PermissionDelta {
@@ -331,6 +333,7 @@ export interface UserAPI {
moveDoc(docId: string, workspaceId: number): Promise<void>;
getUserProfile(): Promise<FullUser>;
updateUserName(name: string): Promise<void>;
updateUserLocale(locale: string|null): Promise<void>;
updateAllowGoogleLogin(allowGoogleLogin: boolean): Promise<void>;
updateIsConsultant(userId: number, isConsultant: boolean): Promise<void>;
getWorker(key: string): Promise<string>;
@@ -632,6 +635,13 @@ export class UserAPIImpl extends BaseAPI implements UserAPI {
});
}
public async updateUserLocale(locale: string|null): Promise<void> {
await this.request(`${this._url}/api/profile/user/locale`, {
method: 'POST',
body: JSON.stringify({locale})
});
}
public async updateAllowGoogleLogin(allowGoogleLogin: boolean): Promise<void> {
await this.request(`${this._url}/api/profile/allowGoogleLogin`, {
method: 'POST',

View File

@@ -585,6 +585,9 @@ export interface GristLoadConfig {
// Email address of the support user.
supportEmail?: string;
// Current user locale, read from the user options;
userLocale?: string;
}
export const HideableUiElements = StringUnion("helpCenter", "billing", "templates", "multiSite", "multiAccounts");