diff --git a/build_data.js b/build_data.js index d0cf1c234..6dbc02259 100644 --- a/build_data.js +++ b/build_data.js @@ -70,6 +70,7 @@ module.exports = function buildData() { 'data/presets/presets.json', 'data/presets.yaml', 'data/taginfo.json', + 'data/territory-languages.json', 'dist/locales/en.json', 'svg/fontawesome/*.svg', ]); @@ -80,6 +81,7 @@ module.exports = function buildData() { var defaults = read('data/presets/defaults.json'); var translations = generateTranslations(fields, presets, tstrings); var taginfo = generateTaginfo(presets, fields); + var territoryLanguages = generateTerritoryLanguages(); // Additional consistency checks validateCategoryPresets(categories, presets); @@ -108,6 +110,10 @@ module.exports = function buildData() { 'data/taginfo.json', prettyStringify(taginfo, { maxLength: 9999 }) ), + writeFileProm( + 'data/territory-languages.json', + prettyStringify({ dataTerritoryLanguages: territoryLanguages }, { maxLength: 9999 }) + ), writeEnJson(tstrings), writeFaIcons(faIcons), writeTnpIcons(tnpIcons) @@ -564,6 +570,23 @@ function generateTaginfo(presets, fields) { return taginfo; } +function generateTerritoryLanguages() { + var allRawInfo = read('./node_modules/cldr-core/supplemental/territoryInfo.json').supplemental.territoryInfo; + var territoryLanguages = {}; + Object.keys(allRawInfo).forEach(function(territoryCode) { + var territoryLangInfo = allRawInfo[territoryCode].languagePopulation; + if (!territoryLangInfo) return; + var langCodes = Object.keys(territoryLangInfo); + territoryLanguages[territoryCode.toLowerCase()] = langCodes.sort(function(langCode1, langCode2) { + return parseFloat(territoryLangInfo[langCode2]._populationPercent) - + parseFloat(territoryLangInfo[langCode1]._populationPercent); + }).map(function(langCode) { + return langCode.replace('_', '-'); + }); + }); + return territoryLanguages; +} + function validateCategoryPresets(categories, presets) { Object.keys(categories).forEach(function(id) { var category = categories[id]; diff --git a/data/index.js b/data/index.js index 8e3119098..f38a9f8a5 100644 --- a/data/index.js +++ b/data/index.js @@ -7,6 +7,7 @@ export { dataLanguages } from './languages.json'; export { dataLocales } from './locales.json'; export { dataPhoneFormats } from './phone-formats.json'; export { dataShortcuts } from './shortcuts.json'; +export { dataTerritoryLanguages } from './territory-languages.json'; export { default as dataImperial } from './imperial.json'; export { default as dataMPH } from './mph.json'; diff --git a/data/territory-languages.json b/data/territory-languages.json new file mode 100644 index 000000000..918445e7d --- /dev/null +++ b/data/territory-languages.json @@ -0,0 +1,260 @@ +{ + "dataTerritoryLanguages": { + "ac": ["en"], + "ad": ["ca", "es", "fr"], + "ae": ["ar", "en", "ml", "ps", "bal", "fa"], + "af": ["fa", "ps", "haz", "uz-Arab", "tk", "prd", "bal", "bgn", "ug", "kk-Arab"], + "ag": ["en", "pt"], + "ai": ["en"], + "al": ["sq", "el", "mk"], + "am": ["hy", "ku", "az"], + "ao": ["pt", "umb", "kmb", "ln"], + "aq": ["und"], + "ar": ["es", "en", "cy", "gn"], + "as": ["sm", "en"], + "at": ["de", "bar", "en", "fr", "it", "hr", "sl", "hu"], + "au": ["en", "zh-Hant", "it", "wbp"], + "aw": ["nl", "pap", "en"], + "ax": ["sv"], + "az": ["az", "az-Cyrl", "tly", "ku", "ttt", "tkr"], + "ba": ["bs", "bs-Cyrl", "en", "hr", "sr", "sr-Latn"], + "bb": ["en"], + "bd": ["bn", "en", "rkt", "syl", "ccp", "my", "grt", "mro", "mni"], + "be": ["en", "nl", "fr", "de", "vls", "wa"], + "bf": ["mos", "dyu", "fr", "ff", "ff-Adlm"], + "bg": ["bg", "en", "ru", "tr", "de"], + "bh": ["ar", "ml"], + "bi": ["rn", "fr", "sw", "en"], + "bj": ["fr", "fon", "yo"], + "bl": ["fr"], + "bm": ["en"], + "bn": ["ms", "zh-Hant", "ms-Arab", "en"], + "bo": ["es", "qu", "ay", "gn", "aro"], + "bq": ["pap", "nl"], + "br": ["pt", "en", "de", "it", "ja", "es", "ko", "kgp", "gub", "yrl", "xav"], + "bs": ["en"], + "bt": ["dz", "ne", "tsj", "en", "lep"], + "bv": ["und"], + "bw": ["en", "tn", "af"], + "by": ["be", "ru"], + "bz": ["en", "es"], + "ca": ["en", "fr", "it", "de", "pdt", "cr", "crk", "yi", "iu", "iu-Latn", "moe", "crj", "atj", "crl", "csw", "crm", "ikt", "moh", "dgr", "den", "scs", "nsk", "chp", "gwi"], + "cc": ["ms-Arab", "en"], + "cd": ["sw", "lua", "fr", "ln", "lu", "kg", "lol", "rw"], + "cf": ["fr", "sg", "ln"], + "cg": ["fr", "ln"], + "ch": ["de", "gsw", "en", "fr", "it", "lmo", "pt", "rm", "rmo", "wae"], + "ci": ["fr", "bci", "sef", "dnj", "kfo", "bqv"], + "ck": ["en"], + "cl": ["es", "en", "arn"], + "cm": ["fr", "en", "bum", "ff", "ewo", "ybb", "nnh", "bbj", "bkm", "bax", "bas", "byv", "mua", "maf", "bfd", "bss", "kkj", "dua", "mgo", "ar", "jgo", "ksf", "agq", "ha-Arab", "nmg", "yav", "ff-Adlm"], + "cn": ["zh", "wuu", "yue-Hans", "hsn", "hak", "nan", "gan", "ii", "ug", "za", "mn-Mong", "bo", "ko", "kk-Arab", "lis", "ky-Arab", "nxq", "khb", "tdd", "lcp", "en", "ru", "vi", "uz-Cyrl", "lzh"], + "co": ["es", "guc"], + "cp": ["und"], + "cr": ["es"], + "cu": ["es"], + "cv": ["kea", "pt"], + "cw": ["pap", "nl", "es"], + "cx": ["en"], + "cy": ["el", "en", "tr", "fr", "hy", "ar"], + "cz": ["cs", "en", "sk", "de", "pl"], + "de": ["de", "en", "fr", "bar", "nds", "nl", "it", "vmf", "ru", "es", "tr", "gsw", "da", "swg", "hr", "ku", "el", "ksh", "pl", "hsb", "frr", "dsb", "frs", "stq", "pfl"], + "dg": ["en"], + "dj": ["aa", "so", "ar", "fr"], + "dk": ["da", "en", "de", "sv", "fo", "kl", "jut"], + "dm": ["en"], + "do": ["es", "en"], + "dz": ["arq", "ar", "fr", "kab", "en"], + "ea": ["es"], + "ec": ["es", "qu", "qug"], + "ee": ["et", "ru", "en", "fi", "vro"], + "eg": ["ar", "arz", "en", "el"], + "eh": ["ar"], + "er": ["ti", "en", "tig", "ar", "aa", "ssy", "byn"], + "es": ["es", "en", "ca", "gl", "eu", "ast", "ext"], + "et": ["en", "am", "om", "so", "ti", "sid", "wal", "aa"], + "fi": ["fi", "en", "sv", "de", "ru", "et", "rmf", "se", "smn", "sms"], + "fj": ["en", "hi", "hif", "fj", "rtm"], + "fk": ["en"], + "fm": ["en", "chk", "pon", "kos", "yap", "uli"], + "fo": ["fo"], + "fr": ["fr", "en", "es", "de", "oc", "it", "pt", "pcd", "gsw", "br", "co", "ca", "nl", "eu", "frp", "ia"], + "ga": ["fr", "puu"], + "gb": ["en", "fr", "de", "sco", "pa", "cy", "bn", "zh-Hant", "syl", "el", "it", "ks", "gd", "yi", "ml", "ga", "kw"], + "gd": ["en"], + "ge": ["ka", "xmf", "ru", "hy", "ab", "os", "ku"], + "gf": ["fr", "gcr", "zh-Hant"], + "gg": ["en"], + "gh": ["ak", "en", "ee", "abr", "gur", "ada", "gaa", "nzi", "ha", "saf", "ff", "ff-Adlm"], + "gi": ["en", "es"], + "gl": ["kl", "da"], + "gm": ["en", "man", "ff", "ff-Adlm"], + "gn": ["fr", "ff", "man-Nkoo", "sus", "nqo", "kpe", "ff-Adlm"], + "gp": ["fr"], + "gq": ["es", "fan", "fr", "bvb", "pt"], + "gr": ["el", "en", "fr", "de", "pnt", "mk", "tr", "bg", "sq", "tsd"], + "gs": ["und"], + "gt": ["es", "quc"], + "gu": ["en", "ch"], + "gw": ["pt", "knf", "ff", "ff-Adlm"], + "gy": ["en"], + "hk": ["zh-Hant", "yue", "en", "zh"], + "hm": ["und"], + "hn": ["es", "en"], + "hr": ["hr", "en", "it"], + "ht": ["ht", "fr"], + "hu": ["hu", "en", "de", "fr", "ro", "hr", "sk", "sl"], + "ic": ["es"], + "id": ["id", "jv", "su", "mad", "ms-Arab", "min", "bew", "ban", "bug", "bjn", "ace", "sas", "zh-Hant", "bbc", "mak", "ljp", "rej", "gor", "nij", "kge", "aoz", "kvr", "lbw", "gay", "rob", "mdr", "sxn", "sly", "mwv"], + "ie": ["en", "ga", "fr"], + "il": ["he", "en", "ar", "ru", "ro", "yi", "pl", "lad", "hu", "am", "ti", "ml"], + "im": ["en", "gv"], + "in": ["hi", "en", "bn", "te", "mr", "ta", "ur", "gu", "kn", "ml", "or", "pa", "bho", "awa", "as", "mwr", "bgc", "mag", "mai", "hne", "dcc", "ne", "bjj", "sat", "wtm", "rkt", "ks", "kok", "gom", "swv", "gbm", "lmn", "sd", "gon", "kfy", "doi", "kru", "sck", "wbq", "xnr", "tcy", "wbr", "khn", "brx", "noe", "bhb", "mni", "hoc", "raj", "mtr", "unr", "bhi", "hoj", "kha", "kfr", "grt", "unx", "bfy", "srx", "saz", "ccp", "sd-Deva", "njo", "bfq", "ria", "bo", "bpy", "bft", "bra", "lep", "btv", "lif", "lah", "sa", "kht", "dv", "dz"], + "io": ["en"], + "iq": ["ar", "en", "ckb", "az-Arab", "fa", "lrc", "syr"], + "ir": ["fa", "az-Arab", "mzn", "glk", "ckb", "sdh", "tk", "lrc", "bal", "ar", "rmt", "bqi", "luz", "lki", "bgn", "prd", "hy", "ps", "ka", "gbz", "kk-Arab"], + "is": ["is", "da"], + "it": ["it", "en", "fr", "sc", "de", "vec", "nap", "lij", "scn", "sdc", "sl", "fur", "egl", "ca", "el", "lmo", "pms", "hr", "rgn"], + "je": ["en"], + "jm": ["en", "jam"], + "jo": ["ar", "en"], + "jp": ["ja", "ryu", "ko"], + "ke": ["sw", "en", "ki", "luy", "luo", "kam", "kln", "guz", "mer", "mas", "ebu", "so", "dav", "teo", "pko", "om", "saq", "ar", "pa", "gu"], + "kg": ["ky", "ru"], + "kh": ["km", "cja", "kdt"], + "ki": ["en", "gil"], + "km": ["ar", "fr", "zdj", "wni"], + "kn": ["en"], + "kp": ["ko"], + "kr": ["ko"], + "kw": ["ar"], + "ky": ["en"], + "kz": ["ru", "kk", "en", "de", "ug-Cyrl"], + "la": ["lo", "kjg", "kdt"], + "lb": ["ar", "en", "hy", "ku-Arab", "fr"], + "lc": ["en"], + "li": ["de", "gsw", "wae"], + "lk": ["si", "ta", "en"], + "lr": ["en", "kpe", "vai", "men", "ff", "ff-Adlm", "vai-Latn"], + "ls": ["st", "en", "zu", "ss", "xh"], + "lt": ["lt", "ru", "en", "de", "sgs"], + "lu": ["fr", "lb", "de", "en", "pt"], + "lv": ["lv", "en", "ru", "ltg"], + "ly": ["ar"], + "ma": ["ary", "ar", "zgh", "fr", "en", "tzm", "shi", "shi-Latn", "rif-Latn", "rif", "es"], + "mc": ["fr"], + "md": ["ro", "uk", "bg", "gag", "ru"], + "me": ["sr-Latn", "sq", "sr"], + "mf": ["fr"], + "mg": ["mg", "fr", "en"], + "mh": ["en", "mh"], + "mk": ["mk", "sq", "tr"], + "ml": ["fr", "bm", "ffm", "snk", "mwk", "ses", "tmh", "bm-Nkoo", "khq", "dtm", "kao", "ar", "bmq", "bze"], + "mm": ["my", "shn", "kac", "mnw", "kht"], + "mn": ["mn", "kk-Arab", "zh", "ru", "ug-Cyrl"], + "mo": ["zh-Hant", "pt", "zh", "en"], + "mp": ["en", "ch"], + "mq": ["fr"], + "mr": ["ar", "fr", "ff", "wo", "ff-Adlm"], + "ms": ["en"], + "mt": ["mt", "en", "it", "fr"], + "mu": ["mfe", "en", "bho", "ur", "fr", "ta"], + "mv": ["dv"], + "mw": ["en", "ny", "tum", "tog", "zu"], + "mx": ["es", "en", "yua", "nhe", "nhw", "maz", "nch", "sei"], + "my": ["ms", "en", "zh-Hant", "ta", "iba", "jv", "zmi", "dtp", "ml", "bug", "bjn"], + "mz": ["pt", "vmw", "ndc", "ts", "ngl", "seh", "mgh", "rng", "ny", "yao", "sw", "zu"], + "na": ["af", "kj", "ng", "naq", "hz", "en", "de", "tn"], + "nc": ["fr"], + "ne": ["ha", "fr", "dje", "fuq", "tmh", "ar", "twq", "ff", "ff-Adlm"], + "nf": ["en"], + "ng": ["en", "pcm", "ha", "ig", "yo", "fuv", "tiv", "ibb", "efi", "ha-Arab", "bin", "kaj", "kcg", "ar", "cch", "amo", "ff", "ff-Adlm"], + "ni": ["es"], + "nl": ["nl", "en", "de", "fr", "nds", "li", "fy", "gos", "id", "zea", "rif-Latn", "tr"], + "no": ["nb", "nn", "se"], + "np": ["ne", "mai", "bho", "taj", "new", "jml", "en", "dty", "awa", "thl", "bap", "tdg", "thr", "mgp", "lif", "thq", "mrd", "gvr", "bfy", "xsr", "rjs", "hi", "bo", "tkt", "tdh", "bn", "unr-Deva", "lep"], + "nr": ["en", "na"], + "nu": ["en", "niu"], + "nz": ["en", "mi"], + "om": ["ar", "bal", "fa"], + "pa": ["es", "en", "zh-Hant"], + "pe": ["es", "qu", "ay"], + "pf": ["fr", "ty", "zh-Hant"], + "pg": ["tpi", "en", "ho"], + "ph": ["en", "fil", "es", "ceb", "ilo", "hil", "bik", "war", "pam", "bhk", "pag", "mdh", "tsg", "zh-Hant", "cps", "krj", "bto", "hnn", "tbw", "bku"], + "pk": ["ur", "pa-Arab", "en", "lah", "ps", "sd", "skr", "bal", "brh", "hno", "fa", "bgn", "hnd", "tg-Arab", "gju", "bft", "kvx", "khw", "mvy", "kxp", "gjk", "ks", "btv"], + "pl": ["pl", "en", "de", "ru", "szl", "be", "uk", "csb", "sli", "lt"], + "pm": ["fr", "en"], + "pn": ["en"], + "pr": ["es", "en"], + "ps": ["ar"], + "pt": ["pt", "en", "fr", "es", "gl"], + "pw": ["pau", "en"], + "py": ["gn", "es", "de"], + "qa": ["ar", "fa", "ml"], + "re": ["fr", "rcf", "ta"], + "ro": ["ro", "en", "fr", "es", "hu", "de", "tr", "sr-Latn", "bg", "el", "pl"], + "rs": ["sr", "sr-Latn", "sq", "hu", "ro", "hr", "sk", "uk"], + "ru": ["ru", "tt", "ba", "cv", "hy", "ce", "av", "udm", "chm", "os", "sah", "kbd", "myv", "dar", "bua", "mdf", "kum", "lez", "kv", "krc", "inh", "tyv", "az-Cyrl", "ady", "krl", "lbe", "koi", "mrj", "alt", "fi", "sr-Latn", "vep", "mn", "izh", "cu", "vot"], + "rw": ["rw", "en", "fr"], + "sa": ["ar"], + "sb": ["en", "rug"], + "sc": ["crs", "fr", "en"], + "sd": ["ar", "en", "bej", "fvr", "ha-Arab", "mls", "fia", "zag"], + "se": ["sv", "en", "fi", "fit", "se", "rmu", "yi", "smj", "sma", "ia"], + "sg": ["en", "zh", "ms", "ta", "ml", "pa"], + "sh": ["en"], + "si": ["sl", "hr", "en", "de", "hu", "it"], + "sj": ["nb", "ru"], + "sk": ["sk", "cs", "en", "de", "hu", "uk", "pl"], + "sl": ["kri", "en", "men", "tem", "ff", "ff-Adlm"], + "sm": ["it", "eo"], + "sn": ["wo", "fr", "ff", "srr", "dyo", "sav", "mfv", "bjt", "snf", "knf", "bsc", "mey", "tnr", "ff-Adlm"], + "so": ["so", "ar", "sw", "om"], + "sr": ["nl", "srn", "zh-Hant"], + "ss": ["ar", "en", "nus"], + "st": ["pt"], + "sv": ["es"], + "sx": ["en", "es", "vic", "nl"], + "sy": ["ar", "ku", "fr", "hy", "syr"], + "sz": ["en", "ss", "zu", "ts"], + "ta": ["en"], + "tc": ["en"], + "td": ["fr", "ar"], + "tf": ["fr"], + "tg": ["fr", "ee", "ife"], + "th": ["th", "en", "tts", "nod", "sou", "mfa", "zh-Hant", "kxm", "kdt", "mnw", "shn", "lwl", "lcp"], + "tj": ["tg", "ru", "fa", "ar"], + "tk": ["en", "tkl"], + "tl": ["pt", "tet"], + "tm": ["tk", "ru", "uz", "ku"], + "tn": ["aeb", "ar", "fr"], + "to": ["to", "en"], + "tr": ["tr", "en", "ku", "zza", "kbd", "az", "az-Arab", "ar", "bgx", "bg", "ady", "kiu", "ka", "hy", "lzz", "sr-Latn", "sq", "el", "ab", "tru", "uz", "ky-Latn", "kk"], + "tt": ["en", "es"], + "tv": ["tvl", "en"], + "tw": ["zh-Hant", "trv"], + "tz": ["sw", "en", "suk", "nym", "kde", "ksb", "bez", "mas", "mgy", "asa", "lag", "rof", "jmc", "vun", "rwk", "sbp"], + "ua": ["uk", "ru", "pl", "yi", "rue", "be", "crh", "ro", "bg", "tr", "hu", "el"], + "ug": ["sw", "lg", "nyn", "cgg", "xog", "en", "teo", "laj", "ach", "myx", "rw", "ttj", "hi"], + "um": ["en"], + "us": ["en", "es", "zh-Hant", "fr", "de", "fil", "vi", "it", "ko", "ru", "nv", "yi", "pdc", "haw", "frc", "chr", "esu", "dak", "cho", "lkt", "ik", "mus"], + "uy": ["es"], + "uz": ["uz", "uz-Cyrl", "ru", "kaa", "tr"], + "va": ["it", "la"], + "vc": ["en"], + "ve": ["es"], + "vg": ["en"], + "vi": ["en"], + "vn": ["vi", "zh-Hant", "cjm"], + "vu": ["bi", "en", "fr"], + "wf": ["wls", "fr", "fud"], + "ws": ["sm", "en"], + "xk": ["sq", "aln", "sr", "sr-Latn"], + "ye": ["ar", "en"], + "yt": ["swb", "fr", "buc", "sw"], + "za": ["en", "zu", "xh", "af", "nso", "tn", "st", "ts", "ss", "ve", "hi", "nr", "sw"], + "zm": ["bem", "en", "ny", "loz"], + "zw": ["sn", "en", "nd", "mxc", "ndc", "kck", "ny", "ve", "tn"] + } +} \ No newline at end of file diff --git a/development_server.js b/development_server.js index 28bdf1eda..23f8ac459 100644 --- a/development_server.js +++ b/development_server.js @@ -33,6 +33,7 @@ if (isDevelopment) { '!data/presets/presets.json', '!data/presets.yaml', '!data/taginfo.json', + '!data/territory-languages.json', '!dist/locales/en.json' ], function(err, watcher) { diff --git a/modules/ui/fields/localized.js b/modules/ui/fields/localized.js index 7518db8ad..aeb225435 100644 --- a/modules/ui/fields/localized.js +++ b/modules/ui/fields/localized.js @@ -1,14 +1,15 @@ import { dispatch as d3_dispatch } from 'd3-dispatch'; import { select as d3_select, event as d3_event } from 'd3-selection'; -import { t, languageName } from '../../util/locale'; +import { currentLocale, t, languageName } from '../../util/locale'; import { dataLanguages } from '../../../data'; +import { dataTerritoryLanguages } from '../../../data'; import { services } from '../../services'; import { svgIcon } from '../../svg'; import { tooltip } from '../../util/tooltip'; import { uiCombobox } from '../combobox'; import { utilDetect } from '../../util/detect'; -import { utilEditDistance, utilGetSetValue, utilNoAuto, utilRebind } from '../../util'; +import { utilArrayUniq, utilEditDistance, utilGetSetValue, utilNoAuto, utilRebind } from '../../util'; var languagesArray = []; function loadLanguagesArray() { @@ -30,6 +31,7 @@ export function uiFieldLocalized(field, context) { var wikipedia = services.wikipedia; var input = d3_select(null); var localizedInputs = d3_select(null); + var _countryCode; var allSuggestions = context.presets().collection.filter(function(p) { return p.suggestion === true; @@ -396,7 +398,23 @@ export function uiFieldLocalized(field, context) { function fetchLanguages(value, cb) { var v = value.toLowerCase(); - cb(languagesArray.filter(function(d) { + // show the user's language first + var langCodes = [currentLocale, currentLocale.split('-')[0]]; + + if (_countryCode && dataTerritoryLanguages[_countryCode]) { + langCodes = langCodes.concat(dataTerritoryLanguages[_countryCode]); + } + + var langItems = []; + langCodes.forEach(function(code) { + var langItem = languagesArray.find(function(item) { + return item.code === code; + }); + if (langItem) langItems.push(langItem); + }); + langItems = utilArrayUniq(langItems.concat(languagesArray)); + + cb(langItems.filter(function(d) { return d.label.toLowerCase().indexOf(v) >= 0 || (d.localName && d.localName.toLowerCase().indexOf(v) >= 0) || (d.nativeName && d.nativeName.toLowerCase().indexOf(v) >= 0) || @@ -540,8 +558,18 @@ export function uiFieldLocalized(field, context) { if (!arguments.length) return _entity; _entity = val; _multilingual = []; + loadCountryCode(); return localized; }; + function loadCountryCode() { + var center = _entity.extent(context.graph()).center(); + services.geocoder.countryCode(center, function(err, result) { + if (!err && result) { + _countryCode = result; + } + }); + } + return utilRebind(localized, dispatch, 'on'); }