Merge pull request #384 from mewtaylor/feature/gh-372-cards
Implement GH-372: Add `/info/cards/` route
|
@ -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);
|
||||
}
|
||||
|
|
52
bin/lib/localized-urls.json
Normal 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"
|
||||
}
|
||||
}
|
|
@ -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
|
@ -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'));
|
43
src/views/cards/cards.scss
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
8
src/views/cards/l10n-static.json
Normal 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
|
@ -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"
|
||||
}
|
BIN
static/images/cards/card-use-overview.png
Normal file
After Width: | Height: | Size: 49 KiB |
BIN
static/images/cards/cards-dance.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
static/images/cards/cards-hide.png
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
static/images/cards/cards-name.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
static/images/cards/cards-pong.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
static/images/cards/cards-starter.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
static/images/cards/cards-story.png
Normal file
After Width: | Height: | Size: 31 KiB |
22
static/svgs/pdf-icon-ui-blue.svg
Normal 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 |
36
test/localization/spot_check_cards_has_strings.js
Normal 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();
|
||||
});
|