mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-29 10:36:42 -05:00
Introduce new tx-push-www script to automate string push to transifex
This commit is contained in:
parent
7bfaa27eb0
commit
2d3158a8f7
12 changed files with 88 additions and 890 deletions
|
@ -139,3 +139,9 @@ stages:
|
||||||
- test
|
- test
|
||||||
- name: smoke
|
- name: smoke
|
||||||
if: type != pull_request
|
if: type != pull_request
|
||||||
|
- provider: script
|
||||||
|
on:
|
||||||
|
branch: develop
|
||||||
|
condition: $TRAVIS_EVENT_TYPE == cron
|
||||||
|
skip_cleanup: true
|
||||||
|
script: npm run i18n:push
|
||||||
|
|
186
.tx/config
186
.tx/config
|
@ -1,186 +0,0 @@
|
||||||
[main]
|
|
||||||
host = https://www.transifex.com
|
|
||||||
lang_map = zh_CN:zh-cn, zh_TW:zh-tw, pt_BR:pt-br, es_419:es-419, aa_DJ:aa-dj
|
|
||||||
|
|
||||||
[scratch-website.explore-l10njson]
|
|
||||||
file_filter = localizations/explore/<lang>.json
|
|
||||||
source_file = src/views/explore/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.general-l10njson]
|
|
||||||
file_filter = localizations/general/<lang>.json
|
|
||||||
source_file = src/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.wedo2-l10njson]
|
|
||||||
file_filter = localizations/wedo2/<lang>.json
|
|
||||||
source_file = src/views/wedo2/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.teacherregistration-l10njson]
|
|
||||||
file_filter = localizations/teacherregistration/<lang>.json
|
|
||||||
source_file = src/views/teacherregistration/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.dmca-l10njson]
|
|
||||||
file_filter = localizations/dmca/<lang>.json
|
|
||||||
source_file = src/views/dmca/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.jobs-l10njson]
|
|
||||||
file_filter = localizations/jobs/<lang>.json
|
|
||||||
source_file = src/views/jobs/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.faq-l10njson]
|
|
||||||
file_filter = localizations/faq/<lang>.json
|
|
||||||
source_file = src/views/faq/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.about-l10njson]
|
|
||||||
file_filter = localizations/about/<lang>.json
|
|
||||||
source_file = src/views/about/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.teacher-faq-l10njson]
|
|
||||||
file_filter = localizations/teacher-faq/<lang>.json
|
|
||||||
source_file = src/views/teachers/faq/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.developers-l10njson]
|
|
||||||
file_filter = localizations/developers/<lang>.json
|
|
||||||
source_file = src/views/developers/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.guidelines-l10njson]
|
|
||||||
file_filter = localizations/guidelines/<lang>.json
|
|
||||||
source_file = src/views/guidelines/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.educator-landing-l10njson]
|
|
||||||
file_filter = localizations/educator-landing/<lang>.json
|
|
||||||
source_file = src/views/teachers/landing/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.splash-l10njson]
|
|
||||||
file_filter = localizations/splash/<lang>.json
|
|
||||||
source_file = src/views/splash/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.conference-index-2019-l10njson]
|
|
||||||
file_filter = localizations/conference-index-2019/<lang>.json
|
|
||||||
source_file = src/views/conference/2019/index/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.conference-index-2017-l10njson]
|
|
||||||
file_filter = localizations/conference-index-2017/<lang>.json
|
|
||||||
source_file = src/views/conference/2017/index/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.credits-l10njson]
|
|
||||||
file_filter = localizations/credits/<lang>.json
|
|
||||||
source_file = src/views/credits/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.download-l10njson]
|
|
||||||
file_filter = localizations/download/<lang>.json
|
|
||||||
source_file = src/views/download/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.download-scratch2-l10njson]
|
|
||||||
file_filter = localizations/download/scratch2/<lang>.json
|
|
||||||
source_file = src/views/download/scratch2/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.camp-l10njson]
|
|
||||||
file_filter = localizations/camp/<lang>.json
|
|
||||||
source_file = src/views/camp/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.messages-l10njson]
|
|
||||||
file_filter = localizations/messages/<lang>.json
|
|
||||||
source_file = src/views/messages/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.research-l10njson]
|
|
||||||
file_filter = localizations/research/<lang>.json
|
|
||||||
source_file = src/views/research/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.preview-l10njson]
|
|
||||||
file_filter = localizations/preview/<lang>.json
|
|
||||||
source_file = src/views/preview/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.ev3-l10njson]
|
|
||||||
source_file = src/views/ev3/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.microbit-l10njson]
|
|
||||||
source_file = src/views/microbit/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.boost-l10njson]
|
|
||||||
source_file = src/views/boost/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.gdxfor-l10njson]
|
|
||||||
source_file = src/views/gdxfor/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.search-l10njson]
|
|
||||||
file_filter = localizations/search/<lang>.json
|
|
||||||
source_file = src/views/search/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.wedo2-legacy-l10njson]
|
|
||||||
source_file = src/views/wedo2-legacy/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.parents-l10njson]
|
|
||||||
source_file = src/views/parents/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.scratch_14-l10njson]
|
|
||||||
source_file = src/views/scratch_1.4/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.ideas-l10njson]
|
|
||||||
source_file = src/views/ideas/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
||||||
|
|
||||||
[scratch-website.starter-projects-l10njson]
|
|
||||||
source_file = src/views/starter-projects/l10n.json
|
|
||||||
source_lang = en
|
|
||||||
type = KEYVALUEJSON
|
|
81
bin/tx-push-www
Executable file
81
bin/tx-push-www
Executable file
|
@ -0,0 +1,81 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
/*
|
||||||
|
Push www strings to Transifex, using scratch-l10n's tx-push-src.js script
|
||||||
|
|
||||||
|
1. for every file like src/views/.../l10n.json, call tx-push-src.js
|
||||||
|
2. also call tx-push-src.js on the general file, src/l10n.json
|
||||||
|
|
||||||
|
The format of tx-push-src.js's arguments is:
|
||||||
|
$ tx-push-src.js tx-project tx-resource english-json-file
|
||||||
|
So, for example, src/views/parents/l10n.json will use:
|
||||||
|
$ tx-push-src.js scratch-website parents-l10njson src/views/parents/l10n.json
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
const glob = require('glob');
|
||||||
|
const execSync = require('child_process').execSync;
|
||||||
|
|
||||||
|
// determine if this is a dry run, or if we're really pushing to transifex
|
||||||
|
let execute = false;
|
||||||
|
const args = process.argv.slice(2);
|
||||||
|
if (args[0] === '--execute') {
|
||||||
|
process.stdout.write('pushing to transifex...\n');
|
||||||
|
execute = true;
|
||||||
|
} else {
|
||||||
|
process.stdout.write('Dry run: pass "execute" as a parameter to add --execute switch to commands\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
// exceptions to the usual relationship between file path and corresponding
|
||||||
|
// transifex resource name
|
||||||
|
const overrides = {
|
||||||
|
'src/views/teachers/faq/l10n.json': 'teacher-faq-l10njson',
|
||||||
|
'src/views/teachers/landing/l10n.json': 'educator-landing-l10njson',
|
||||||
|
'src/views/conference/2020/index/l10n.json': 'conference-index-2020-l10njson',
|
||||||
|
'src/views/conference/2019/index/l10n.json': 'conference-index-2019-l10njson',
|
||||||
|
'src/views/conference/2017/index/l10n.json': 'conference-index-2017-l10njson'
|
||||||
|
};
|
||||||
|
|
||||||
|
// convert an l10n file path to the usual format of the corresponding
|
||||||
|
// transifex resource name. E.g., for file path src/views/parents/l10n.json ,
|
||||||
|
// return parents-l10njson.
|
||||||
|
const txResourceNameFromPath = l10nFilePath => {
|
||||||
|
const pathRegexp = /(src\/views\/)?(.*)/g;
|
||||||
|
const match = pathRegexp.exec(l10nFilePath);
|
||||||
|
let resourceName = match[2];
|
||||||
|
resourceName = resourceName.replace(/\//g, '-');
|
||||||
|
resourceName = resourceName.replace(/\./g, '');
|
||||||
|
return resourceName;
|
||||||
|
};
|
||||||
|
|
||||||
|
// start with the general l10n file, which is an exception to the format
|
||||||
|
let resources = [{
|
||||||
|
filename: 'src/l10n.json',
|
||||||
|
resourceName: 'general-l10njson'
|
||||||
|
}];
|
||||||
|
|
||||||
|
glob('src/views/**/l10n.json', {}, function (er, files) {
|
||||||
|
files.forEach(filename => {
|
||||||
|
// figure out likely resource name from file path
|
||||||
|
let resourceName = txResourceNameFromPath(filename);
|
||||||
|
if (filename in overrides) { // see if it needs overriding
|
||||||
|
resourceName = overrides[filename];
|
||||||
|
}
|
||||||
|
resources.push({
|
||||||
|
filename: filename,
|
||||||
|
resourceName: resourceName
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
let cmd;
|
||||||
|
resources.forEach(resource => {
|
||||||
|
cmd = `$(npm bin)/tx-push-src scratch-website ${resource.resourceName} ${resource.filename}`;
|
||||||
|
if (execute) {
|
||||||
|
// push all the source files to transifex - force update
|
||||||
|
process.stdout.write(`running command: ${cmd}\n`);
|
||||||
|
execSync(cmd, {stdio: 'inherit'});
|
||||||
|
} else {
|
||||||
|
process.stdout.write(`command we would run: ${cmd}\n`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -26,6 +26,7 @@
|
||||||
"deploy:s3:all": "npm run deploy:s3cmd -- --exclude '.DS_Store' --exclude '*.svg' --exclude '*.js' ./build/ s3://$S3_BUCKET_NAME/",
|
"deploy:s3:all": "npm run deploy:s3cmd -- --exclude '.DS_Store' --exclude '*.svg' --exclude '*.js' ./build/ s3://$S3_BUCKET_NAME/",
|
||||||
"deploy:s3:svg": "npm run deploy:s3cmd -- --exclude '*' --include '*.svg' --mime-type 'image/svg+xml' ./build/ s3://$S3_BUCKET_NAME/",
|
"deploy:s3:svg": "npm run deploy:s3cmd -- --exclude '*' --include '*.svg' --mime-type 'image/svg+xml' ./build/ s3://$S3_BUCKET_NAME/",
|
||||||
"deploy:s3:js": "npm run deploy:s3cmd -- --exclude '*' --include '*.js' --mime-type 'application/javascript' ./build/ s3://$S3_BUCKET_NAME/",
|
"deploy:s3:js": "npm run deploy:s3cmd -- --exclude '*' --include '*.js' --mime-type 'application/javascript' ./build/ s3://$S3_BUCKET_NAME/",
|
||||||
|
"i18n:push": "tx-push-www --execute",
|
||||||
"translate:urls": "node ./bin/get-localized-urls localized-urls.json",
|
"translate:urls": "node ./bin/get-localized-urls localized-urls.json",
|
||||||
"translate:files": "node ./bin/build-locales node_modules/scratch-l10n/www intl",
|
"translate:files": "node ./bin/build-locales node_modules/scratch-l10n/www intl",
|
||||||
"translate": "npm run translate:urls && npm run translate:files"
|
"translate": "npm run translate:urls && npm run translate:files"
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"preview-faq.title": "Scratch 3.0 FAQ"
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
const cheerio = require('cheerio');
|
|
||||||
const injectIntl = require('react-intl').injectIntl;
|
|
||||||
const intlShape = require('react-intl').intlShape;
|
|
||||||
const React = require('react');
|
|
||||||
const xhr = require('xhr');
|
|
||||||
|
|
||||||
const InformationPage = require('../../components/informationpage/informationpage.jsx');
|
|
||||||
|
|
||||||
const Page = require('../../components/page/www/page.jsx');
|
|
||||||
const render = require('../../lib/render.jsx');
|
|
||||||
|
|
||||||
require('./preview-faq.scss');
|
|
||||||
|
|
||||||
class PreviewFaq extends React.Component {
|
|
||||||
constructor (props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
faqDoc: {__html: ''}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
componentDidMount () {
|
|
||||||
xhr({
|
|
||||||
method: 'GET',
|
|
||||||
uri: 'https://docs.google.com/document/d/e/2PACX-1vQZFrpOagYqEwcrBBCplIomiyguPAodIJVnCq9Sr11WDI_aa2b-JtDWak-Aiu-cwWobTXftRMF6wBbd/pub?embedded=true'
|
|
||||||
}, (error, response, body) => {
|
|
||||||
const $ = cheerio.load(body);
|
|
||||||
this.setState({faqDoc: {__html: $('html').html()}});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
render () {
|
|
||||||
return (
|
|
||||||
<InformationPage title={this.props.intl.formatMessage({id: 'preview-faq.title'})}>
|
|
||||||
<div className="inner">
|
|
||||||
<div
|
|
||||||
className="preview-faq"
|
|
||||||
dangerouslySetInnerHTML={this.state.faqDoc} // eslint-disable-line react/no-danger
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</InformationPage>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PreviewFaq.propTypes = {
|
|
||||||
intl: intlShape
|
|
||||||
};
|
|
||||||
|
|
||||||
const WrappedPreviewFAQ = injectIntl(PreviewFaq);
|
|
||||||
|
|
||||||
render(<Page><WrappedPreviewFAQ /></Page>, document.getElementById('app'));
|
|
|
@ -1,18 +0,0 @@
|
||||||
#view {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-faq {
|
|
||||||
margin-bottom: 5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title-banner-h1 {
|
|
||||||
line-height: 1.7em !important;
|
|
||||||
font-family: "Helvetica Neue", "Helvetica", Arial, sans-serif !important;
|
|
||||||
font-size: 2.5rem !important;
|
|
||||||
font-weight: 900 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-faq li {
|
|
||||||
margin: 0 2rem !important;
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
{
|
|
||||||
"cards.Scratch2CardsLink": "https://resources.scratch.mit.edu/www/cards/en/Scratch2Cards.pdf",
|
|
||||||
"cards.ScratchCardsAllLink": "https://resources.scratch.mit.edu/www/cards/en/ScratchCardsAll.pdf",
|
|
||||||
"cards.catchCardsLink": "https://resources.scratch.mit.edu/www/cards/en/catchCards.pdf",
|
|
||||||
"cards.danceCardsLink": "https://resources.scratch.mit.edu/www/cards/en/danceCards.pdf",
|
|
||||||
"cards.dressupCardsLink": "https://resources.scratch.mit.edu/www/cards/en/dressupCards.pdf",
|
|
||||||
"cards.fashionCardsLink": "https://resources.scratch.mit.edu/www/cards/en/fashionCards.pdf",
|
|
||||||
"cards.flyCardsLink": "https://resources.scratch.mit.edu/www/cards/en/flyCards.pdf",
|
|
||||||
"cards.hide-seekCardsLink": "https://resources.scratch.mit.edu/www/cards/en/hide-seekCards.pdf",
|
|
||||||
"cards.musicCardsLink": "https://resources.scratch.mit.edu/www/cards/en/musicCards.pdf",
|
|
||||||
"cards.nameCardsLink": "https://resources.scratch.mit.edu/www/cards/en/nameCards.pdf",
|
|
||||||
"cards.petCardsLink": "https://resources.scratch.mit.edu/www/cards/en/petCards.pdf",
|
|
||||||
"cards.pongCardsLink": "https://resources.scratch.mit.edu/www/cards/en/pongCards.pdf",
|
|
||||||
"cards.raceCardsLink": "https://resources.scratch.mit.edu/www/cards/en/raceCards.pdf",
|
|
||||||
"cards.storyCardsLink": "https://resources.scratch.mit.edu/www/cards/en/storyCards.pdf",
|
|
||||||
"guides.CatchGuideLink": "https://resources.scratch.mit.edu/www/guides/en/CatchGuide.pdf",
|
|
||||||
"guides.DanceGuideLink": "https://resources.scratch.mit.edu/www/guides/en/DanceGuide.pdf",
|
|
||||||
"guides.FashionGuideLink": "https://resources.scratch.mit.edu/www/guides/en/FashionGuide.pdf",
|
|
||||||
"guides.FlyGuideLink": "https://resources.scratch.mit.edu/www/guides/en/FlyGuide.pdf",
|
|
||||||
"guides.Getting-Started-Guide-Scratch2Link": "https://resources.scratch.mit.edu/www/guides/en/Getting-Started-Guide-Scratch2.pdf",
|
|
||||||
"guides.HideandSeekGuideLink": "https://resources.scratch.mit.edu/www/guides/en/HideandSeekGuide.pdf",
|
|
||||||
"guides.MusicGuideLink": "https://resources.scratch.mit.edu/www/guides/en/MusicGuide.pdf",
|
|
||||||
"guides.NameGuideLink": "https://resources.scratch.mit.edu/www/guides/en/NameGuide.pdf",
|
|
||||||
"guides.PetGuideLink": "https://resources.scratch.mit.edu/www/guides/en/PetGuide.pdf",
|
|
||||||
"guides.PongGuideLink": "https://resources.scratch.mit.edu/www/guides/en/PongGuide.pdf",
|
|
||||||
"guides.RaceGuideLink": "https://resources.scratch.mit.edu/www/guides/en/RaceGuide.pdf",
|
|
||||||
"guides.StoryGuideLink": "https://resources.scratch.mit.edu/www/guides/en/StoryGuide.pdf"
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
{
|
|
||||||
"tips.title": "Getting Started",
|
|
||||||
"tips.subTitle": "Start making projects in Scratch by trying the <a href=\"/projects/editor/?tip_bar=getStarted\" class=\"mod-underline\">online tutorial</a> or downloading the <a href=\"{GettingStartedPDF}\" class=\"mod-underline\">PDF Guide</a>.",
|
|
||||||
"tips.tryGettingStarted": "Try the Getting Started tutorial",
|
|
||||||
"tips.tttHeader": "Things to Try",
|
|
||||||
"tips.tttBody": "What do you want to make with Scratch? For each activity, you can try the <strong>Tutorial</strong>, download a set of <strong>Activity Cards</strong>, or view the <strong>Educator Guide</strong>.",
|
|
||||||
"tips.cardsHeader": "Get the Entire Collection of Activity Cards",
|
|
||||||
"tips.cardsBody": "With the Scratch Activity Cards, you can learn to create interactive games, stories, music, animations, and more!",
|
|
||||||
"tips.cardsPurchase": "Purchase Printed Set",
|
|
||||||
"tips.starterProjectsHeader": "Starter Projects",
|
|
||||||
"tips.starterProjectsBody": "You can play with Starter Projects to get ideas for making your own projects.",
|
|
||||||
"tips.starterProjectsPlay": "Play with Starter Projects",
|
|
||||||
"tips.offlineEditorHeader": "Offline Editor",
|
|
||||||
"tips.offlineEditorBody": "To create projects without an Internet connection, you can <a href=\"/download\">download the offline editor</a>.",
|
|
||||||
"tips.questionsHeader": "Questions",
|
|
||||||
"tips.questionsBody": "Have more questions? See the <a href=\"/info/faq\">Frequently Asked Questions</a> or visit the <a href=\"/discuss/7/\">Help with Scripts Forum</a>.",
|
|
||||||
"ttt.tutorial": "Tutorial",
|
|
||||||
"tile.guides": "See Cards and Guides",
|
|
||||||
"tile.tryIt": "Try It",
|
|
||||||
"ttt.placeholder": "Placeholder text",
|
|
||||||
"ttt.tutorialSubtitle": "Find out how to make this project using a step-by-step tutorial in Scratch.",
|
|
||||||
"ttt.activityTitle": "Activity Cards",
|
|
||||||
"ttt.activitySubtitle": "Explore new coding ideas using this set of illustrated cards you can print out.",
|
|
||||||
"ttt.educatorTitle": "Educator Guide",
|
|
||||||
"ttt.educatorSubtitle": "Use this educator guide to plan and lead a one-hour Scratch workshop.",
|
|
||||||
"ttt.open": "Open",
|
|
||||||
"ttt.MakeItFlyTitle": "Make It Fly",
|
|
||||||
"ttt.MakeItFlyDescription": "Animate the Scratch Cat, The Powerpuff Girls, or even a taco!",
|
|
||||||
"ttt.AnimateYourNameTitle": "Animate a Name",
|
|
||||||
"ttt.AnimateYourNameDescription": "Animate the letters of your username, initials, or favorite word.",
|
|
||||||
"ttt.RaceTitle": "Race to the Finish",
|
|
||||||
"ttt.RaceDescription": "Make a game where two characters race each other.",
|
|
||||||
"ttt.MakeMusicTitle": "Make Music",
|
|
||||||
"ttt.MakeMusicDescription": "Choose instruments, add sounds, and press keys to play music.",
|
|
||||||
"ttt.HideAndSeekTitle": "Hide and Seek",
|
|
||||||
"ttt.HideAndSeekDescription": "Make a hide-and-seek game with characters that appear and disappear.",
|
|
||||||
"ttt.StoryTitle": "Create a Story",
|
|
||||||
"ttt.StoryDescription": "Choose characters, add conversation, and bring your story to life.",
|
|
||||||
"ttt.FashionTitle": "Fashion Game",
|
|
||||||
"ttt.FashionDescription": "Make a game where you dress a character with different clothes and styles.",
|
|
||||||
"ttt.PongTitle": "Pong Game",
|
|
||||||
"ttt.PongDescription": "Make a bouncing ball game with sounds, points, and other effects.",
|
|
||||||
"ttt.DanceTitle": "Let's Dance",
|
|
||||||
"ttt.DanceDescription": "Design an animated dance scene with music and dance moves.",
|
|
||||||
"ttt.CatchTitle": "Catch Game",
|
|
||||||
"ttt.CatchDescription": "Make a game where you catch things falling from the sky.",
|
|
||||||
"ttt.VirtualPetTitle": "Virtual Pet",
|
|
||||||
"ttt.VirtualPetDescription": "Create an interactive pet that can eat, drink, and play."
|
|
||||||
}
|
|
|
@ -1,234 +0,0 @@
|
||||||
const bindAll = require('lodash.bindall');
|
|
||||||
const FormattedHTMLMessage = require('react-intl').FormattedHTMLMessage;
|
|
||||||
const FormattedMessage = require('react-intl').FormattedMessage;
|
|
||||||
const injectIntl = require('react-intl').injectIntl;
|
|
||||||
const intlShape = require('react-intl').intlShape;
|
|
||||||
const React = require('react');
|
|
||||||
|
|
||||||
const Button = require('../../components/forms/button.jsx');
|
|
||||||
const FlexRow = require('../../components/flex-row/flex-row.jsx');
|
|
||||||
const MasonryGrid = require('../../components/masonrygrid/masonrygrid.jsx');
|
|
||||||
const TitleBanner = require('../../components/title-banner/title-banner.jsx');
|
|
||||||
const TTTModal = require('../../components/modal/ttt/modal.jsx');
|
|
||||||
const TTTTile = require('../../components/ttt-tile/ttt-tile.jsx');
|
|
||||||
|
|
||||||
const Page = require('../../components/page/www/page.jsx');
|
|
||||||
const render = require('../../lib/render.jsx');
|
|
||||||
|
|
||||||
const Tiles = require('./ttt.json');
|
|
||||||
|
|
||||||
require('./tips.scss');
|
|
||||||
|
|
||||||
class Tips extends React.Component {
|
|
||||||
constructor (props) {
|
|
||||||
super(props);
|
|
||||||
bindAll(this, [
|
|
||||||
'handleShowTTTModal',
|
|
||||||
'handleHideTTTModal',
|
|
||||||
'renderTTTTiles'
|
|
||||||
]);
|
|
||||||
this.state = {
|
|
||||||
currentTile: Tiles[0],
|
|
||||||
TTTModalOpen: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
handleShowTTTModal (tile) {
|
|
||||||
// expects translated tile
|
|
||||||
this.setState({
|
|
||||||
currentTile: tile,
|
|
||||||
TTTModalOpen: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
handleHideTTTModal () {
|
|
||||||
this.setState({
|
|
||||||
TTTModalOpen: false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
renderTTTTiles () {
|
|
||||||
|
|
||||||
return Tiles.map((tile, key) => {
|
|
||||||
const translatedTile = {
|
|
||||||
activityLoc: this.props.intl.formatMessage({id: tile.activityLoc}),
|
|
||||||
bannerUrl: tile.bannerUrl,
|
|
||||||
description: this.props.intl.formatMessage({id: tile.description}),
|
|
||||||
guideLoc: this.props.intl.formatMessage({id: tile.guideLoc}),
|
|
||||||
thumbUrl: tile.thumbUrl,
|
|
||||||
title: this.props.intl.formatMessage({id: tile.title}),
|
|
||||||
tutorialLoc: tile.tutorialLoc
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<TTTTile
|
|
||||||
key={key}
|
|
||||||
onGuideClick={() => { // eslint-disable-line react/jsx-no-bind
|
|
||||||
this.handleShowTTTModal(translatedTile);
|
|
||||||
}}
|
|
||||||
{...translatedTile}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
render () {
|
|
||||||
return (
|
|
||||||
<div className="tips">
|
|
||||||
<TitleBanner className="masthead mod-blue-bg">
|
|
||||||
<h1 className="title-banner-h1">
|
|
||||||
<FormattedMessage id="tips.title" />
|
|
||||||
</h1>
|
|
||||||
<p className="intro title-banner-p">
|
|
||||||
<FormattedHTMLMessage
|
|
||||||
id="tips.subTitle"
|
|
||||||
values={{
|
|
||||||
GettingStartedPDF: this.props.intl.formatMessage({
|
|
||||||
id: 'guides.Getting-Started-Guide-Scratch2Link'
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<p className="title-banner-p">
|
|
||||||
<a href="/projects/editor/?tip_bar=getStarted">
|
|
||||||
<Button className="tips-button getting-started-button">
|
|
||||||
<img src="/images/tips/blocks-icon.svg" />
|
|
||||||
<FormattedMessage id="tips.tryGettingStarted" />
|
|
||||||
</Button>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</TitleBanner>
|
|
||||||
<div className="inner">
|
|
||||||
<section className="ttt-section">
|
|
||||||
<div className="ttt-head">
|
|
||||||
<h2>
|
|
||||||
<FormattedMessage id="tips.tttHeader" />
|
|
||||||
</h2>
|
|
||||||
<p>
|
|
||||||
<FormattedHTMLMessage id="tips.tttBody" />
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<MasonryGrid >
|
|
||||||
{this.renderTTTTiles()}
|
|
||||||
</MasonryGrid>
|
|
||||||
<TTTModal
|
|
||||||
isOpen={this.state.TTTModalOpen}
|
|
||||||
onRequestClose={this.handleHideTTTModal}
|
|
||||||
{...this.state.currentTile}
|
|
||||||
/>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
<div className="tips-resources">
|
|
||||||
<div className="inner">
|
|
||||||
<FlexRow
|
|
||||||
as="section"
|
|
||||||
className="tips-info-section cards-info"
|
|
||||||
>
|
|
||||||
<div className="tips-info-body">
|
|
||||||
<h2>
|
|
||||||
<FormattedMessage id="tips.cardsHeader" />
|
|
||||||
</h2>
|
|
||||||
<p>
|
|
||||||
<FormattedHTMLMessage id="tips.cardsBody" />
|
|
||||||
</p>
|
|
||||||
<p className="tips-cards-buttons">
|
|
||||||
<a
|
|
||||||
href={this.props.intl.formatMessage({
|
|
||||||
id: 'cards.ScratchCardsAllLink'
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<Button className="tips-button">
|
|
||||||
<FormattedMessage id="general.downloadPDF" />
|
|
||||||
</Button>
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href="https://scratch-foundation.myshopify.com/collections/all-products/products/scratch-coding-cards-creative-coding-activities-for-kids"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
target="_blank"
|
|
||||||
>
|
|
||||||
<Button className="tips-button purchase-button">
|
|
||||||
<FormattedMessage id="tips.cardsPurchase" />
|
|
||||||
<img src="/images/tips/arrow-icon.svg" />
|
|
||||||
</Button>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="tips-info-body tips-illustration">
|
|
||||||
<img src="/images/tips/cards-illustration.svg" />
|
|
||||||
</div>
|
|
||||||
</FlexRow>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="inner">
|
|
||||||
<div className="tips-divider" />
|
|
||||||
</div>
|
|
||||||
<div className="tips-resources">
|
|
||||||
<div className="inner">
|
|
||||||
<FlexRow
|
|
||||||
as="section"
|
|
||||||
className="tips-info-section"
|
|
||||||
>
|
|
||||||
<div className="tips-info-body tips-illustration">
|
|
||||||
<img
|
|
||||||
className="mod-flow-left"
|
|
||||||
src="/images/tips/project-illustration.svg"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="tips-info-body">
|
|
||||||
<h2>
|
|
||||||
<FormattedMessage id="tips.starterProjectsHeader" />
|
|
||||||
</h2>
|
|
||||||
<p>
|
|
||||||
<FormattedHTMLMessage id="tips.starterProjectsBody" />
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a href="/starter_projects">
|
|
||||||
<Button className="tips-button">
|
|
||||||
<FormattedMessage id="tips.starterProjectsPlay" />
|
|
||||||
</Button>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</FlexRow>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="inner">
|
|
||||||
<FlexRow
|
|
||||||
as="section"
|
|
||||||
className="tips-info-section mod-align-top"
|
|
||||||
>
|
|
||||||
<div className="tips-info-body mod-narrow">
|
|
||||||
<img
|
|
||||||
className="tips-icon"
|
|
||||||
src="/images/tips/download-icon.svg"
|
|
||||||
/>
|
|
||||||
<h3>
|
|
||||||
<FormattedMessage id="tips.offlineEditorHeader" />
|
|
||||||
</h3>
|
|
||||||
<p>
|
|
||||||
<FormattedHTMLMessage id="tips.offlineEditorBody" />
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="tips-info-body mod-narrow">
|
|
||||||
<img
|
|
||||||
className="tips-icon"
|
|
||||||
src="/images/tips/question-icon.svg"
|
|
||||||
/>
|
|
||||||
<h3>
|
|
||||||
<FormattedMessage id="tips.questionsHeader" />
|
|
||||||
</h3>
|
|
||||||
<p>
|
|
||||||
<FormattedHTMLMessage id="tips.questionsBody" />
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</FlexRow>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Tips.propTypes = {
|
|
||||||
intl: intlShape
|
|
||||||
};
|
|
||||||
|
|
||||||
const WrappedTips = injectIntl(Tips);
|
|
||||||
|
|
||||||
render(
|
|
||||||
<Page><WrappedTips /></Page>, document.getElementById('app'));
|
|
|
@ -1,221 +0,0 @@
|
||||||
@import "../../colors";
|
|
||||||
@import "../../frameless";
|
|
||||||
|
|
||||||
$base-bg: $ui-white;
|
|
||||||
|
|
||||||
#view {
|
|
||||||
background-color: $ui-gray;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tips-resources {
|
|
||||||
background-color: $ui-white;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ttt-section {
|
|
||||||
display: flex;
|
|
||||||
margin: 0 auto;
|
|
||||||
text-align: center;
|
|
||||||
justify-content: center;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tips-divider {
|
|
||||||
border-top: 1px solid $ui-gray;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tips-banner-image {
|
|
||||||
max-width: calc(100% - 2rem);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tips-button {
|
|
||||||
margin-right: .75rem;
|
|
||||||
background-color: $ui-blue;
|
|
||||||
color: $ui-white;
|
|
||||||
font-size: 1rem;
|
|
||||||
|
|
||||||
&.getting-started-button {
|
|
||||||
margin-right: 0;
|
|
||||||
background-color: $ui-white;
|
|
||||||
color: $link-blue;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
margin-right: 1rem;
|
|
||||||
height: 1.25rem;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: $ui-white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.purchase-button {
|
|
||||||
img {
|
|
||||||
margin-right: 0;
|
|
||||||
margin-left: .75rem;
|
|
||||||
width: 1rem;
|
|
||||||
vertical-align: baseline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tips-info-section {
|
|
||||||
padding: 2.5rem 0;
|
|
||||||
width: 100%;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tips-info-body {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tips-cards-buttons {
|
|
||||||
a {
|
|
||||||
white-space: normal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
img.tips-icon {
|
|
||||||
height: 1.75rem;
|
|
||||||
}
|
|
||||||
//4 columns
|
|
||||||
@media #{$small} {
|
|
||||||
|
|
||||||
.title-banner {
|
|
||||||
&.masthead {
|
|
||||||
padding-bottom: 1.25rem;
|
|
||||||
|
|
||||||
p {
|
|
||||||
max-width: $cols4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.ttt-head {
|
|
||||||
|
|
||||||
p {
|
|
||||||
max-width: $cols4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//put the image first if in 4-column
|
|
||||||
.tips-info-body {
|
|
||||||
max-width: $cols4;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
&.tips-illustration {
|
|
||||||
order: -1;
|
|
||||||
img {
|
|
||||||
width: $cols4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//6 columns
|
|
||||||
@media #{$medium} {
|
|
||||||
.title-banner {
|
|
||||||
&.masthead {
|
|
||||||
|
|
||||||
p {
|
|
||||||
max-width: $cols6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.ttt-head {
|
|
||||||
p {
|
|
||||||
max-width: $cols6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tips-info-body.tips-illustration {
|
|
||||||
order: -1;
|
|
||||||
img {
|
|
||||||
width: $cols4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tips-info-body {
|
|
||||||
max-width: $cols4;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//8 columns
|
|
||||||
@media #{$intermediate} {
|
|
||||||
.title-banner {
|
|
||||||
&.masthead {
|
|
||||||
padding-bottom: 2rem;
|
|
||||||
|
|
||||||
p {
|
|
||||||
max-width: $cols6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.ttt-head {
|
|
||||||
p {
|
|
||||||
max-width: $cols6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tips-info-section {
|
|
||||||
&.mod-align-top {
|
|
||||||
align-items: flex-start;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tips-info-body {
|
|
||||||
max-width: $cols4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tips-button {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
img.mod-flow-left {
|
|
||||||
transform: translate(-1*$cols2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 12 columns
|
|
||||||
@media #{$big} {
|
|
||||||
.title-banner {
|
|
||||||
&.masthead {
|
|
||||||
padding-bottom: 1.25rem;
|
|
||||||
|
|
||||||
p {
|
|
||||||
max-width: $cols8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.ttt-head {
|
|
||||||
p {
|
|
||||||
max-width: $cols8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tips-info-section {
|
|
||||||
&.mod-align-top {
|
|
||||||
align-items: flex-start;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tips-info-body {
|
|
||||||
max-width: $cols6;
|
|
||||||
&.mod-narrow {
|
|
||||||
max-width: $cols5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,101 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"title": "ttt.AnimateYourNameTitle",
|
|
||||||
"description": "ttt.AnimateYourNameDescription",
|
|
||||||
"thumbUrl": "/images/ttt/animate-your-name.jpg",
|
|
||||||
"bannerUrl": "/images/ttt/animate-your-name-banner.jpg",
|
|
||||||
"tutorialLoc": "/projects/editor/?tip_bar=name",
|
|
||||||
"activityLoc": "cards.nameCardsLink",
|
|
||||||
"guideLoc": "guides.NameGuideLink"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "ttt.MakeItFlyTitle",
|
|
||||||
"description": "ttt.MakeItFlyDescription",
|
|
||||||
"thumbUrl": "/images/ttt/make-it-fly.jpg",
|
|
||||||
"bannerUrl": "/images/ttt/make-it-fly-banner.jpg",
|
|
||||||
"tutorialLoc": "/projects/editor/?tip_bar=fly",
|
|
||||||
"activityLoc": "cards.flyCardsLink",
|
|
||||||
"guideLoc": "guides.FlyGuideLink"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "ttt.MakeMusicTitle",
|
|
||||||
"description": "ttt.MakeMusicDescription",
|
|
||||||
"thumbUrl": "/images/ttt/make-music.jpg",
|
|
||||||
"bannerUrl": "/images/ttt/make-music-banner.jpg",
|
|
||||||
"tutorialLoc": "/projects/editor/?tip_bar=music",
|
|
||||||
"activityLoc": "cards.musicCardsLink",
|
|
||||||
"guideLoc": "guides.MusicGuideLink"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "ttt.RaceTitle",
|
|
||||||
"description": "ttt.RaceDescription",
|
|
||||||
"thumbUrl": "/images/ttt/race-to-the-finish.jpg",
|
|
||||||
"bannerUrl": "/images/ttt/race-to-the-finish-banner.jpg",
|
|
||||||
"tutorialLoc": "/projects/editor/?tip_bar=racegame",
|
|
||||||
"activityLoc": "cards.raceCardsLink",
|
|
||||||
"guideLoc": "guides.RaceGuideLink"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "ttt.HideAndSeekTitle",
|
|
||||||
"description": "ttt.HideAndSeekDescription",
|
|
||||||
"thumbUrl": "/images/ttt/hide-and-seek.jpg",
|
|
||||||
"bannerUrl": "/images/ttt/hide-and-seek-banner.jpg",
|
|
||||||
"tutorialLoc": "/projects/editor/?tip_bar=hide",
|
|
||||||
"activityLoc": "cards.hide-seekCardsLink",
|
|
||||||
"guideLoc": "guides.HideandSeekGuideLink"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "ttt.FashionTitle",
|
|
||||||
"description": "ttt.FashionDescription",
|
|
||||||
"thumbUrl": "/images/ttt/fashion-game.jpg",
|
|
||||||
"bannerUrl": "/images/ttt/fashion-game-banner.jpg",
|
|
||||||
"tutorialLoc": "/projects/editor/?tip_bar=fashion",
|
|
||||||
"activityLoc": "cards.fashionCardsLink",
|
|
||||||
"guideLoc": "guides.FashionGuideLink"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "ttt.StoryTitle",
|
|
||||||
"description": "ttt.StoryDescription",
|
|
||||||
"thumbUrl": "/images/ttt/create-a-story.jpg",
|
|
||||||
"bannerUrl": "/images/ttt/create-a-story-banner.jpg",
|
|
||||||
"tutorialLoc": "/projects/editor/?tip_bar=story",
|
|
||||||
"activityLoc": "cards.storyCardsLink",
|
|
||||||
"guideLoc": "guides.StoryGuideLink"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "ttt.PongTitle",
|
|
||||||
"description": "ttt.PongDescription",
|
|
||||||
"thumbUrl": "/images/ttt/pong-game.jpg",
|
|
||||||
"bannerUrl": "/images/ttt/pong-game-banner.jpg",
|
|
||||||
"tutorialLoc": "/projects/editor/?tip_bar=pong",
|
|
||||||
"activityLoc": "cards.pongCardsLink",
|
|
||||||
"guideLoc": "guides.PongGuideLink"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "ttt.DanceTitle",
|
|
||||||
"description": "ttt.DanceDescription",
|
|
||||||
"thumbUrl": "/images/ttt/lets-dance.jpg",
|
|
||||||
"bannerUrl": "/images/ttt/lets-dance-banner.jpg",
|
|
||||||
"tutorialLoc": "/projects/editor/?tip_bar=dance",
|
|
||||||
"activityLoc": "cards.danceCardsLink",
|
|
||||||
"guideLoc": "guides.DanceGuideLink"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "ttt.CatchTitle",
|
|
||||||
"description": "ttt.CatchDescription",
|
|
||||||
"thumbUrl": "/images/ttt/catch-game.jpg",
|
|
||||||
"bannerUrl": "/images/ttt/catch-game-banner.jpg",
|
|
||||||
"tutorialLoc": "/projects/editor/?tip_bar=catch",
|
|
||||||
"activityLoc": "cards.catchCardsLink",
|
|
||||||
"guideLoc": "guides.CatchGuideLink"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "ttt.VirtualPetTitle",
|
|
||||||
"description": "ttt.VirtualPetDescription",
|
|
||||||
"thumbUrl": "/images/ttt/virtual-pet.jpg",
|
|
||||||
"bannerUrl": "/images/ttt/virtual-pet-banner.jpg",
|
|
||||||
"tutorialLoc": "/projects/editor/?tip_bar=pet",
|
|
||||||
"activityLoc": "cards.petCardsLink",
|
|
||||||
"guideLoc": "guides.PetGuideLink"
|
|
||||||
}
|
|
||||||
]
|
|
Loading…
Reference in a new issue