i18n: rename locale to regionalFormat (#106585)

* locale -> regionalFormat, mirroring #102233

* set up regionalFormat to replace locale entirely

* replace locale with regionalFormat

* update reportInteraction arguments
simpson-query-service-sse
Luminessa Starlight 6 months ago committed by GitHub
parent c00caa2fb2
commit 09e8484bac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      kinds/preferences/preferences_kind.cue
  2. 4
      packages/grafana-data/src/types/config.ts
  3. 9
      packages/grafana-runtime/src/config.ts
  4. 8
      packages/grafana-schema/src/raw/preferences/x/preferences_types.gen.ts
  5. 1
      pkg/api/dtos/models.go
  6. 16
      pkg/api/dtos/prefs.go
  7. 30
      pkg/api/index.go
  8. 2
      pkg/api/preferences.go
  9. 2
      pkg/kinds/preferences/preferences_spec_gen.go
  10. 6
      pkg/services/preference/model.go
  11. 6
      pkg/services/preference/prefapi/api.go
  12. 12
      pkg/services/preference/prefimpl/pref.go
  13. 22
      pkg/services/preference/prefimpl/pref_test.go
  14. 20
      public/api-merged.json
  15. 4
      public/app/app.ts
  16. 30
      public/app/core/components/SharedPreferences/SharedPreferences.tsx
  17. 4
      public/app/core/internationalization/dates.ts
  18. 4
      public/app/core/services/context_srv.ts
  19. 20
      public/openapi3.json

@ -28,7 +28,7 @@ lineage: schemas: [{
language?: string
// Selected locale (beta)
locale?: string
regionalFormat?: string
// Explore query history preferences
queryHistory?: #QueryHistoryPreference

@ -129,7 +129,7 @@ export interface CurrentUserDTO {
gravatarUrl: string;
timezone: string;
weekStart: string;
locale: string;
regionalFormat: string;
language: string;
permissions?: Record<string, boolean>;
analytics: AnalyticsSettings;
@ -251,7 +251,7 @@ export interface GrafanaConfig {
* Grafana's supported language.
*/
language: string | undefined;
locale: string;
regionalFormat: string;
}
export interface SqlConnectionLimits {

@ -213,10 +213,10 @@ export class GrafanaBootConfig implements GrafanaConfig {
language: string | undefined;
/**
* Locale used in Grafana's UI. Default to 'es-US' in the backend and overwritten when the user select a different one in SharedPreferences.
* This is the locale that is used for date formatting and other locale-specific features.
* regionalFormat used in Grafana's UI. Default to 'es-US' in the backend and overwritten when the user select a different one in SharedPreferences.
* This is the regionalFormat that is used for date formatting and other locale-specific features.
*/
locale: string;
regionalFormat: string;
constructor(options: GrafanaBootConfig) {
this.bootData = options.bootData;
@ -253,8 +253,7 @@ export class GrafanaBootConfig implements GrafanaConfig {
this.theme2 = getThemeById(this.bootData.user.theme);
this.bootData.user.lightTheme = this.theme2.isLight;
this.theme = this.theme2.v1;
this.locale = options.bootData.user.locale;
this.regionalFormat = options.bootData.user.regionalFormat;
}
geomapDefaultBaseLayer?: MapLayerOptions<any> | undefined;
listDashboardScopesEndpoint?: string | undefined;

@ -46,10 +46,6 @@ export interface Preferences {
* Selected language (beta)
*/
language?: string;
/**
* Selected locale (beta)
*/
locale?: string;
/**
* Navigation preferences
*/
@ -58,6 +54,10 @@ export interface Preferences {
* Explore query history preferences
*/
queryHistory?: QueryHistoryPreference;
/**
* Selected locale (beta)
*/
regionalFormat?: string;
/**
* light, dark, empty is default
*/

@ -45,6 +45,7 @@ type CurrentUser struct {
Timezone string `json:"timezone"`
WeekStart string `json:"weekStart"`
Locale string `json:"locale"`
RegionalFormat string `json:"regionalFormat"`
Language string `json:"language"`
HelpFlags1 user.HelpFlags1 `json:"helpFlags1"`
HasEditPermissionInFolders bool `json:"hasEditPermissionInFolders"`

@ -14,13 +14,13 @@ type UpdatePrefsCmd struct {
HomeDashboardID int64 `json:"homeDashboardId"`
HomeDashboardUID *string `json:"homeDashboardUID,omitempty"`
// Enum: utc,browser
Timezone string `json:"timezone"`
WeekStart string `json:"weekStart"`
QueryHistory *pref.QueryHistoryPreference `json:"queryHistory,omitempty"`
Language string `json:"language"`
Locale string `json:"locale"`
Cookies []pref.CookieType `json:"cookies,omitempty"`
Navbar *pref.NavbarPreference `json:"navbar,omitempty"`
Timezone string `json:"timezone"`
WeekStart string `json:"weekStart"`
QueryHistory *pref.QueryHistoryPreference `json:"queryHistory,omitempty"`
Language string `json:"language"`
RegionalFormat string `json:"regionalFormat"`
Cookies []pref.CookieType `json:"cookies,omitempty"`
Navbar *pref.NavbarPreference `json:"navbar,omitempty"`
}
// swagger:model
@ -35,7 +35,7 @@ type PatchPrefsCmd struct {
Timezone *string `json:"timezone,omitempty"`
WeekStart *string `json:"weekStart,omitempty"`
Language *string `json:"language,omitempty"`
Locale *string `json:"locale,omitempty"`
RegionalFormat *string `json:"regionalFormat,omitempty"`
QueryHistory *pref.QueryHistoryPreference `json:"queryHistory,omitempty"`
HomeDashboardUID *string `json:"homeDashboardUID,omitempty"`
Cookies []pref.CookieType `json:"cookies,omitempty"`

@ -24,21 +24,21 @@ import (
)
type URLPrefs struct {
Language string
Locale string
Theme string
Language string
RegionalFormat string
Theme string
}
// URL prefs take precedence over any saved user preferences
func getURLPrefs(c *contextmodel.ReqContext) URLPrefs {
language := c.Query("lang")
theme := c.Query("theme")
locale := c.Query("locale")
regionalFormat := c.Query("regionalFormat")
return URLPrefs{
Language: language,
Locale: locale,
Theme: theme,
Language: language,
RegionalFormat: regionalFormat,
Theme: theme,
}
}
@ -70,7 +70,8 @@ func (hs *HTTPServer) setIndexViewData(c *contextmodel.ReqContext) (*dtos.IndexV
// translating words in the interface
acceptLangHeader := c.Req.Header.Get("Accept-Language")
locale := "en-US" // default to en formatting, but use the accept-lang header or user's preference
language := "" // frontend will set the default language
var regionalFormat string
language := "" // frontend will set the default language
urlPrefs := getURLPrefs(c)
if urlPrefs.Language != "" {
@ -85,11 +86,11 @@ func (hs *HTTPServer) setIndexViewData(c *contextmodel.ReqContext) (*dtos.IndexV
}
if hs.Features.IsEnabled(c.Req.Context(), featuremgmt.FlagLocaleFormatPreference) {
locale = "en" // default to "en", not "en-US", matching the locale code
if urlPrefs.Locale != "" {
locale = urlPrefs.Locale
} else if prefs.JSONData.Locale != "" {
locale = prefs.JSONData.Locale
regionalFormat = "en" // default to "en", not "en-US", matching the regionalFormat code
if urlPrefs.RegionalFormat != "" {
regionalFormat = urlPrefs.RegionalFormat
} else if prefs.JSONData.RegionalFormat != "" {
regionalFormat = prefs.JSONData.RegionalFormat
}
}
@ -140,7 +141,8 @@ func (hs *HTTPServer) setIndexViewData(c *contextmodel.ReqContext) (*dtos.IndexV
LightTheme: theme.Type == "light",
Timezone: prefs.Timezone,
WeekStart: weekStart,
Locale: locale,
Locale: locale, // << will be removed in favor of RegionalFormat
RegionalFormat: regionalFormat,
Language: language,
HelpFlags1: c.HelpFlags1,
HasEditPermissionInFolders: hasEditPerm,

@ -172,7 +172,7 @@ func (hs *HTTPServer) patchPreferencesFor(ctx context.Context, orgID, userID, te
HomeDashboardID: dtoCmd.HomeDashboardID, // nolint:staticcheck
HomeDashboardUID: dtoCmd.HomeDashboardUID,
Language: dtoCmd.Language,
Locale: dtoCmd.Locale,
RegionalFormat: dtoCmd.RegionalFormat,
QueryHistory: dtoCmd.QueryHistory,
CookiePreferences: dtoCmd.Cookies,
Navbar: dtoCmd.Navbar,

@ -26,7 +26,7 @@ type Spec struct {
// Selected language (beta)
Language *string `json:"language,omitempty"`
// Selected locale (beta)
Locale *string `json:"locale,omitempty"`
RegionalFormat *string `json:"regionalFormat,omitempty"`
// Explore query history preferences
QueryHistory *QueryHistoryPreference `json:"queryHistory,omitempty"`
// Cookie preferences

@ -68,7 +68,7 @@ type SavePreferenceCommand struct {
WeekStart string `json:"weekStart,omitempty"`
Theme string `json:"theme,omitempty"`
Language string `json:"language,omitempty"`
Locale string `json:"locale,omitempty"`
RegionalFormat string `json:"regionalFormat,omitempty"`
QueryHistory *QueryHistoryPreference `json:"queryHistory,omitempty"`
CookiePreferences []CookieType `json:"cookiePreferences,omitempty"`
Navbar *NavbarPreference `json:"navbar,omitempty"`
@ -86,7 +86,7 @@ type PatchPreferenceCommand struct {
WeekStart *string `json:"weekStart,omitempty"`
Theme *string `json:"theme,omitempty"`
Language *string `json:"language,omitempty"`
Locale *string `json:"locale,omitempty"`
RegionalFormat *string `json:"regionalFormat,omitempty"`
QueryHistory *QueryHistoryPreference `json:"queryHistory,omitempty"`
CookiePreferences []CookieType `json:"cookiePreferences,omitempty"`
Navbar *NavbarPreference `json:"navbar,omitempty"`
@ -94,7 +94,7 @@ type PatchPreferenceCommand struct {
type PreferenceJSONData struct {
Language string `json:"language"`
Locale string `json:"locale"`
RegionalFormat string `json:"regionalFormat"`
QueryHistory QueryHistoryPreference `json:"queryHistory"`
CookiePreferences map[string]struct{} `json:"cookiePreferences"`
Navbar NavbarPreference `json:"navbar"`

@ -62,7 +62,7 @@ func UpdatePreferencesFor(ctx context.Context,
}
if features.IsEnabled(ctx, featuremgmt.FlagLocaleFormatPreference) {
saveCmd.Locale = dtoCmd.Locale
saveCmd.RegionalFormat = dtoCmd.RegionalFormat
}
if err := preferenceService.Save(ctx, &saveCmd); err != nil {
@ -102,8 +102,8 @@ func GetPreferencesFor(ctx context.Context,
}
if features.IsEnabled(ctx, featuremgmt.FlagLocaleFormatPreference) {
if preference.JSONData.Locale != "" {
dto.Locale = &preference.JSONData.Locale
if preference.JSONData.RegionalFormat != "" {
dto.RegionalFormat = &preference.JSONData.RegionalFormat
}
}

@ -72,8 +72,8 @@ func (s *Service) GetWithDefaults(ctx context.Context, query *pref.GetPreference
res.JSONData.Language = p.JSONData.Language
}
if p.JSONData.Locale != "" {
res.JSONData.Locale = p.JSONData.Locale
if p.JSONData.RegionalFormat != "" {
res.JSONData.RegionalFormat = p.JSONData.RegionalFormat
}
if p.JSONData.QueryHistory.HomeTab != "" {
@ -192,11 +192,11 @@ func (s *Service) Patch(ctx context.Context, cmd *pref.PatchPreferenceCommand) e
preference.JSONData.Language = *cmd.Language
}
if cmd.Locale != nil {
if cmd.RegionalFormat != nil {
if preference.JSONData == nil {
preference.JSONData = &pref.PreferenceJSONData{}
}
preference.JSONData.Locale = *cmd.Locale
preference.JSONData.RegionalFormat = *cmd.RegionalFormat
}
if cmd.Navbar != nil && cmd.Navbar.BookmarkUrls != nil {
@ -296,8 +296,8 @@ func parseCookiePreferences(prefs []pref.CookieType) (map[string]struct{}, error
func preferenceData(cmd *pref.SavePreferenceCommand) (*pref.PreferenceJSONData, error) {
jsonData := &pref.PreferenceJSONData{
Language: cmd.Language,
Locale: cmd.Locale,
Language: cmd.Language,
RegionalFormat: cmd.RegionalFormat,
}
if cmd.Navbar != nil {
jsonData.Navbar = *cmd.Navbar

@ -94,8 +94,8 @@ func TestGetWithDefaults_withUserAndOrgPrefs(t *testing.T) {
WeekStart: &weekStartOne,
HomeDashboardUID: "test-uid",
JSONData: &pref.PreferenceJSONData{
Language: "en-GB",
Locale: "en",
Language: "en-GB",
RegionalFormat: "en",
},
},
pref.Preference{
@ -107,8 +107,8 @@ func TestGetWithDefaults_withUserAndOrgPrefs(t *testing.T) {
Timezone: "browser",
WeekStart: &weekStartTwo,
JSONData: &pref.PreferenceJSONData{
Language: "en-AU",
Locale: "es",
Language: "en-AU",
RegionalFormat: "es",
},
},
)
@ -124,8 +124,8 @@ func TestGetWithDefaults_withUserAndOrgPrefs(t *testing.T) {
HomeDashboardID: 4, // nolint:staticcheck
HomeDashboardUID: "test-uid4",
JSONData: &pref.PreferenceJSONData{
Language: "en-AU",
Locale: "es",
Language: "en-AU",
RegionalFormat: "es",
},
}
if diff := cmp.Diff(expected, preference); diff != "" {
@ -145,8 +145,8 @@ func TestGetWithDefaults_withUserAndOrgPrefs(t *testing.T) {
HomeDashboardID: 1, // nolint:staticcheck
HomeDashboardUID: "test-uid",
JSONData: &pref.PreferenceJSONData{
Language: "en-GB",
Locale: "en",
Language: "en-GB",
RegionalFormat: "en",
},
}
if diff := cmp.Diff(expected, preference); diff != "" {
@ -168,7 +168,7 @@ func TestGetDefaults_JSONData(t *testing.T) {
Language: "en-GB",
}
orgPreferencesWithLocaleJsonData := pref.PreferenceJSONData{
Locale: "en",
RegionalFormat: "en",
}
team2PreferencesJsonData := pref.PreferenceJSONData{}
team1PreferencesJsonData := pref.PreferenceJSONData{}
@ -254,8 +254,8 @@ func TestGetDefaults_JSONData(t *testing.T) {
require.Equal(t, &pref.Preference{
WeekStart: &weekStart,
JSONData: &pref.PreferenceJSONData{
Locale: "en",
QueryHistory: queryPreference,
RegionalFormat: "en",
QueryHistory: queryPreference,
},
}, preference)
})

@ -18052,15 +18052,15 @@
"language": {
"type": "string"
},
"locale": {
"type": "string"
},
"navbar": {
"$ref": "#/definitions/NavbarPreference"
},
"queryHistory": {
"$ref": "#/definitions/QueryHistoryPreference"
},
"regionalFormat": {
"type": "string"
},
"theme": {
"type": "string",
"enum": [
@ -18680,16 +18680,16 @@
"description": "Selected language (beta)",
"type": "string"
},
"locale": {
"description": "Selected locale (beta)",
"type": "string"
},
"navbar": {
"$ref": "#/definitions/NavbarPreference"
},
"queryHistory": {
"$ref": "#/definitions/QueryHistoryPreference"
},
"regionalFormat": {
"description": "Selected locale (beta)",
"type": "string"
},
"theme": {
"description": "light, dark, empty is default",
"type": "string"
@ -22296,15 +22296,15 @@
"language": {
"type": "string"
},
"locale": {
"type": "string"
},
"navbar": {
"$ref": "#/definitions/NavbarPreference"
},
"queryHistory": {
"$ref": "#/definitions/QueryHistoryPreference"
},
"regionalFormat": {
"type": "string"
},
"theme": {
"type": "string",
"enum": [

@ -127,7 +127,7 @@ export class GrafanaApp {
// Let iframe container know grafana has started loading
window.parent.postMessage('GrafanaAppInit', '*');
const regionalFormat = config.featureToggles.localeFormatPreference
? config.locale
? config.regionalFormat
: config.bootData.user.language;
const initI18nPromise = initializeI18n(
@ -149,7 +149,7 @@ export class GrafanaApp {
// This needs to be done after the `initEchoSrv` since it is being used under the hood.
startMeasure('frontend_app_init');
setLocale(config.locale);
setLocale(config.regionalFormat);
setWeekStart(config.bootData.user.weekStart);
setPanelRenderer(PanelRenderer);
setPluginPage(PluginPage);

@ -68,7 +68,7 @@ function getLanguageOptions(): ComboboxOption[] {
return options;
}
function getLocaleOptions(): ComboboxOption[] {
function getRegionalFormatOptions(): ComboboxOption[] {
const localeOptions = LOCALES.map((v) => ({
value: v.code,
label: v.name,
@ -90,7 +90,7 @@ export class SharedPreferences extends PureComponent<Props, State> {
service: PreferencesService;
themeOptions: ComboboxOption[];
languageOptions: ComboboxOption[];
localeOptions: ComboboxOption[];
regionalFormatOptions: ComboboxOption[];
constructor(props: Props) {
super(props);
@ -103,7 +103,7 @@ export class SharedPreferences extends PureComponent<Props, State> {
timezone: '',
weekStart: '',
language: '',
locale: '',
regionalFormat: '',
queryHistory: { homeTab: '' },
navbar: { bookmarkUrls: [] },
};
@ -118,7 +118,7 @@ export class SharedPreferences extends PureComponent<Props, State> {
group: theme.isExtra ? t('shared-preferences.theme.experimental', 'Experimental') : undefined,
}));
this.languageOptions = getLanguageOptions();
this.localeOptions = getLocaleOptions();
this.regionalFormatOptions = getRegionalFormatOptions();
// Add default option
this.themeOptions.unshift({ value: '', label: t('shared-preferences.theme.default-label', 'Default') });
@ -137,7 +137,7 @@ export class SharedPreferences extends PureComponent<Props, State> {
timezone: prefs.timezone,
weekStart: prefs.weekStart,
language: prefs.language,
locale: prefs.locale,
regionalFormat: prefs.regionalFormat,
queryHistory: prefs.queryHistory,
navbar: prefs.navbar,
});
@ -148,7 +148,8 @@ export class SharedPreferences extends PureComponent<Props, State> {
const confirmationResult = this.props.onConfirm ? await this.props.onConfirm() : true;
if (confirmationResult) {
const { homeDashboardUID, theme, timezone, weekStart, language, locale, queryHistory, navbar } = this.state;
const { homeDashboardUID, theme, timezone, weekStart, language, regionalFormat, queryHistory, navbar } =
this.state;
reportInteraction('grafana_preferences_save_button_clicked', {
preferenceType: this.props.preferenceType,
theme,
@ -162,7 +163,7 @@ export class SharedPreferences extends PureComponent<Props, State> {
timezone,
weekStart,
language,
locale,
regionalFormat,
queryHistory,
navbar,
})
@ -209,17 +210,18 @@ export class SharedPreferences extends PureComponent<Props, State> {
});
};
onLocaleChanged = (locale: string) => {
this.setState({ locale });
onLocaleChanged = (regionalFormat: string) => {
this.setState({ regionalFormat });
reportInteraction('grafana_preferences_locale_changed', {
toLocale: locale,
reportInteraction('grafana_preferences_regional_format_changed', {
toRegionalFormat: regionalFormat,
preferenceType: this.props.preferenceType,
});
};
render() {
const { theme, timezone, weekStart, homeDashboardUID, language, isLoading, isSubmitting, locale } = this.state;
const { theme, timezone, weekStart, homeDashboardUID, language, isLoading, isSubmitting, regionalFormat } =
this.state;
const { disabled } = this.props;
const styles = getStyles();
const currentThemeOption = this.themeOptions.find((x) => x.value === theme) ?? this.themeOptions[0];
@ -343,9 +345,9 @@ export class SharedPreferences extends PureComponent<Props, State> {
data-testid="User preferences locale drop down"
>
<Combobox
value={this.localeOptions.find((loc) => loc.value === locale)?.value || ''}
value={this.regionalFormatOptions.find((loc) => loc.value === regionalFormat)?.value || ''}
onChange={(locale: ComboboxOption | null) => this.onLocaleChanged(locale?.value ?? '')}
options={this.localeOptions}
options={this.regionalFormatOptions}
placeholder={t('shared-preferences.fields.locale-preference-placeholder', 'Choose region')}
id="locale-preference-select"
/>

@ -22,7 +22,7 @@ export const formatDate = deepMemoize(
return formatDate(new Date(value), format);
}
const currentLocale = isLocaleEnabled ? config.locale : getLanguage();
const currentLocale = isLocaleEnabled ? config.regionalFormat : getLanguage();
const dateFormatter = createDateTimeFormatter(currentLocale, format);
return dateFormatter.format(value);
@ -31,7 +31,7 @@ export const formatDate = deepMemoize(
export const formatDuration = deepMemoize(
(duration: Intl.DurationInput, options: Intl.DurationFormatOptions = {}): string => {
const currentLocale = isLocaleEnabled ? config.locale : getLanguage();
const currentLocale = isLocaleEnabled ? config.regionalFormat : getLanguage();
const dateFormatter = createDurationFormatter(currentLocale, options);
return dateFormatter.format(duration);

@ -38,7 +38,7 @@ export class User implements Omit<CurrentUserInternal, 'lightTheme'> {
gravatarUrl: string;
timezone: string;
weekStart: string;
locale: string;
regionalFormat: string;
language: string;
helpFlags1: number;
hasEditPermissionInFolders: boolean;
@ -65,7 +65,7 @@ export class User implements Omit<CurrentUserInternal, 'lightTheme'> {
this.hasEditPermissionInFolders = false;
this.email = '';
this.name = '';
this.locale = '';
this.regionalFormat = '';
this.language = '';
this.weekStart = '';
this.gravatarUrl = '';

@ -8102,15 +8102,15 @@
"language": {
"type": "string"
},
"locale": {
"type": "string"
},
"navbar": {
"$ref": "#/components/schemas/NavbarPreference"
},
"queryHistory": {
"$ref": "#/components/schemas/QueryHistoryPreference"
},
"regionalFormat": {
"type": "string"
},
"theme": {
"enum": [
"light",
@ -8730,16 +8730,16 @@
"description": "Selected language (beta)",
"type": "string"
},
"locale": {
"description": "Selected locale (beta)",
"type": "string"
},
"navbar": {
"$ref": "#/components/schemas/NavbarPreference"
},
"queryHistory": {
"$ref": "#/components/schemas/QueryHistoryPreference"
},
"regionalFormat": {
"description": "Selected locale (beta)",
"type": "string"
},
"theme": {
"description": "light, dark, empty is default",
"type": "string"
@ -12345,15 +12345,15 @@
"language": {
"type": "string"
},
"locale": {
"type": "string"
},
"navbar": {
"$ref": "#/components/schemas/NavbarPreference"
},
"queryHistory": {
"$ref": "#/components/schemas/QueryHistoryPreference"
},
"regionalFormat": {
"type": "string"
},
"theme": {
"enum": [
"light",

Loading…
Cancel
Save