Skip to content

Commit

Permalink
Don't bundle the locales anymore, load first in context init
Browse files Browse the repository at this point in the history
(re: #4994)
  • Loading branch information
bhousel committed Feb 21, 2020
1 parent e633f1b commit b12c304
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 49 deletions.
25 changes: 13 additions & 12 deletions modules/core/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ import { dispatch as d3_dispatch } from 'd3-dispatch';
import { json as d3_json } from 'd3-fetch';
import { select as d3_select } from 'd3-selection';

import { t, localeStrings, setLocale } from '../util/locale';
import { t, setLocale, localeStrings, localeData } from '../util/locale';

import { coreData } from './data';
import { coreHistory } from './history';
import { coreValidator } from './validator';
import { coreUploader } from './uploader';
import { dataLocales } from '../../data';
import { geoRawMercator } from '../geo/raw_mercator';
import { modeSelect } from '../modes/select';
import { osmSetAreaKeys, osmSetPointTags, osmSetVertexTags } from '../osm/tags';
Expand Down Expand Up @@ -51,9 +50,6 @@ export function coreContext() {
// forOwn(tkeys, traverser);
// addLocale('_tkeys_', tkeys);

// addLocale('en', dataEn);
// setLocale('en');


// https://github.com/openstreetmap/iD/issues/772
// http://mathiasbynens.be/notes/localstorage-pattern#comment-9
Expand Down Expand Up @@ -432,17 +428,17 @@ export function coreContext() {


/* Locales */
// Returns a Promise to load the strings for the given locale
// Returns a Promise to load the strings for the requested locale
context.loadLocale = (requested) => {
let locale = requested;

if (!_data) {
return Promise.reject('loadLocale called before init');
}
if (!dataLocales.hasOwnProperty(locale)) { // Not supported, e.g. 'es-FAKE'
locale = locale.split('-')[0]; // Fallback to the first part 'es'
if (!localeData[locale]) { // Locale not supported, e.g. 'es-FAKE'
locale = locale.split('-')[0]; // Fallback to the first part 'es'
}
if (!dataLocales.hasOwnProperty(locale)) {
if (!localeData[locale]) {
return Promise.reject(`Unsupported locale: ${requested}`);
}

Expand All @@ -452,7 +448,7 @@ export function coreContext() {

let fileMap = _data.fileMap();
const key = `locale_${locale}`;
fileMap[key] = `locales/${locale}.json`; // .min.json?
fileMap[key] = `locales/${locale}.json`;

return _data.get(key)
.then(d => {
Expand Down Expand Up @@ -500,9 +496,14 @@ export function coreContext() {

_data = coreData(context);

// always load the English locale, then load preferred locale.
// Start loading data:
// 1. the list of supported locales
// 2. the English locale strings (used as fallbacks)
// 3. the preferred locale strings (detected by utilDetect)
const requested = utilDetect().locale;
context.loadLocale('en')
_data.get('locales')
.then(d => Object.assign(localeData, d))
.then(() => context.loadLocale('en'))
.then(() => context.loadLocale(requested))
.then(received => { // `received` may not match `requested`.
setLocale(received); // (e.g. 'es-FAKE' will return 'es')
Expand Down
5 changes: 2 additions & 3 deletions modules/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as d3 from 'd3'; // TODO: remove (needed for tests?)
import * as d3 from 'd3'; // remove someday, see #4379
export { d3 };

export * from './actions/index';
export * from './behavior/index';
export * from './core/index';
export * from '../data/index';
export * from './geo/index';
export * from './modes/index';
export * from './operations/index';
Expand Down Expand Up @@ -48,4 +48,3 @@ export { uiPresetEditor as uiPreset } from './ui/preset_editor';

export var debug = false;

export { d3 };
10 changes: 7 additions & 3 deletions modules/ui/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -340,16 +340,20 @@ export function uiInit(context) {


// `ui()` renders the iD interface into the given node, assigning
// that node as the `container`. We need to delay rendering until
// the locale has been loaded (i.e. promise settled), because the
// that node as the `container`. We need to delay rendering until the
// locale data has been loaded (i.e. promises all settled), because the
// UI code expects localized strings to be available.
function ui(node, callback) {
_initCallback = callback;
var container = d3_select(node);
context.container(container);

const current = utilDetect().locale;
context.loadLocale(current)

context.data().get('locales')
.then(function () {
return context.loadLocale(current);
})
.then(function() {
render(container);
if (callback) callback();
Expand Down
5 changes: 2 additions & 3 deletions modules/util/detect.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { currentLocale, setTextDirection, setLanguageNames, setScriptNames } from './locale';
import { dataLocales } from '../../data/index';
import { currentLocale, localeData, setTextDirection, setLanguageNames, setScriptNames } from './locale';
import { utilStringQs } from './util';

let _detected;
Expand Down Expand Up @@ -126,7 +125,7 @@ export function utilDetect(force) {
}

// detect text direction
const lang = dataLocales[_detected.locale] || dataLocales[_detected.language];
const lang = localeData[_detected.locale] || localeData[_detected.language];
if ((lang && lang.rtl) || (hash.rtl === 'true')) {
_detected.textDirection = 'rtl';
} else {
Expand Down
53 changes: 26 additions & 27 deletions modules/util/locale.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,42 @@
let _dataLanguages = {};


// `localeStrings` is an object containing all loaded locale codes -> string data
// `localeData` is an object containing all _supported_ locale codes -> language info
// `context.init()` will load this before anything else.
// {
// en: {icons: {…}, toolbar: {…}, modes: {…}, operations: {…}, …},
// de: {icons: {…}, toolbar: {…}, modes: {…}, operations: {…}, …},
// en: { rtl: false, languageNames: {…}, scriptNames: {…} },
// de: { rtl: false, languageNames: {…}, scriptNames: {…} },
// …
// }
export let localeStrings = Object.create(null);
export let localeData = {};

// `localeStrings` is an object containing all _loaded_ locale codes -> string data
// `context.init()` will load the 'en' strings.
// {
// en: { icons: {…}, toolbar: {…}, modes: {…}, operations: {…}, … },
// de: { icons: {…}, toolbar: {…}, modes: {…}, operations: {…}, … },
// …
// }
export let localeStrings = {};

export let currentLocale;
export let textDirection = 'ltr';
export let languageNames = {};
export let scriptNames = {};

export function setLocale(locale) {
currentLocale = locale;
// if (localeStrings[locale] !== undefined) {
// currentLocale = locale;
// } else if (localeStrings[locale.split('-')[0]]) {
// currentLocale = locale.split('-')[0];
// }
export function setLocale(val) {
currentLocale = val;
}
export function setTextDirection(val) {
textDirection = val;
}
export function setLanguageNames(val) {
languageNames = val;
}
export function setScriptNames(val) {
scriptNames = val;
}


/**
* Given a string identifier, try to find that string in the current
Expand Down Expand Up @@ -72,22 +87,6 @@ export function t(s, replacements, locale) {
return missing;
}

/**
* Given string 'ltr' or 'rtl', save that setting
*
* @param {string} dir ltr or rtl
*/
export function setTextDirection(dir) {
textDirection = dir;
}

export function setLanguageNames(obj) {
languageNames = obj;
}

export function setScriptNames(obj) {
scriptNames = obj;
}

export function languageName(context, code, options) {
// Data access is async now, which makes this complicated.
Expand Down
3 changes: 2 additions & 1 deletion test/spec/spec_helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ for (var k in iD.services) { delete iD.services[k]; }

// Run without data for speed (tests which need data can set it up themselves)

// Initializing `coreContext` will try loading the English locale strings:
// Initializing `coreContext` will try loading the locale data and English locale strings:
iD.data.locales = { en: { rtl: false, languageNames: {}, scriptNames: {} }};
iD.data.locale_en = { en: {} };
// Initializing `coreContext` initializes `_background`, which tries loading:
iD.data.imagery = [];
Expand Down

0 comments on commit b12c304

Please sign in to comment.