Merge pull request #384 from mewtaylor/feature/gh-372-cards

Implement GH-372: Add `/info/cards/` route
This commit is contained in:
Matthew Taylor 2016-03-24 07:04:34 -04:00
commit 49611edb0d
16 changed files with 355 additions and 0 deletions

View file

@ -42,6 +42,7 @@ var path = require('path');
var languages = require('../languages.json');
var localeCompare = require('./lib/locale-compare');
var localizedUrls = require('./lib/localized-urls');
// -----------------------------------------------------------------------------
// Main script
@ -92,6 +93,28 @@ files.forEach(function (file) {
localeCompare.getIdsForView(view, file, viewLocales, idsWithICU, icuWithIds);
});
// get asset url translations
var localizedAssetUrls = {};
files = glob.sync(path.resolve(__dirname, '../src/views/**/l10n-static.json'));
files.forEach(function (file) {
var dirPath = file.split('/');
dirPath.pop();
var view = dirPath.pop();
localizedAssetUrls[view] = {};
var assetUrls = JSON.parse(fs.readFileSync(file, 'utf8'));
for (var lang in localizedUrls) {
localizedAssetUrls[view][lang] = {};
for (var key in assetUrls) {
if (localizedUrls[lang].hasOwnProperty(key)) {
localizedAssetUrls[view][lang][key] = localizedUrls[lang][key];
} else {
localizedAssetUrls[view][lang][key] = assetUrls[key];
}
}
}
});
// md5 of english strings with message key as the value for searching po files.
// Sample structure: { 'sdfas43534sdfasdf': 'general-general.blah', 'lkjfasdf4t342asdfa': 'about-about.blah' }
var md5WithIds = localeCompare.getMD5Map(icuWithIds);
@ -110,5 +133,8 @@ for (i in views) {
if (views[i] in viewLocales) {
viewTranslations = merge(viewLocales[views[i]], viewTranslations);
}
if (views[i] in localizedAssetUrls) {
viewTranslations = merge(viewTranslations, localizedAssetUrls[[views[i]]]);
}
localeCompare.writeTranslationsToJS(outputDir, views[i], viewTranslations);
}

View file

@ -0,0 +1,52 @@
{
"en": {
"cards.starterLink": "//scratch.mit.edu/scratchr2/static/pdfs/help/Scratch2Cards.pdf",
"cards.nameLink": "//scratch.mit.edu/scratchr2/static/pdfs/help/AnimateYourNameCards.pdf",
"cards.pongLink": "//scratch.mit.edu/scratchr2/static/pdfs/help/PongCards.pdf",
"cards.storyLink": "//scratch.mit.edu/scratchr2/static/pdfs/help/StoryCards.pdf",
"cards.danceLink": "//scratch.mit.edu/scratchr2/static/pdfs/help/DanceCards.pdf",
"cards.hideLink": "//scratch.mit.edu/scratchr2/static/pdfs/help/Hide-and-Seek-Cards.pdf"
},
"ar": {
"cards.starterLink": "//cdn.scratch.mit.edu/scratchr2/static/pdfs/help/ar/Scratch2Cards.pdf"
},
"ca": {
"cards.starterLink": "//cdn.scratch.mit.edu/scratchr2/static/pdfs/help/ca/Scratch2Cards.pdf"
},
"cs": {
"cards.starterLink": "//cdn.scratch.mit.edu/scratchr2/static/pdfs/help/cs/Scratch2Cards.pdf"
},
"de": {
"cards.starterLink": "//cdn.scratch.mit.edu/scratchr2/static/pdfs/help/de/Scratch2Cards.pdf"
},
"es": {
"cards.starterLink": "//cdn.scratch.mit.edu/scratchr2/static/pdfs/help/es/Scratch2Cards.pdf"
},
"fr": {
"cards.starterLink": "//cdn.scratch.mit.edu/scratchr2/static/pdfs/help/fr/Scratch2Cards.pdf"
},
"hr": {
"cards.starterLink": "//cdn.scratch.mit.edu/scratchr2/static/pdfs/help/hr/Scratch2Cards.pdf"
},
"it": {
"cards.starterLink": "//cdn.scratch.mit.edu/scratchr2/static/pdfs/help/it/Scratch2Cards.pdf"
},
"ja": {
"cards.starterLink": "//cdn.scratch.mit.edu/scratchr2/static/pdfs/help/ja/Scratch2Cards.pdf"
},
"ja-hr": {
"cards.starterLink": "//cdn.scratch.mit.edu/scratchr2/static/pdfs/help/ja-hr/Scratch2Cards.pdf"
},
"ko": {
"cards.starterLink": "//cdn.scratch.mit.edu/scratchr2/static/pdfs/help/ko/Scratch2Cards.pdf"
},
"nl": {
"cards.starterLink": "//cdn.scratch.mit.edu/scratchr2/static/pdfs/help/nl/Scratch2Cards.pdf"
},
"pt-br": {
"cards.starterLink": "//cdn.scratch.mit.edu/scratchr2/static/pdfs/help/pt-br/Scratch2Cards.pdf"
},
"sl": {
"cards.starterLink": "//cdn.scratch.mit.edu/scratchr2/static/pdfs/help/sl/Scratch2Cards.pdf"
}
}

