diff --git a/bin/build-locales b/bin/build-locales index 7102d2a1a..2c78e1b1e 100755 --- a/bin/build-locales +++ b/bin/build-locales @@ -86,7 +86,7 @@ for (var v in routes) { if (typeof routes[v].redirect !== 'undefined') { continue; } - + views.push(routes[v].name); try { var subdir = routes[v].view.split('/'); @@ -97,7 +97,8 @@ for (var v in routes) { en: ids }; idsWithICU = merge(idsWithICU, localeCompare.idToICUMap(routes[v].name, ids)); - icuWithIds = merge(icuWithIds, localeCompare.icuToIdMap(routes[v].name, ids)); + // Note: if lodash.merge gets updated to 4.0 or higher this needs to be mergeWith instead + icuWithIds = merge(icuWithIds, localeCompare.icuToIdMap(routes[v].name, ids), localeCompare.customMerge); } catch (err) { if (err.code !== 'MODULE_NOT_FOUND') { throw err; diff --git a/bin/lib/locale-compare.js b/bin/lib/locale-compare.js index 5a2e3bc81..55dcb5f41 100644 --- a/bin/lib/locale-compare.js +++ b/bin/lib/locale-compare.js @@ -6,6 +6,7 @@ var crypto = require('crypto'); var fs = require('fs'); var path = require('path'); var po2icu = require('po2icu'); +var isArray = require('lodash.isArray'); var Helpers = {}; @@ -20,6 +21,21 @@ Helpers.getMD5 = function (string) { return crypto.createHash('md5').update(cleanedString, 'utf8').digest('hex'); }; +/** + * Customizer for icuWithIds merge. + * If icu key already has an id value, concatenate additional ids instead + * of replacing. + * + * @param {array} objVal current value + * @param {string} srcVal new value + * @return {array} objVal with srcVal concatenated + */ +Helpers.customMerge = function (objVal, srcVal) { + if (isArray(objVal)) { + return objVal.concat(srcVal); + } +}; + /* Existing translations should be in the key value format specified by react-intl (i.e. formatted message id, with icu string as the value). New Translations should be in the @@ -33,7 +49,9 @@ Helpers.mergeNewTranslations = function (existingTranslations, newTranslations, for (var id in newTranslations) { var md5 = Helpers.getMD5(id); if (md5Map.hasOwnProperty(md5) && newTranslations[id].length > 0) { - existingTranslations[md5Map[md5]] = newTranslations[id]; + md5Map[md5].forEach(function (msgId) { + existingTranslations[msgId] = newTranslations[id]; + }); } } @@ -103,7 +121,7 @@ Helpers.getTranslationsForLanguage = function (lang, idsWithICU, md5WithIds, sep throw err; } } - + var translationsByView = {}; for (var id in translations) { var ids = id.split(separator); // [viewName, stringId] @@ -132,7 +150,7 @@ Helpers.writeTranslationsToJS = function (outputDir, viewName, translationObject Helpers.idToICUMap = function (viewName, ids, separator) { var idsToICU = {}; separator = separator || ':'; - + for (var id in ids) { idsToICU[viewName + separator + id] = ids[id]; } @@ -146,7 +164,7 @@ Helpers.icuToIdMap = function (viewName, ids, separator) { separator = separator || ':'; for (var id in ids) { - icuToIds[ids[id]] = viewName + separator + id; + icuToIds[ids[id]] = [viewName + separator + id]; } return icuToIds; }; diff --git a/package.json b/package.json index 077e598f0..89e0fdd7b 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "keymirror": "0.1.1", "lodash.clone": "3.0.3", "lodash.defaultsdeep": "3.10.0", + "lodash.isarray": "^3.0.4", "lodash.merge": "3.3.2", "lodash.omit": "3.1.0", "lodash.range": "3.0.1", diff --git a/src/views/splash/splash.jsx b/src/views/splash/splash.jsx index cd0042683..55fb71777 100644 --- a/src/views/splash/splash.jsx +++ b/src/views/splash/splash.jsx @@ -215,11 +215,11 @@ var Splash = injectIntl(React.createClass({ <Box key="curator_top_projects" title={ - 'Projects Curated by ' + + formatMessage({id: 'splash.projectsCuratedBy', defaultMessage: 'Projects Curated by '}) + this.state.featuredGlobal.curator_top_projects[0].curator_name} moreTitle={formatMessage({id: 'general.learnMore', defaultMessage: 'Learn More'})} moreHref="/studios/386359/"> - + <Carousel items={this.state.featuredGlobal.curator_top_projects} /> </Box> ); @@ -236,7 +236,7 @@ var Splash = injectIntl(React.createClass({ + ' - ' + this.state.featuredGlobal.scratch_design_studio[0].gallery_title} moreTitle={formatMessage({id: 'splash.visitTheStudio', defaultMessage: 'Visit the studio'})} moreHref={'/studios/' + this.state.featuredGlobal.scratch_design_studio[0].gallery_id + '/'}> - + <Carousel items={this.state.featuredGlobal.scratch_design_studio} /> </Box> ); @@ -260,7 +260,7 @@ var Splash = injectIntl(React.createClass({ rows.push( <Box title={formatMessage({id: 'splash.projectsByScratchersFollowing'})} key="custom_projects_by_following"> - + <Carousel items={this.state.featuredCustom.custom_projects_by_following} /> </Box> ); @@ -271,7 +271,7 @@ var Splash = injectIntl(React.createClass({ rows.push( <Box title={formatMessage({id: 'splash.projectsLovedByScratchersFollowing'})} key="custom_projects_loved_by_following"> - + <Carousel items={this.state.featuredCustom.custom_projects_loved_by_following} /> </Box> ); @@ -283,7 +283,7 @@ var Splash = injectIntl(React.createClass({ rows.push( <Box title={formatMessage({id:'splash.projectsInStudiosFollowing'})} key="custom_projects_in_studios_following"> - + <Carousel items={this.state.featuredCustom.custom_projects_in_studios_following} /> </Box> );