mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Extending default locale list
Summary: Adding more locale codes to support more countries in document settings Test Plan: existing tests Reviewers: dsagal Reviewed By: dsagal Subscribers: dsagal Differential Revision: https://phab.getgrist.com/D3018
This commit is contained in:
@@ -14,13 +14,12 @@ import {DocPageModel} from 'app/client/models/DocPageModel';
|
||||
import {testId, vars} from 'app/client/ui2018/cssVars';
|
||||
import {select} from 'app/client/ui2018/menus';
|
||||
import {saveModal} from 'app/client/ui2018/modals';
|
||||
import {buildCurrencyPicker} from 'app/client/widgets/CurrencyPicker';
|
||||
import {buildTZAutocomplete} from 'app/client/widgets/TZAutocomplete';
|
||||
import {EngineCode} from 'app/common/DocumentSettings';
|
||||
import {GristLoadConfig} from 'app/common/gristUrls';
|
||||
import {locales} from "app/common/Locales";
|
||||
import {buildCurrencyPicker} from 'app/client/widgets/CurrencyPicker';
|
||||
import * as LocaleCurrency from 'locale-currency';
|
||||
|
||||
import {propertyCompare} from "app/common/gutil";
|
||||
import {getCurrency, locales} from "app/common/Locales";
|
||||
/**
|
||||
* Builds a simple saveModal for saving settings.
|
||||
*/
|
||||
@@ -50,7 +49,7 @@ export async function showDocSettingsModal(docInfo: DocInfoRec, docPageModel: Do
|
||||
cssDataRow('Currency:'),
|
||||
cssDataRow(dom.domComputed(localeObs, (l) =>
|
||||
dom.create(buildCurrencyPicker, currencyObs, (val) => currencyObs.set(val),
|
||||
{defaultCurrencyLabel: `Local currency (${LocaleCurrency.getCurrency(l)})`})
|
||||
{defaultCurrencyLabel: `Local currency (${getCurrency(l)})`})
|
||||
)),
|
||||
canChangeEngine ? [
|
||||
cssDataRow('Engine:'),
|
||||
@@ -101,7 +100,7 @@ function buildLocaleSelect(
|
||||
label: l.name,
|
||||
locale: l.code,
|
||||
cleanText: l.name.trim().toLowerCase(),
|
||||
}));
|
||||
})).sort(propertyCompare("label"));
|
||||
const acIndex = new ACIndexImpl<LocaleItem>(localeList, 200, true);
|
||||
// AC select will show the value (in this case locale) not a label when something is selected.
|
||||
// To show the label - create another observable that will be in sync with the value, but
|
||||
|
||||
36
app/common/LocaleCodes.ts
Normal file
36
app/common/LocaleCodes.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
// This file was generated by core/buildtools/generate_locale_list.js at 2021-09-23T08:32:25.517Z
|
||||
export const localeCodes = [
|
||||
"af-ZA", "ak-GH", "am-ET", "ar-AE", "ar-BH", "ar-DZ", "ar-EG",
|
||||
"ar-IN", "ar-IQ", "ar-JO", "ar-KW", "ar-LB", "ar-LY", "ar-MA",
|
||||
"ar-OM", "ar-QA", "ar-SA", "ar-SD", "ar-SS", "ar-SY", "ar-TN",
|
||||
"ar-YE", "as-IN", "ast-ES", "az-AZ", "az-IR", "be-BY", "bem-ZM",
|
||||
"bg-BG", "bn-BD", "bn-IN", "bo-CN", "bo-IN", "br-FR", "brx-IN",
|
||||
"bs-BA", "ca-AD", "ca-ES", "ca-FR", "ca-IT", "ce-RU", "chr-US",
|
||||
"ckb-IQ", "cs-CZ", "cy-GB", "da-DK", "de-AT", "de-BE", "de-CH",
|
||||
"de-DE", "de-IT", "de-LI", "de-LU", "doi-IN", "dz-BT", "el-CY",
|
||||
"el-GR", "en-AG", "en-AU", "en-BW", "en-CA", "en-DK", "en-GB",
|
||||
"en-HK", "en-IE", "en-IL", "en-IN", "en-NG", "en-NZ", "en-PH",
|
||||
"en-SC", "en-SG", "en-US", "en-ZA", "en-ZM", "en-ZW", "es-AR",
|
||||
"es-BO", "es-CL", "es-CO", "es-CR", "es-CU", "es-DO", "es-EC",
|
||||
"es-ES", "es-GT", "es-HN", "es-MX", "es-NI", "es-PA", "es-PE",
|
||||
"es-PR", "es-PY", "es-SV", "es-US", "es-UY", "es-VE", "et-EE",
|
||||
"eu-ES", "fa-IR", "ff-SN", "fi-FI", "fil-PH", "fo-FO", "fr-BE",
|
||||
"fr-CA", "fr-CH", "fr-FR", "fr-LU", "fur-IT", "fy-DE", "fy-NL",
|
||||
"ga-IE", "gd-GB", "gl-ES", "gu-IN", "gv-GB", "ha-NG", "he-IL",
|
||||
"hi-IN", "hr-HR", "hsb-DE", "hu-HU", "hy-AM", "ia-FR", "id-ID",
|
||||
"ig-NG", "is-IS", "it-CH", "it-IT", "ja-JP", "kab-DZ", "ka-GE",
|
||||
"kk-KZ", "kl-GL", "km-KH", "kn-IN", "kok-IN", "ko-KR", "ks-IN",
|
||||
"ku-TR", "kw-GB", "ky-KG", "lb-LU", "lg-UG", "ln-CD", "lo-LA",
|
||||
"lt-LT", "lv-LV", "mai-IN", "mai-NP", "mfe-MU", "mg-MG", "mi-NZ",
|
||||
"mk-MK", "ml-IN", "mni-IN", "mn-MN", "mr-IN", "ms-MY", "mt-MT",
|
||||
"my-MM", "ne-NP", "nl-AW", "nl-BE", "nl-NL", "nn-NO", "om-ET",
|
||||
"om-KE", "or-IN", "os-RU", "pa-IN", "pa-PK", "pl-PL", "ps-AF",
|
||||
"pt-BR", "pt-PT", "ro-RO", "ru-RU", "ru-UA", "rw-RW", "sa-IN",
|
||||
"sat-IN", "sd-IN", "se-NO", "si-LK", "sk-SK", "sl-SI", "so-DJ",
|
||||
"so-ET", "so-KE", "so-SO", "sq-AL", "sq-MK", "sr-ME", "sr-RS",
|
||||
"sv-FI", "sv-SE", "sw-KE", "sw-TZ", "ta-IN", "ta-LK", "te-IN",
|
||||
"tg-TJ", "th-TH", "ti-ER", "ti-ET", "tk-TM", "to-TO", "tr-CY",
|
||||
"tr-TR", "tt-RU", "ug-CN", "uk-UA", "ur-IN", "ur-PK", "uz-UZ",
|
||||
"vi-VN", "wae-CH", "wo-SN", "xh-ZA", "yi-US", "yo-NG", "yue-HK",
|
||||
"zh-CN", "zh-HK", "zh-SG", "zh-TW", "zu-ZA"
|
||||
];
|
||||
@@ -1,16 +1,9 @@
|
||||
import LocaleCurrency = require('locale-currency/map');
|
||||
import * as LocaleCurrencyMap from 'locale-currency/map';
|
||||
import * as LocaleCurrency from 'locale-currency';
|
||||
import {nativeCompare} from 'app/common/gutil';
|
||||
import {localeCodes} from "app/common/LocaleCodes";
|
||||
|
||||
const localeCodes = [
|
||||
"es-AR", "hy-AM", "en-AU", "az-AZ", "be-BY", "quz-BO", "pt-BR",
|
||||
"bg-BG", "en-CA", "arn-CL", "es-CO", "hr-HR", "cs-CZ", "da-DK",
|
||||
"es-EC", "ar-EG", "fi-FI", "fr-FR", "ka-GE", "de-DE", "el-GR", "en-HK",
|
||||
"hu-HU", "hi-IN", "id-ID", "ga-IE", "ar-IL", "it-IT", "ja-JP", "kk-KZ",
|
||||
"lv-LV", "lt-LT", "es-MX", "mn-MN", "my-MM", "nl-NL", "nb-NO",
|
||||
"es-PY", "ceb-PH", "pl-PL", "pt-PT", "ro-RO", "ru-RU", "sr-RS",
|
||||
"sk-SK", "sl-SI", "ko-KR", "es-ES", "sv-SE", "de-CH", "zh-TW", "th-TH",
|
||||
"tr-TR", "uk-UA", "en-GB", "en-US", "es-UY", "es-VE", "vi-VN"
|
||||
];
|
||||
const DEFAULT_CURRENCY = "USD";
|
||||
|
||||
export interface Locale {
|
||||
name: string;
|
||||
@@ -21,13 +14,27 @@ export let locales: Readonly<Locale[]>;
|
||||
|
||||
// Intl.DisplayNames is only supported on recent browsers, so proceed with caution.
|
||||
try {
|
||||
const localeDisplay = new Intl.DisplayNames('en', {type: 'region'});
|
||||
locales = localeCodes.map(code => {
|
||||
return { name: localeDisplay.of(new Intl.Locale(code).region), code };
|
||||
const regionDisplay = new Intl.DisplayNames('en', {type: 'region'});
|
||||
const languageDisplay = new Intl.DisplayNames('en', {type: 'language'});
|
||||
const display = (code: string) => {
|
||||
try {
|
||||
const locale = new Intl.Locale(code);
|
||||
const regionName = regionDisplay.of(locale.region);
|
||||
const languageName = languageDisplay.of(locale.language);
|
||||
return `${regionName} (${languageName})`;
|
||||
} catch (ex) {
|
||||
return code;
|
||||
}
|
||||
};
|
||||
// Leave only those that are supported by current system (can be translated to human readable form).
|
||||
// Though, this file is in common, it is safe to filter by current system
|
||||
// as the list should be already filtered by codes that are supported by the backend.
|
||||
locales = Intl.DisplayNames.supportedLocalesOf(localeCodes).map(code => {
|
||||
return {name: display(code), code};
|
||||
});
|
||||
} catch {
|
||||
// Fall back to using the locale code as the display name.
|
||||
locales = localeCodes.map(code => ({ name: code, code }));
|
||||
locales = localeCodes.map(code => ({name: code, code}));
|
||||
}
|
||||
|
||||
export interface Currency {
|
||||
@@ -37,16 +44,26 @@ export interface Currency {
|
||||
|
||||
export let currencies: Readonly<Currency[]>;
|
||||
|
||||
// locale-currency package doesn't have South Sudanese pound currency or a default value for Kosovo
|
||||
LocaleCurrencyMap["SS"] = "SSP";
|
||||
LocaleCurrencyMap["XK"] = "EUR";
|
||||
const currenciesCodes = Object.values(LocaleCurrencyMap);
|
||||
export function getCurrency(code: string) {
|
||||
const currency = LocaleCurrency.getCurrency(code);
|
||||
// Fallback to USD
|
||||
return currency ?? DEFAULT_CURRENCY;
|
||||
}
|
||||
|
||||
// Intl.DisplayNames is only supported on recent browsers, so proceed with caution.
|
||||
try {
|
||||
const currencyDisplay = new Intl.DisplayNames('en', {type: 'currency'});
|
||||
currencies = [...new Set(Object.values(LocaleCurrency))].map(code => {
|
||||
return { name: currencyDisplay.of(code), code };
|
||||
currencies = [...new Set(currenciesCodes)].map(code => {
|
||||
return {name: currencyDisplay.of(code), code};
|
||||
});
|
||||
} catch {
|
||||
// Fall back to using the currency code as the display name.
|
||||
currencies = [...new Set(Object.values(LocaleCurrency))].map(code => {
|
||||
return { name: code, code };
|
||||
currencies = [...new Set(currenciesCodes)].map(code => {
|
||||
return {name: code, code};
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
2
app/common/declarations.d.ts
vendored
2
app/common/declarations.d.ts
vendored
@@ -12,12 +12,14 @@ declare module "locale-currency/map" {
|
||||
|
||||
declare namespace Intl {
|
||||
class DisplayNames {
|
||||
public static supportedLocalesOf(locales: string | string[]): string[];
|
||||
constructor(locales?: string, options?: object);
|
||||
public of(code: string): string;
|
||||
}
|
||||
|
||||
class Locale {
|
||||
public region: string;
|
||||
public language: string;
|
||||
constructor(locale: string);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -487,6 +487,15 @@ export function nativeCompare<T>(a: T, b: T): number {
|
||||
return (a < b ? -1 : (a > b ? 1 : 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a function that compares objects by a property value.
|
||||
*/
|
||||
export function propertyCompare<T>(property: keyof T) {
|
||||
return function(a: T, b: T) {
|
||||
return nativeCompare(a[property], b[property]);
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: In the future, locale should be a value associated with the document or the user.
|
||||
export const defaultLocale = 'en-US';
|
||||
export const defaultCollator = new Intl.Collator(defaultLocale);
|
||||
|
||||
Reference in New Issue
Block a user