View file

@ -24,6 +24,11 @@
"view": "credits",
"title": "Credits"
},
{
"pattern": "/info/cards",
"view": "cards",
"title": "Cards"
},
{
"pattern": "/jobs",
"view": "jobs",

150
src/views/cards/cards.jsx Normal file
View file

@ -0,0 +1,150 @@
var React = require('react');
var injectIntl = require('react-intl').injectIntl;
var FormattedMessage = require('react-intl').FormattedMessage;
var render = require('../../lib/render.jsx');
var Box = require('../../components/box/box.jsx');
var Page = require('../../components/page/page.jsx');
require('./cards.scss');
var Cards = injectIntl(React.createClass({
type: 'Cards',
render: function () {
var locale = window._locale || 'en';
var formatMessage = this.props.intl.formatMessage;
var englishLinks = {
'cards.starterLink': '//scratch.mit.edu/scratchr2/static/pdfs/help/Scratch2Cards.pdf',
'cards.nameLink': '//scratch.mit.edu/scratchr2/static/pdfs/help/AnimateYourNameCards.pdf',
'cards.pongLink': '//scratch.mit.edu/scratchr2/static/pdfs/help/PongCards.pdf',
'cards.storyLink': '//scratch.mit.edu/scratchr2/static/pdfs/help/StoryCards.pdf',
'cards.danceLink': '//scratch.mit.edu/scratchr2/static/pdfs/help/DanceCards.pdf',
'cards.hideLink': '//scratch.mit.edu/scratchr2/static/pdfs/help/Hide-and-Seek-Cards.pdf'
};
var formattedLinks = {
'cards.starterLink': formatMessage({id: 'cards.starterLink'}),
'cards.nameLink': formatMessage({id: 'cards.nameLink'}),
'cards.pongLink': formatMessage({id: 'cards.pongLink'}),
'cards.storyLink': formatMessage({id: 'cards.storyLink'}),
'cards.danceLink': formatMessage({id: 'cards.danceLink'}),
'cards.hideLink': formatMessage({id: 'cards.hideLink'})
};
return (
<div className="inner">
<div className="intro cards">
<div className="intro-content">
<h1><FormattedMessage id='cards.introHeader' /></h1>
<p><FormattedMessage id='cards.introContent' /></p>
</div>
<img src='/images/cards/card-use-overview.png' alt="Card Use Explanation" />
</div>
<div className='cards-container'>
<Box title={''}>
<div className='card-row'>
<div>
<h4><FormattedMessage id='cards.starter' /></h4>
<a href={formattedLinks['cards.starterLink']}>
<img src="/images/cards/cards-starter.png" alt="" />
</a>
<a href={formattedLinks['cards.starterLink']}>
<img src="/svgs/pdf-icon-ui-blue.svg" alt="" className='pdf-icon' />
<FormattedMessage id='cards.viewCard' />
{(
formattedLinks['cards.starterLink'] === englishLinks['cards.starterLink'] &&
locale !== 'en'
) ? [
<span> <FormattedMessage id='cards.english' /></span>
] : []}
</a>
</div>
<div>
<h4><FormattedMessage id='cards.name' /></h4>
<a href={formattedLinks['cards.nameLink']}>
<img src="/images/cards/cards-name.png" alt="" />
</a>
<a href={formattedLinks['cards.nameLink']}>
<img src="/svgs/pdf-icon-ui-blue.svg" alt="" className='pdf-icon' />
<FormattedMessage id='cards.viewCard' />
{(
formattedLinks['cards.nameLink'] === englishLinks['cards.nameLink'] &&
locale !== 'en'
) ? [
<span> (<FormattedMessage id='cards.english' />)</span>
] : []}
</a>
</div>
<div>
<h4><FormattedMessage id='cards.pong' /></h4>
<a href={formattedLinks['cards.pongLink']}>
<img src="/images/cards/cards-pong.png" alt="" />
</a>
<a href={formattedLinks['cards.pongLink']}>
<img src="/svgs/pdf-icon-ui-blue.svg" alt="" className='pdf-icon' />
<FormattedMessage id='cards.viewCard' />
{(
formattedLinks['cards.pongLink'] === englishLinks['cards.pongLink'] &&
locale !== 'en'
) ? [
<span> (<FormattedMessage id='cards.english' />)</span>
] : []}
</a>
</div>
</div>
<div className='card-row'>
<div>
<h4><FormattedMessage id='cards.story' /></h4>
<a href={formattedLinks['cards.storyLink']}>
<img src="/images/cards/cards-story.png" alt="" />
</a>
<a href={formattedLinks['cards.storyLink']}>
<img src="/svgs/pdf-icon-ui-blue.svg" alt="" className='pdf-icon' />
<FormattedMessage id='cards.viewCard' />
{(
formattedLinks['cards.storyLink'] === englishLinks['cards.storyLink'] &&
locale !== 'en'
) ? [
<span> (<FormattedMessage id='cards.english' />)</span>
] : []}
</a>
</div>
<div>
<h4><FormattedMessage id='cards.dance' /></h4>
<a href={formattedLinks['cards.danceLink']}>
<img src="/images/cards/cards-dance.png" alt="" />
</a>
<a href={formattedLinks['cards.danceLink']}>
<img src="/svgs/pdf-icon-ui-blue.svg" alt="" className='pdf-icon' />
<FormattedMessage id='cards.viewCard' />
{(
formattedLinks['cards.danceLink'] === englishLinks['cards.danceLink'] &&
locale !== 'en'
) ? [
<span> (<FormattedMessage id='cards.english' />)</span>
] : []}
</a>
</div>
<div>
<h4><FormattedMessage id='cards.hide' /></h4>
<a href={formattedLinks['cards.hideLink']}>
<img src="/images/cards/cards-hide.png" alt="" />
</a>
<a href={formattedLinks['cards.hideLink']}>
<img src="/svgs/pdf-icon-ui-blue.svg" alt="" className='pdf-icon' />
<FormattedMessage id='cards.viewCard' />
{(
formattedLinks['cards.hideLink'] === englishLinks['cards.hideLink'] &&
locale !== 'en'
) ? [
<span> (<FormattedMessage id='cards.english' />)</span>
] : []}
</a>
</div>
</div>
</Box>
</div>
</div>
);
}
}));
render(<Page><Cards /></Page>, document.getElementById('app'));

View file

@ -0,0 +1,43 @@
@import "../../colors";
@import "../../typography";
.cards {
display: flex;
margin: 1em 0;
align-items: center;
justify-content: center;
.intro-content {
float: left;
width: 45%;
}
img {
width: 45%;
}
}
.cards-container {
text-align: center;
.card-row {
display: flex;
justify-content: space-around;
align-items: center;
flex-wrap: wrap;
div {
display: inline-block;
padding: .5em;
a {
display: block;
.pdf-icon {
margin-right: .2em;
width: 1em;
}
}
}
}
}

View file

@ -0,0 +1,8 @@
{
"cards.starterLink": "//scratch.mit.edu/scratchr2/static/pdfs/help/Scratch2Cards.pdf",
"cards.nameLink": "//scratch.mit.edu/scratchr2/static/pdfs/help/AnimateYourNameCards.pdf",
"cards.pongLink": "//scratch.mit.edu/scratchr2/static/pdfs/help/PongCards.pdf",
"cards.storyLink": "//scratch.mit.edu/scratchr2/static/pdfs/help/StoryCards.pdf",
"cards.danceLink": "//scratch.mit.edu/scratchr2/static/pdfs/help/DanceCards.pdf",
"cards.hideLink": "//scratch.mit.edu/scratchr2/static/pdfs/help/Hide-and-Seek-Cards.pdf"
}

13
src/views/cards/l10n.json Normal file
View file

@ -0,0 +1,13 @@
{
"cards.introHeader": "Scratch Cards",
"cards.introContent": "Scratch cards provide a quick way to learn new Scratch code.",
"cards.english": "English",
"cards.introWikiSupport": "Looking for Scratch Cards in your language? Check <a href=\"http://wiki.scratch.mit.edu/wiki/Scratch_Support_Materials\">Scratch Wiki</a>.",
"cards.viewCard": "View Cards",
"cards.starter": "Starter Cards",
"cards.name": "Animate Your Name",
"cards.pong": "Create a Pong Game",
"cards.story": "Animate a Story",
"cards.dance": "Dance, Dance, Dance",
"cards.hide": "Hide and Seek"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="20px" height="20px" viewBox="0 0 20 20" style="enable-background:new 0 0 20 20;" xml:space="preserve">
<g>
<g>
<path style="fill:#41ABE1;" d="M11.8,2.2L16.6,7v0L11.8,2.2z"/>
<path style="fill:#41ABE1;" d="M16.8,7.3c0-0.1-0.1-0.2-0.1-0.3c0,0,0,0,0,0l-4.8-4.8C11.7,2.1,11.6,2,11.4,2H7.1
C5.9,2,4.8,3.1,4.8,4.4v4.4c0,0.4,0.3,0.6,0.6,0.6C5.8,9.4,6,9.2,6,8.8V4.4c0-0.6,0.5-1.1,1.1-1.1h3.6v2.4C10.8,7,11.8,8,13.1,8
h2.4v7.6c0,0.6-0.5,1.1-1.1,1.1H7.1c-0.5,0-0.8-0.3-1-0.7c-0.1-0.2-0.3-0.4-0.5-0.4H5.5c-0.4,0-0.7,0.4-0.6,0.8
C5.3,17.4,6.2,18,7.1,18h7.3c1.3,0,2.4-1.1,2.4-2.4V7.4C16.8,7.4,16.8,7.3,16.8,7.3z M13.1,6.8c-0.6,0-1.1-0.5-1.1-1.1V4.1
l2.6,2.6H13.1z"/>
</g>
<g>
<path style="fill:#41ABE1;" d="M3.2,10.9h1.5c0.9,0,1.4,0.5,1.4,1.2v0c0,0.8-0.6,1.2-1.5,1.2H4.2v1h-1V10.9z M4.6,12.6
c0.3,0,0.6-0.2,0.6-0.5v0c0-0.3-0.2-0.5-0.6-0.5H4.2v0.9H4.6z"/>
<path style="fill:#41ABE1;" d="M7,10.9h1.3c1.2,0,2,0.7,2,1.7v0c0,1-0.7,1.7-2,1.7H7V10.9z M8.4,13.5c0.6,0,1-0.3,1-0.9v0
c0-0.6-0.4-0.9-1-0.9H8v1.8H8.4z"/>
<path style="fill:#41ABE1;" d="M11.3,10.9h2.8v0.8h-1.8v0.6h1.6v0.8h-1.6v1.2h-1V10.9z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -0,0 +1,36 @@
/*
* spot check that each language has values for the string id keys on Cards page
* that are contained in English (i.e. make sure strings will show up, not ids")
*/
var merge = require('lodash.merge');
var path = require('path');
var tap = require('tap');
var languages = require('../../languages.json');
var localeCompare = require('../../bin/lib/locale-compare');
tap.test('spotCheckAboutStrings', function (t) {
var isoCodes = Object.keys(languages);
isoCodes.splice(isoCodes.indexOf('en'), 1);
var viewLocales = {};
var idsWithICU = {};
var icuWithIds = {};
localeCompare.getIdsForView(
'cards',
path.resolve(__dirname, '../../src/views/cards/l10n.json'),
viewLocales,
idsWithICU,
icuWithIds
);
var md5WithIds = localeCompare.getMD5Map(icuWithIds);
var keysToCheck = Object.keys(merge(viewLocales['cards']['en'])).sort();
for (var i in isoCodes) {
var translations = localeCompare.getTranslationsForLanguage(isoCodes[i], idsWithICU, md5WithIds);
t.same(
Object.keys(translations['cards'][isoCodes[i]]).sort(),
keysToCheck,
'check Cards keys for language ' + isoCodes[i]
);
}
t.end();
});