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..ff0e4890a 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..18d507095 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/components/activity/activity.jsx b/src/components/activity/activity.jsx index 9126e641b..c0f735cc8 100644 --- a/src/components/activity/activity.jsx +++ b/src/components/activity/activity.jsx @@ -11,8 +11,7 @@ require('./activity.scss'); var defaultMessages = defineMessages({ whatsHappening: { - id: 'general.whatsHappening', - defaultMessage: 'What\'s Happening?' + id: 'general.whatsHappening' } }); diff --git a/src/views/splash/splash.jsx b/src/views/splash/splash.jsx index cd0042683..9b80e0a72 100644 --- a/src/views/splash/splash.jsx +++ b/src/views/splash/splash.jsx @@ -215,11 +215,11 @@ var Splash = injectIntl(React.createClass({ - + ); @@ -234,9 +234,9 @@ var Splash = injectIntl(React.createClass({ title={ formatMessage({id: 'splash.scratchDesignStudioTitle'}) + ' - ' + this.state.featuredGlobal.scratch_design_studio[0].gallery_title} - moreTitle={formatMessage({id: 'splash.visitTheStudio', defaultMessage: 'Visit the studio'})} + moreTitle={formatMessage({id: 'splash.visitTheStudio'})} moreHref={'/studios/' + this.state.featuredGlobal.scratch_design_studio[0].gallery_id + '/'}> - + ); @@ -260,7 +260,7 @@ var Splash = injectIntl(React.createClass({ rows.push( - + ); @@ -271,7 +271,7 @@ var Splash = injectIntl(React.createClass({ rows.push( - + ); @@ -283,7 +283,7 @@ var Splash = injectIntl(React.createClass({ rows.push( - + ); diff --git a/src/views/wedo2/l10n.json b/src/views/wedo2/l10n.json index 5e98a547d..58cab3daa 100644 --- a/src/views/wedo2/l10n.json +++ b/src/views/wedo2/l10n.json @@ -1,6 +1,6 @@ { "wedo2.intro": "The LEGO® Education WeDo 2.0 is an introductory invention kit you can use to build your own interactive machines. You can snap together Scratch programming blocks to interact with your LEGO WeDo creations and add animations on the screen.", - "wedo2.requirement": "The LEGO WeDo 2.0 extension is currently only available for Mac OSX. We plan to release a Windows version later in 2016.", + "wedo2.requirement": "The LEGO WeDo 2.0 extension is available for Mac OSX and Windows 10+", "wedo2.getStarted": "Getting Started with LEGO WeDo 2.0", "wedo2.installTitle": "1. Install Device Manager", "wedo2.installText": "The Device Manager lets you connect WeDo 2.0 to Scratch using Bluetooth Download Here", diff --git a/test/fixtures/test_es_md5map.json b/test/fixtures/test_es_md5map.json index b19fcf3ab..e5d21c1d3 100644 --- a/test/fixtures/test_es_md5map.json +++ b/test/fixtures/test_es_md5map.json @@ -1,4 +1,4 @@ { - "2ec20d41b181e1a41c071e13f414a74d": "test.id1", - "37ba6d5ef524504215f478912155f9ba": "test.id2" + "2ec20d41b181e1a41c071e13f414a74d": ["test.id1"], + "37ba6d5ef524504215f478912155f9ba": ["test.id2"] } diff --git a/test/functional/build_locales_icuMap.js b/test/functional/build_locales_icuMap.js new file mode 100644 index 000000000..48152a020 --- /dev/null +++ b/test/functional/build_locales_icuMap.js @@ -0,0 +1,23 @@ +var merge = require('lodash.merge'); +var tap = require('tap'); + +var buildLocales = require('../../bin/lib/locale-compare'); + +tap.test('buildIcuMap', function (t) { + var ids1 = { + 'first.test1' : 'We know where we\'re going, but we don\'t know where we\'ve been', + 'first.test2' : 'You may find yourself living in a shotgun shack' + }; + var ids2 = { + 'second.test1' : 'We know where we\'re going, but we don\'t know where we\'ve been', + 'second.test2' : 'Gadji beri bimba clandridi' + }; + + var testicuMap = buildLocales.icuToIdMap('first', ids1); + testicuMap = merge(testicuMap, buildLocales.icuToIdMap('second', ids2), buildLocales.customMerge); + + t.ok(testicuMap['We know where we\'re going, but we don\'t know where we\'ve been'].length === 2); + t.ok(testicuMap['You may find yourself living in a shotgun shack'].length === 1); + t.ok(testicuMap['Gadji beri bimba clandridi'].length === 1); + t.end(); +}); diff --git a/test/functional/build_locales_mergeDupStrings.js b/test/functional/build_locales_mergeDupStrings.js new file mode 100644 index 000000000..aa0828417 --- /dev/null +++ b/test/functional/build_locales_mergeDupStrings.js @@ -0,0 +1,25 @@ +var tap = require('tap'); + +var buildLocales = require('../../bin/lib/locale-compare'); + +tap.test('buildLocalesMergeDupStrings', function (t) { + var existingTranslations = { + 'test.test1': 'It\'s like raaayaaain, on your wedding day', + 'test.test2': 'Free to flyyy, when you already paid', + 'test.test4': 'Free to flyyy, when you already paid' + }; + var newTranslations = { + 'Isn\'t it ironic? No.': 'Es irónico? No.' + }; + var md5map = { + 'c21ce5ceefe167028182032d4255a384': ['test.test1'], + '9c40648034e467e16f8d6ae24bd610ab': ['test.test2', 'test.test4'], + '6885a345adafb3a9dd43d9f549430c88': ['test.test3', 'test.test5'] + }; + + var mergedTranslations = buildLocales.mergeNewTranslations(existingTranslations, newTranslations, {}, md5map); + t.ok(mergedTranslations['test.test2'] !== undefined); + t.ok(mergedTranslations['test.test3'] !== undefined); + t.ok(mergedTranslations['test.test5'] !== undefined); + t.end(); +}); diff --git a/test/functional/build_locales_mergeTranslations.js b/test/functional/build_locales_mergeTranslations.js index 47d6e512d..a83496dae 100644 --- a/test/functional/build_locales_mergeTranslations.js +++ b/test/functional/build_locales_mergeTranslations.js @@ -11,9 +11,9 @@ tap.test('buildLocalesMergeTranslations', function (t) { 'Isn\'t it ironic? No.': 'Es irónico? No.' }; var md5map = { - 'c21ce5ceefe167028182032d4255a384': 'test.test1', - '9c40648034e467e16f8d6ae24bd610ab': 'test.test2', - '6885a345adafb3a9dd43d9f549430c88': 'test.test3' + 'c21ce5ceefe167028182032d4255a384': ['test.test1'], + '9c40648034e467e16f8d6ae24bd610ab': ['test.test2'], + '6885a345adafb3a9dd43d9f549430c88': ['test.test3'] }; var mergedTranslations = buildLocales.mergeNewTranslations(existingTranslations, newTranslations, {}, md5map);