From 1ab7a2792931f254b2987d674028c9a8fea3d727 Mon Sep 17 00:00:00 2001 From: Matthew Taylor Date: Wed, 2 Dec 2015 17:12:01 -0500 Subject: [PATCH 01/38] Add apache 2.0 license --- LICENSE.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 LICENSE.md diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 000000000..a36476508 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,13 @@ +Copyright 2015 Lifelong Kindergarten Group + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file From 6285c3f7550841a11165123c28e9410f9dedf566 Mon Sep 17 00:00:00 2001 From: Matthew Taylor Date: Wed, 2 Dec 2015 17:12:32 -0500 Subject: [PATCH 02/38] Add contribution mardown file This is also the homepage of the wiki. --- CONTRIBUTING.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..6584d9fd7 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,34 @@ +### Where am I? ### +Physically? No idea. + +Digitally? You’re at Scratch’s open source Web Client! + +At Scratch, we’re working to update our UI to use a new codebase, which will be contained in this repository. The transition from existing to new codebase is an ongoing process, and we love to have people in the Scratch and Open Source communities help us along the way, and even afterwards as we develop new features for Scratch here. + + +### Who and what will I find here? ### +We are always excited to have people join us in working to make Scratch a wonderful place for people of all ages to make projects together. If you’re new here, and looking to jump into our wonderful community, we have some wonderful resources for you to take a look at: + +* [README](https://github.com/LLK/scratch-www/blob/develop/README.md) (if you’re to read only one me in this repo, make it this one – it has all of the necessary information for getting a local Scratch UI running on your machine!) +* [Community Guidelines](https://github.com/LLK/scratch-www/wiki/Community-Guidelines) (we find it important to maintain a constructive and welcoming community, just like on Scratch) +* [Issues](https://github.com/LLK/scratch-www/issues) – where we keep track of all the things that need fixin’ on the website +Road map + +Beyond this repo, there are also some other resources that you might want to take a look at: +Scratch (the thing we work on) +Bugs & Glitches forum on Scratch (where mosquitoes and dei ex machina congregate) +Advanced Topics forum on Scratch (like Topics, but more complex-y) + + +### I wanna contribute! ### +Sweet! Here are some ways you can contribute: +* [Report bugs](https://github.com/LLK/scratch-www/wiki/Reporting-Bugs) +* [Work on bugs](https://github.com/LLK/scratch-www/wiki/Workflow-for-Repo-Contributions) + * Make sure to check out how to [assign yourself bugs](https://github.com/LLK/scratch-www/wiki/Assigning-Yourself-Bugs) too. + + +We’re currently building Scratch using [React](https://facebook.github.io/react/) and [SCSS](http://sass-lang.com/documentation/file.SASS_REFERENCE.html). Here are some resources to help you get acquainted with how we’re working on the Scratch codebase: +* [Style Guide](https://github.com/LLK/scratch-www/wiki/Style-Guide) +* [Testing Guide](https://github.com/LLK/scratch-www/wiki/Testing-Guide) +* [Localization Guide](https://github.com/LLK/scratch-www/wiki/Localization-Guide) +* [Map of the repository](https://github.com/LLK/scratch-www/wiki/Repo-Map) From ebc306a67332323b74d8109e9c3379024e903615 Mon Sep 17 00:00:00 2001 From: Matthew Taylor Date: Wed, 2 Dec 2015 17:13:33 -0500 Subject: [PATCH 03/38] Add some extra info to readme 1. note on installing node/npm before getting started 2. note emphasizing that default setup means pointing to real data on the Scratch website. --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index a92481006..aa09b0e58 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,9 @@ [![Build Status](https://magnum.travis-ci.com/LLK/scratch-www.svg?token=xzzHj4ct3SyBTpeqxnx1)](https://magnum.travis-ci.com/LLK/scratch-www) +### Before Getting Started +* make sure you have npm [installed](https://docs.npmjs.com/getting-started/installing-node) + ### To Build ```bash npm install @@ -16,6 +19,10 @@ npm start During development, `npm start` watches any update you make to files in either `./static` or `./src` and triggers a rebuild of the project. In development the build is stored in memory, and not served from the `./build` directory. +When running `npm start`, here are some important log messages to keep an eye out for: +* `webpack: bundle is now VALID.` – the bundle has been loaded into memory and is now viewable in the browser. This will show up both once `npm start` has completed its setup, and also once updates you make to files have been re-compiled for viewing in the browser. +* `webpack: bundle is now INVALID.` – if you see this, then it means you have made updates to files that are still being compiled for browser viewing. Pages will still be viewable, but they will not see any updates you made yet. + Once running, open `http://localhost:8333` in your browser. If you wish to have the server reload automatically, you can install either [nodemon](https://github.com/remy/nodemon) or [forever](https://github.com/foreverjs/forever). ### To stop @@ -32,6 +39,8 @@ Use `^C` to stop the node process `npm start` starts. | `PORT` | `8333` | Port for devserver (http://localhost:XXXX) | | `FALLBACK` | `''` | Pass-through location for scratchr2 | +**NOTE:** Because by default both `API_HOST=https://api.scratch.mit.edu` and `PROXY_HOST=https://scratch.mit.edu`, please be aware that, by default, you will be seeing and interacting with real data on the Scratch website. + ### To Test ```bash npm test From 82008c3fa11fa674cac484bea26c2513b5ecb68f Mon Sep 17 00:00:00 2001 From: Matthew Taylor Date: Tue, 8 Dec 2015 09:49:37 -0500 Subject: [PATCH 04/38] Update for rename --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aa09b0e58..37aab25bf 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ Use `^C` to stop the node process `npm start` starts. | `PORT` | `8333` | Port for devserver (http://localhost:XXXX) | | `FALLBACK` | `''` | Pass-through location for scratchr2 | -**NOTE:** Because by default both `API_HOST=https://api.scratch.mit.edu` and `PROXY_HOST=https://scratch.mit.edu`, please be aware that, by default, you will be seeing and interacting with real data on the Scratch website. +**NOTE:** Because by default both `API_HOST=https://api.scratch.mit.edu` and `FALLBACK=https://scratch.mit.edu`, please be aware that, by default, you will be seeing and interacting with real data on the Scratch website. ### To Test ```bash From 76bab4c915eb2adf855c42fbb45b53bb138c79b7 Mon Sep 17 00:00:00 2001 From: Matthew Taylor Date: Wed, 16 Dec 2015 15:51:18 -0500 Subject: [PATCH 05/38] Some fixes based on feedback Thanks @thisandagain! --- CONTRIBUTING.md | 7 ++++--- LICENSE.md | 2 +- README.md | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6584d9fd7..cee92531a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,9 +15,10 @@ We are always excited to have people join us in working to make Scratch a wonder Road map Beyond this repo, there are also some other resources that you might want to take a look at: -Scratch (the thing we work on) -Bugs & Glitches forum on Scratch (where mosquitoes and dei ex machina congregate) -Advanced Topics forum on Scratch (like Topics, but more complex-y) +[Scratch](https://scratch.mit.edu/) (the thing we work on) +[Open Source forum](https://scratch.mit.edu/discuss/49/) on Scratch (talk about the thing we work on on the thing we work on. so meta.) +[Bugs & Glitches forum](https://scratch.mit.edu/discuss/3/) on Scratch (where mosquitoes and dei ex machina congregate) +[Advanced Topics forum](https://scratch.mit.edu/discuss/31/) on Scratch (like Topics, but more complex-y) ### I wanna contribute! ### diff --git a/LICENSE.md b/LICENSE.md index a36476508..8578cae57 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,4 +1,4 @@ -Copyright 2015 Lifelong Kindergarten Group +Copyright 2015 Massachusetts Institute of Technology Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index 37aab25bf..8f5d1e750 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Build Status](https://magnum.travis-ci.com/LLK/scratch-www.svg?token=xzzHj4ct3SyBTpeqxnx1)](https://magnum.travis-ci.com/LLK/scratch-www) ### Before Getting Started -* make sure you have npm [installed](https://docs.npmjs.com/getting-started/installing-node) +* make sure you have node and npm [installed](https://docs.npmjs.com/getting-started/installing-node) ### To Build ```bash @@ -37,7 +37,7 @@ Use `^C` to stop the node process `npm start` starts. | `API_HOST` | `https://api.scratch.mit.edu` | Hostname for API requests | | `NODE_ENV` | `null` | If not `production`, app acts like development | | `PORT` | `8333` | Port for devserver (http://localhost:XXXX) | -| `FALLBACK` | `''` | Pass-through location for scratchr2 | +| `FALLBACK` | `''` | Pass-through location for old site | **NOTE:** Because by default both `API_HOST=https://api.scratch.mit.edu` and `FALLBACK=https://scratch.mit.edu`, please be aware that, by default, you will be seeing and interacting with real data on the Scratch website. From 0a313ad29bb711a3e10a2784a2cad8eb37a6859c Mon Sep 17 00:00:00 2001 From: Matthew Taylor Date: Mon, 4 Jan 2016 14:18:47 -0500 Subject: [PATCH 06/38] default to pt-br if browser is set to pt If the user has not yet set their own language, but has pt in their browser, use pt-br for now, to accommodate for our large Brasilian base. Fixes #273. --- src/init.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/init.js b/src/init.js index 5418a3b4f..69c40d39a 100644 --- a/src/init.js +++ b/src/init.js @@ -64,6 +64,9 @@ var translations = require('../locales/translations.json'); var obj = jar.get('scratchlanguage'); if (typeof obj === 'undefined') { obj = window.navigator.userLanguage || window.navigator.language; + if (['pt','pt-pt','PT','PT-PT'].indexOf(obj) !== -1) { + obj = 'pt-br'; // default Portuguese users to Brazilian Portuguese due to our user base. Added in 2.2.5. + } } if (typeof translations[obj] === 'undefined') { // Fall back on the split From 8ae98d703f661dd5ad71bd007fd181a9fb4774c9 Mon Sep 17 00:00:00 2001 From: Matthew Taylor Date: Wed, 6 Jan 2016 14:09:32 -0500 Subject: [PATCH 07/38] Make localizations view-based 1. Load locale strings into `window._messages` in a separate file added to `template.html`, which contains view-specific and general strings 2. Update build-locales to compile separate files --- .gitignore | 2 +- Makefile | 5 +- bin/build-locales | 157 +++++++++++++++++++++++++++++ {lib => bin/lib}/locale-compare.js | 0 en.json | 133 ------------------------ lib/bin/build-locales | 78 -------------- package.json | 1 + server/template.html | 1 + src/init.js | 13 +-- src/l10n.json | 78 ++++++++++++++ src/lib/render.jsx | 12 ++- src/views/about/l10n.json | 26 +++++ src/views/hoc/l10n.json | 19 ++++ src/views/splash/l10n.json | 13 +++ webpack.config.js | 3 +- 15 files changed, 312 insertions(+), 229 deletions(-) create mode 100755 bin/build-locales rename {lib => bin/lib}/locale-compare.js (100%) delete mode 100644 en.json delete mode 100755 lib/bin/build-locales create mode 100644 src/l10n.json create mode 100644 src/views/about/l10n.json create mode 100644 src/views/hoc/l10n.json create mode 100644 src/views/splash/l10n.json diff --git a/.gitignore b/.gitignore index 328da9bd8..b237f39ea 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,7 @@ npm-* /build # Locales -/locales +/intl # Elastic Beanstalk Files .elasticbeanstalk/* diff --git a/Makefile b/Makefile index ed7148256..c1b645436 100644 --- a/Makefile +++ b/Makefile @@ -18,8 +18,9 @@ build: clean: rm -rf ./build + rm -rf ./intl mkdir -p build - mkdir -p locales + mkdir -p intl deploy: @@ -38,7 +39,7 @@ tag: echo $(GIT_VERSION) > ./build/version.txt translations: - ./lib/bin/build-locales locales/translations.json + ./bin/build-locales intl webpack: $(WEBPACK) --bail diff --git a/bin/build-locales b/bin/build-locales new file mode 100755 index 000000000..1c32f86ac --- /dev/null +++ b/bin/build-locales @@ -0,0 +1,157 @@ +#!/usr/bin/env node + +/* + Converts the existing .po translation files in the module to JSON files. + Requires po2json in order to work. Takes as input a directory + in which to store the resulting json translation files. + + Takes in as an argument an output directory to put translation files. + Searches for files named `l10n.json` in the `src/views/` directory to get + template english strings (as well as the general template at `src/l10n.json`). + + It compiles the template strings into a flat object that is compared against the + translations in the .po files from the `scratchr2_translations` dependency, using + an md5 of the template string without whitespace, and an md5 of the .po msgid string + without whitespace. + + The output files are javascript files that declare objects by locale. Each locale + has a sub-object with FormattedMessage ids as keys, and translated strings as + values. If no translation was found for a string, the default english will be the + value. + + Output Example: + ''' + var message = { + en: { + 'general.inAWorld': 'In a world, where bears are invisible...', + 'general.question': 'Are there bears here?', + 'general.answer': 'I dunno, but there could be...' + }, + es: { + 'general.inAWorld': 'En un mundo, donde hay osos invisibles', + 'general.question': 'Are there bears here?', + 'general.answer': 'No sé, pero es posible...' + } + } + ''' +*/ +var fs = require('fs'); +var glob = require('glob'); +var merge = require('lodash.merge'); +var path = require('path'); +var po2icu = require('po2icu'); + +var localeCompare = require('./lib/locale-compare'); + +// ----------------------------------------------------------------------------- +// Main script +// ----------------------------------------------------------------------------- + + +var args = process.argv.slice(2); + +if (!args.length) { + process.stdout.write('A destination directory must be specified.'); + process.exit(1); +} + +var poUiDir = path.resolve(__dirname, '../node_modules/scratchr2_translations/ui'); +var outputDir = path.resolve(__dirname, '../', args[0]); +try { + fs.accessSync(outputDir, fs.F_OK); +} catch (err) { + // Doesn't exist - create it. + fs.mkdirSync(outputDir); +} + +// get global locale strings first. +var globalTemplateFile = path.resolve(__dirname, '../src/l10n.json'); +// message key with english string values (i.e. default values) +var generalIds = JSON.parse(fs.readFileSync(globalTemplateFile, 'utf8')); +var viewLocales = {}; +var generalLocales = { + en: generalIds +}; + +// FormattedMessage id with english string as value. Use for default values in translations +// Sample structure: { 'general-general.blah': 'blah', 'about-about.blah': 'blahblah' } +var idsWithICU = {}; + +// reverse (i.e. english string with message key as the value) object for searching po files. +// Sample structure: { 'blah': 'general-general.blah', 'blahblah': 'about-about.blah' } +var icuWithIds = {}; + +for (var id in generalIds) { + idsWithICU['general-' + id] = generalIds[id]; + icuWithIds[generalIds[id]] = 'general-' + id; +} + +// get view-specific locale strings. +var files = glob.sync(path.resolve(__dirname, '../src/views/**/l10n.json')); +files.forEach(function (file) { + var dirPath = file.split('/'); + dirPath.pop(); + var view = dirPath.pop(); + + var viewIds = JSON.parse(fs.readFileSync(file, 'utf8')); + viewLocales[view] = { + en: viewIds + }; + for (var id in viewIds) { + idsWithICU[view + '-' + id] = viewIds[id]; + icuWithIds[viewIds[id]] = view + '-' + id; // add viewName to identifier for later + } +}); + +// 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); + +// Get ui localization strings first +glob(poUiDir + '/*', function (err, files) { + if (err) throw new Error(err); + + files.forEach(function (file) { + var lang = file.split('/').pop(); + var jsFile = path.resolve(file, 'LC_MESSAGES/djangojs.po'); + var pyFile = path.resolve(file, 'LC_MESSAGES/django.po'); + + var translations = {}; + + try { + var jsTranslations = po2icu.poFileToICUSync(lang, jsFile); + translations = localeCompare.mergeNewTranslations(translations, jsTranslations, idsWithICU, md5WithIds); + } catch (err) { + process.stdout.write(lang + ': ' + err + '\n'); + } + + try { + var pyTranslations = po2icu.poFileToICUSync(lang, pyFile); + translations = localeCompare.mergeNewTranslations(translations, pyTranslations, idsWithICU, md5WithIds); + } catch (err) { + process.stdout.write(lang + ': ' + err + '\n'); + } + + // add new translations to locale object + for (var id in translations) { + var ids = id.split('-'); // [viewName, stringId] + var viewName = ids[0]; + var stringId = ids[1]; + if (viewLocales.hasOwnProperty(viewName)) { + if (!viewLocales[viewName].hasOwnProperty(lang)) viewLocales[viewName][lang] = {}; + viewLocales[viewName][lang][stringId] = translations[id]; + } else { + // default to general + if (!generalLocales.hasOwnProperty(lang)) generalLocales[lang] = {}; + generalLocales[lang][stringId] = translations[id]; + } + } + }); + + for (var view in viewLocales) { + var viewTranslations = merge(viewLocales[view], generalLocales); + var objectString = JSON.stringify(viewTranslations); + var fileString = 'window._messages = ' + objectString + ';'; + fs.writeFileSync(outputDir + '/' + view + '.js', fileString); + } +}); diff --git a/lib/locale-compare.js b/bin/lib/locale-compare.js similarity index 100% rename from lib/locale-compare.js rename to bin/lib/locale-compare.js diff --git a/en.json b/en.json deleted file mode 100644 index e4e709ef2..000000000 --- a/en.json +++ /dev/null @@ -1,133 +0,0 @@ -{ - "general.accountSettings": "Account settings", - "general.about": "About", - "general.aboutScratch": "About Scratch", - "general.donate": "Donate", - "general.collaborators": "Collaborators", - "general.community": "Community", - "general.contactUs": "Contact Us", - "general.copyright": "Scratch is a project of the Lifelong Kindergarten Group at the MIT Media Lab", - "general.create": "Create", - "general.credits": "Credits", - "general.discuss": "Discuss", - "general.dmca": "DMCA", - "general.explore": "Explore", - "general.faq": "FAQ", - "general.forParents": "For Parents", - "general.forEducators": "For Educators", - "general.guidelines": "Community Guidelines", - "general.help": "Help", - "general.jobs": "Jobs", - "general.joinScratch": "Join Scratch", - "general.legal": "Legal", - "general.learnMore": "Learn More", - "general.messages": "Messages", - "general.myClasses": "My Classes", - "general.myStuff": "My Stuff", - "general.offlineEditor": "Offline Editor", - "general.profile": "Profile", - "general.scratchConference": "Scratch Conference", - "general.scratchday": "Scratch Day", - "general.scratchEd": "ScratchEd", - "general.scratchFoundation": "Scratch Foundation", - "general.scratchJr": "ScratchJr", - "general.search": "Search", - "general.signIn": "Sign in", - "general.statistics": "Statistics", - "general.support": "Support", - "general.tipsWindow": "Tips Window", - "general.tipsAnimateYourNameTitle": "Animate Your Name", - "general.tipsBearstack": "Bearstack Story", - "general.tipsDanceTitle": "Dance, Dance, Dance", - "general.tipsGetStarted": "Getting Started", - "general.tipsHideAndSeekTitle": "Hide-and-Seek Game", - "general.tipsPongGame": "Create a Pong Game", - "general.termsOfUse": "Terms of Use", - "general.username": "Username", - "general.viewAll": "View All", - "general.whatsHappening": "What's Happening?", - "general.wiki": "Scratch Wiki", - - "about.introOne": "With Scratch, you can program your own interactive stories, games, and animations — and share your creations with others in the online community.", - "about.introTwo": "Scratch helps young people learn to think creatively, reason systematically, and work collaboratively — essential skills for life in the 21st century.", - "about.introThree": "Scratch is a project of the Lifelong Kindergarten Group at the MIT Media Lab. It is provided free of charge.", - "about.introParents": "Info for parents", - "about.introEducators": "Info for educators", - "about.whoUsesScratch": "Who Uses Scratch?", - "about.whoUsesScratchDescription": "Scratch is designed especially for ages 8 to 16, but is used by people of all ages. Millions of people are creating Scratch projects in a wide variety of settings, including homes, schools, museums, libraries, and community centers.", - "about.aroundTheWorld": "Around the World", - "about.aroundTheWorldDescription": "Scratch is used in more than 150 different countries and available in more than 40 languages. To change languages, click the menu at the bottom of the page. Or, in the Project Editor, click the globe at the top of the page. To add or improve a translation, see the translation page.", - "about.quotes": "Quotes", - "about.quotesDescription": "The Scratch Team has received many emails from youth, parents, and educators expressing thanks for Scratch. Want to see what people are saying? You can read a collection of the quotes we've received.", - "about.learnMore": "Learn More About Scratch", - "about.learnMoreHelp": "Scratch Help Page", - "about.learnMoreFaq": "Frequently Asked Questions", - "about.learnMoreParents": "Information for Parents", - "about.learnMoreCredits": "Scratch Credits", - "about.literacy": "Learn to Code, Code to Learn", - "about.literacyDescription": "The ability to code computer programs is an important part of literacy in today’s society. When people learn to code in Scratch, they learn important strategies for solving problems, designing projects, and communicating ideas.", - "about.schools": "Scratch in Schools", - "about.schoolsDescription": "Students are learning with Scratch at all levels (from elementary school to college) and across disciplines (such as math, computer science, language arts, social studies). Educators share stories, exchange resources, ask questions, and find people on the ScratchEd website.", - "about.research": "Research", - "about.researchDescription": "The MIT Scratch Team and collaborators are researching how people use and learn with Scratch (for an introduction, see Scratch: Programming for All). Find out more about Scratch research and statistics about Scratch.", - "about.support": "Support and Funding", - "about.supportDescription": "The Scratch project, initiated in 2003, has received generous support from the National Science Foundation (grants 0325828, 1002713, 1027848, 1019396), Intel Foundation, Microsoft, MacArthur Foundation, LEGO Foundation, Code-to-Learn Foundation, Google, Dell, Fastly, Inversoft, and MIT Media Lab research consortia. If you'd like to support Scratch, please see our donate page, or contact us at donate@scratch.mit.edu.", - - "footer.about": "About Scratch", - "footer.discuss": "Discussion Forums", - "footer.help": "Help Page", - "footer.scratchFamily": "Scratch Family", - - "hoc.activityCards": "Activity Cards", - "hoc.activityCardsHeader": "Activity Cards and Guides", - "hoc.activityCardsInfo1": "Want tips and ideas for these Hour of Code™ activities? Use the activity cards to get ideas for creating with Scratch. Facilitator guides can help you plan a group activity.", - "hoc.addToStudios": "Add Your Projects to Studios", - "hoc.addToStudiosDescription": "These studios include projects created by young people around the world. Take a look at the studios to get inspired - or submit your own projects to the studios!", - "hoc.facilitatorGuide": "Facilitator Guide", - "hoc.findOutMore": "Find out more", - "hoc.helpScratch": "Help with Scratch", - "hoc.helpScratchDescription": "You can find tutorials and helpful hints in the Tips Window. For more resources, see Scratch Help", - "hoc.moreActivities": "Want More Activities?", - "hoc.moreDescription": "Check out these other tutorials. Or remix one of our Starter Projects", - "hoc.officialNotice": "The \"Hour of Code™\" is a nationwide initiative by Computer Science Education Week and Code.org to introduce millions of students to one hour of computer science and computer programming.", - "hoc.studioAlice": "Alice in Wonderland Studio", - "hoc.studioWeBareBears": "We Bare Bears Studio", - "hoc.subTitle": "With Scratch, you can program your own stories, games, and animations — and share them online.", - "hoc.tipsDescription": "Need help getting started? Looking for ideas?  You can find tutorials and helpful hints in the Tips Window", - "hoc.title": "Get Creative with Coding", - - "intro.aboutScratch": "ABOUT SCRATCH", - "intro.forEducators": "FOR EDUCATORS", - "intro.forParents": "FOR PARENTS", - "intro.joinScratch": "JOIN SCRATCH", - "intro.seeExamples": "SEE EXAMPLES", - "intro.tagLine": "Create stories, games, and animations
Share with others around the world", - "intro.tryItOut": "TRY IT OUT", - "login.forgotPassword": "Forgot Password?", - - "navigation.signOut": "Sign out", - - "news.scratchNews": "Scratch News", - - "parents.FaqAgeRangeA": "While Scratch is primarily designed for 8 to 16 year olds, it is also used by people of all ages, including younger children with their parents.", - "parents.FaqAgeRangeQ": "What is the age range for Scratch?", - "parents.FaqResourcesQ": "What resources are available for learning Scratch?", - "parents.introDescription": "Scratch is a programming language and an online community where children can program and share interactive media such as stories, games, and animation with people from all over the world. As children create with Scratch, they learn to think creatively, work collaboratively, and reason systematically. Scratch is designed and maintained by the Lifelong Kindergarten group at the MIT Media Lab.", - - "splash.featuredProjects": "Featured Projects", - "splash.featuredStudios": "Featured Studios", - "splash.projectsCuratedBy": "Projects Curated by", - "splash.scratchDesignStudioTitle": "Scratch Design Studio", - "splash.visitTheStudio": "Visit the studio", - "splash.recentlySharedProjects": "Recently Shared Projects", - "splash.projectsByScratchersFollowing": "Projects by Scratchers I'm Following", - "splash.projectsLovedByScratchersFollowing": "Projects Loved by Scratchers I'm Following", - "splash.projectsInStudiosFollowing": "Projects in Studios I'm Following", - "splash.communityRemixing": "What the Community is Remixing", - "splash.communityLoving": "What the Community is Loving", - - "welcome.welcomeToScratch": "Welcome to Scratch!", - "welcome.learn": "Learn how to make a project in Scratch", - "welcome.tryOut": "Try out starter projects", - "welcome.connect": "Connect with other Scratchers" -} diff --git a/lib/bin/build-locales b/lib/bin/build-locales deleted file mode 100755 index c315deb47..000000000 --- a/lib/bin/build-locales +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env node - -/* - Converts the existing .po translation files in the module to JSON files. - Requires po2json in order to work. Takes as input a directory - in which to store the resulting json translation files. -*/ -var fs = require('fs'); -var glob = require('glob'); -var path = require('path'); -var po2icu = require('po2icu'); - -var localeCompare = require('../locale-compare'); - -// ----------------------------------------------------------------------------- -// Main script -// ----------------------------------------------------------------------------- - - -var args = process.argv.slice(2); - -if (!args.length) { - process.stdout.write('A destination directory must be specified.'); - process.exit(1); -} - -var poUiDir = path.resolve(__dirname, '../../node_modules/scratchr2_translations/ui'); -var outputFile = path.resolve(__dirname, '../../', args[0]); -// Create the directory if it doesn't exist. -var fileInfo = path.parse(outputFile); -try { - fs.accessSync(fileInfo.dir, fs.F_OK); -} catch (err) { - // Doesn't exist – create it. - fs.mkdirSync(fileInfo.dir); -} - -var icuTemplateFile = path.resolve(__dirname, '../../en.json'); -var idsWithICU = JSON.parse(fs.readFileSync(icuTemplateFile, 'utf8')); -var locales = { - en: idsWithICU -}; - -var icuWithIds = {}; -for (var id in idsWithICU) { - icuWithIds[idsWithICU[id]] = id; -} -var md5WithIds = localeCompare.getMD5Map(icuWithIds); - -// Get ui localization strings first -glob(poUiDir + '/*', function (err, files) { - if (err) throw new Error(err); - - files.forEach(function (file) { - var lang = file.split('/').pop(); - var jsFile = path.resolve(file, 'LC_MESSAGES/djangojs.po'); - var pyFile = path.resolve(file, 'LC_MESSAGES/django.po'); - - var translations = {}; - - try { - var jsTranslations = po2icu.poFileToICUSync(lang, jsFile); - translations = localeCompare.mergeNewTranslations(translations, jsTranslations, idsWithICU, md5WithIds); - } catch (err) { - process.stdout.write(lang + ': ' + err + '\n'); - } - - try { - var pyTranslations = po2icu.poFileToICUSync(lang, pyFile); - translations = localeCompare.mergeNewTranslations(translations, pyTranslations, idsWithICU, md5WithIds); - } catch (err) { - process.stdout.write(lang + ': ' + err + '\n'); - } - - locales[lang] = translations; - }); - fs.writeFileSync(outputFile, JSON.stringify(locales, null, 4)); -}); diff --git a/package.json b/package.json index d71a7fdd6..5ca221023 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "jsx-loader": "0.13.2", "lodash.clone": "3.0.3", "lodash.defaultsdeep": "3.10.0", + "lodash.merge": "3.3.2", "lodash.omit": "3.1.0", "lodash.range": "3.0.1", "minilog": "2.0.8", diff --git a/server/template.html b/server/template.html index 584f4d865..f7b079ab0 100644 --- a/server/template.html +++ b/server/template.html @@ -51,6 +51,7 @@ + diff --git a/src/init.js b/src/init.js index 5418a3b4f..1d32261a1 100644 --- a/src/init.js +++ b/src/init.js @@ -1,8 +1,6 @@ var api = require('./mixins/api.jsx').api; var jar = require('./lib/jar'); -var translations = require('../locales/translations.json'); - /** * ----------------------------------------------------------------------------- * Session @@ -65,17 +63,8 @@ var translations = require('../locales/translations.json'); if (typeof obj === 'undefined') { obj = window.navigator.userLanguage || window.navigator.language; } - if (typeof translations[obj] === 'undefined') { - // Fall back on the split - obj = obj.split('-')[0]; - } - if (typeof translations[obj] === 'undefined') { - // Language appears to not be supported – return `null` - obj = null; - } return obj; } - window._locale = updateLocale() || 'en'; - window._translations = translations; + window._locale = updateLocale(); })(); diff --git a/src/l10n.json b/src/l10n.json new file mode 100644 index 000000000..35e7104ae --- /dev/null +++ b/src/l10n.json @@ -0,0 +1,78 @@ +{ + "general.accountSettings": "Account settings", + "general.about": "About", + "general.aboutScratch": "About Scratch", + "general.donate": "Donate", + "general.collaborators": "Collaborators", + "general.community": "Community", + "general.contactUs": "Contact Us", + "general.copyright": "Scratch is a project of the Lifelong Kindergarten Group at the MIT Media Lab", + "general.create": "Create", + "general.credits": "Credits", + "general.discuss": "Discuss", + "general.dmca": "DMCA", + "general.explore": "Explore", + "general.faq": "FAQ", + "general.forParents": "For Parents", + "general.forEducators": "For Educators", + "general.guidelines": "Community Guidelines", + "general.help": "Help", + "general.jobs": "Jobs", + "general.joinScratch": "Join Scratch", + "general.legal": "Legal", + "general.learnMore": "Learn More", + "general.messages": "Messages", + "general.myClasses": "My Classes", + "general.myStuff": "My Stuff", + "general.offlineEditor": "Offline Editor", + "general.profile": "Profile", + "general.scratchConference": "Scratch Conference", + "general.scratchday": "Scratch Day", + "general.scratchEd": "ScratchEd", + "general.scratchFoundation": "Scratch Foundation", + "general.scratchJr": "ScratchJr", + "general.search": "Search", + "general.signIn": "Sign in", + "general.statistics": "Statistics", + "general.support": "Support", + "general.tipsWindow": "Tips Window", + "general.tipsAnimateYourNameTitle": "Animate Your Name", + "general.tipsBearstack": "Bearstack Story", + "general.tipsDanceTitle": "Dance, Dance, Dance", + "general.tipsGetStarted": "Getting Started", + "general.tipsHideAndSeekTitle": "Hide-and-Seek Game", + "general.tipsPongGame": "Create a Pong Game", + "general.termsOfUse": "Terms of Use", + "general.username": "Username", + "general.viewAll": "View All", + "general.whatsHappening": "What's Happening?", + "general.wiki": "Scratch Wiki", + + "footer.about": "About Scratch", + "footer.discuss": "Discussion Forums", + "footer.help": "Help Page", + "footer.scratchFamily": "Scratch Family", + + "intro.aboutScratch": "ABOUT SCRATCH", + "intro.forEducators": "FOR EDUCATORS", + "intro.forParents": "FOR PARENTS", + "intro.joinScratch": "JOIN SCRATCH", + "intro.seeExamples": "SEE EXAMPLES", + "intro.tagLine": "Create stories, games, and animations
Share with others around the world", + "intro.tryItOut": "TRY IT OUT", + "login.forgotPassword": "Forgot Password?", + + "navigation.signOut": "Sign out", + + "news.scratchNews": "Scratch News", + + "parents.FaqAgeRangeA": "While Scratch is primarily designed for 8 to 16 year olds, it is also used by people of all ages, including younger children with their parents.", + "parents.FaqAgeRangeQ": "What is the age range for Scratch?", + "parents.FaqResourcesQ": "What resources are available for learning Scratch?", + "parents.introDescription": "Scratch is a programming language and an online community where children can program and share interactive media such as stories, games, and animation with people from all over the world. As children create with Scratch, they learn to think creatively, work collaboratively, and reason systematically. Scratch is designed and maintained by the Lifelong Kindergarten group at the MIT Media Lab.", + + "welcome.welcomeToScratch": "Welcome to Scratch!", + "welcome.learn": "Learn how to make a project in Scratch", + "welcome.tryOut": "Try out starter projects", + "welcome.connect": "Connect with other Scratchers" +} diff --git a/src/lib/render.jsx b/src/lib/render.jsx index c21f74118..378997e70 100644 --- a/src/lib/render.jsx +++ b/src/lib/render.jsx @@ -5,8 +5,16 @@ var IntlProvider = ReactIntl.IntlProvider; var render = function (jsx, element) { // Get locale and messages from global namespace (see "init.js") - var locale = window._locale; - var messages = window._translations[locale]; + var locale = window._locale || 'en'; + if (typeof window._messages[locale] === 'undefined') { + // Fall back on the split + locale = locale.split('-')[0]; + } + if (typeof window._messages[locale] === 'undefined') { + // Language appears to not be supported – fall back to 'en' + locale = 'en'; + } + var messages = window._messages[locale]; // Render component var component = ReactDOM.render( diff --git a/src/views/about/l10n.json b/src/views/about/l10n.json new file mode 100644 index 000000000..7c0bb5279 --- /dev/null +++ b/src/views/about/l10n.json @@ -0,0 +1,26 @@ +{ + "about.introOne": "With Scratch, you can program your own interactive stories, games, and animations — and share your creations with others in the online community.", + "about.introTwo": "Scratch helps young people learn to think creatively, reason systematically, and work collaboratively — essential skills for life in the 21st century.", + "about.introThree": "Scratch is a project of the Lifelong Kindergarten Group at the MIT Media Lab. It is provided free of charge.", + "about.introParents": "Info for parents", + "about.introEducators": "Info for educators", + "about.whoUsesScratch": "Who Uses Scratch?", + "about.whoUsesScratchDescription": "Scratch is designed especially for ages 8 to 16, but is used by people of all ages. Millions of people are creating Scratch projects in a wide variety of settings, including homes, schools, museums, libraries, and community centers.", + "about.aroundTheWorld": "Around the World", + "about.aroundTheWorldDescription": "Scratch is used in more than 150 different countries and available in more than 40 languages. To change languages, click the menu at the bottom of the page. Or, in the Project Editor, click the globe at the top of the page. To add or improve a translation, see the translation page.", + "about.quotes": "Quotes", + "about.quotesDescription": "The Scratch Team has received many emails from youth, parents, and educators expressing thanks for Scratch. Want to see what people are saying? You can read a collection of the quotes we've received.", + "about.learnMore": "Learn More About Scratch", + "about.learnMoreHelp": "Scratch Help Page", + "about.learnMoreFaq": "Frequently Asked Questions", + "about.learnMoreParents": "Information for Parents", + "about.learnMoreCredits": "Scratch Credits", + "about.literacy": "Learn to Code, Code to Learn", + "about.literacyDescription": "The ability to code computer programs is an important part of literacy in today’s society. When people learn to code in Scratch, they learn important strategies for solving problems, designing projects, and communicating ideas.", + "about.schools": "Scratch in Schools", + "about.schoolsDescription": "Students are learning with Scratch at all levels (from elementary school to college) and across disciplines (such as math, computer science, language arts, social studies). Educators share stories, exchange resources, ask questions, and find people on the ScratchEd website.", + "about.research": "Research", + "about.researchDescription": "The MIT Scratch Team and collaborators are researching how people use and learn with Scratch (for an introduction, see Scratch: Programming for All). Find out more about Scratch research and statistics about Scratch.", + "about.support": "Support and Funding", + "about.supportDescription": "The Scratch project, initiated in 2003, has received generous support from the National Science Foundation (grants 0325828, 1002713, 1027848, 1019396), Intel Foundation, Microsoft, MacArthur Foundation, LEGO Foundation, Code-to-Learn Foundation, Google, Dell, Fastly, Inversoft, and MIT Media Lab research consortia. If you'd like to support Scratch, please see our donate page, or contact us at donate@scratch.mit.edu." +} \ No newline at end of file diff --git a/src/views/hoc/l10n.json b/src/views/hoc/l10n.json new file mode 100644 index 000000000..235499807 --- /dev/null +++ b/src/views/hoc/l10n.json @@ -0,0 +1,19 @@ +{ + "hoc.activityCards": "Activity Cards", + "hoc.activityCardsHeader": "Activity Cards and Guides", + "hoc.activityCardsInfo1": "Want tips and ideas for these Hour of Code™ activities? Use the activity cards to get ideas for creating with Scratch. Facilitator guides can help you plan a group activity.", + "hoc.addToStudios": "Add Your Projects to Studios", + "hoc.addToStudiosDescription": "These studios include projects created by young people around the world. Take a look at the studios to get inspired - or submit your own projects to the studios!", + "hoc.facilitatorGuide": "Facilitator Guide", + "hoc.findOutMore": "Find out more", + "hoc.helpScratch": "Help with Scratch", + "hoc.helpScratchDescription": "You can find tutorials and helpful hints in the Tips Window. For more resources, see Scratch Help", + "hoc.moreActivities": "Want More Activities?", + "hoc.moreDescription": "Check out these other tutorials. Or remix one of our Starter Projects", + "hoc.officialNotice": "The \"Hour of Code™\" is a nationwide initiative by Computer Science Education Week and Code.org to introduce millions of students to one hour of computer science and computer programming.", + "hoc.studioAlice": "Alice in Wonderland Studio", + "hoc.studioWeBareBears": "We Bare Bears Studio", + "hoc.subTitle": "With Scratch, you can program your own stories, games, and animations — and share them online.", + "hoc.tipsDescription": "Need help getting started? Looking for ideas?  You can find tutorials and helpful hints in the Tips Window", + "hoc.title": "Get Creative with Coding" +} \ No newline at end of file diff --git a/src/views/splash/l10n.json b/src/views/splash/l10n.json new file mode 100644 index 000000000..4e46b3a67 --- /dev/null +++ b/src/views/splash/l10n.json @@ -0,0 +1,13 @@ +{ + "splash.featuredProjects": "Featured Projects", + "splash.featuredStudios": "Featured Studios", + "splash.projectsCuratedBy": "Projects Curated by", + "splash.scratchDesignStudioTitle": "Scratch Design Studio", + "splash.visitTheStudio": "Visit the studio", + "splash.recentlySharedProjects": "Recently Shared Projects", + "splash.projectsByScratchersFollowing": "Projects by Scratchers I'm Following", + "splash.projectsLovedByScratchersFollowing": "Projects Loved by Scratchers I'm Following", + "splash.projectsInStudiosFollowing": "Projects in Studios I'm Following", + "splash.communityRemixing": "What the Community is Remixing", + "splash.communityLoving": "What the Community is Loving" +} \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index 51e74922a..68995d64c 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -53,7 +53,8 @@ module.exports = { }, plugins: [ new CopyWebpackPlugin([ - {from: 'static'} + {from: 'static'}, + {from: 'intl', to: 'js/intl'} ]), new webpack.optimize.UglifyJsPlugin({ compress: { From 448ca0b103d8342620c204e1661e6493878ab1fc Mon Sep 17 00:00:00 2001 From: Matthew Taylor Date: Wed, 6 Jan 2016 14:23:47 -0500 Subject: [PATCH 08/38] Remove main bundle Render footer and nav on each view directly instead of globally in a separate bundle --- server/template.html | 1 - src/main.jsx | 9 --------- src/views/about/about.jsx | 6 ++++++ src/views/components/components.jsx | 7 ++++++- src/views/credits/credits.jsx | 6 ++++++ src/views/hoc/hoc.jsx | 6 ++++++ src/views/splash/splash.jsx | 6 ++++++ webpack.config.js | 3 +-- 8 files changed, 31 insertions(+), 13 deletions(-) delete mode 100644 src/main.jsx diff --git a/server/template.html b/server/template.html index f7b079ab0..4741617f0 100644 --- a/server/template.html +++ b/server/template.html @@ -52,7 +52,6 @@ - diff --git a/src/main.jsx b/src/main.jsx deleted file mode 100644 index 9d69e6918..000000000 --- a/src/main.jsx +++ /dev/null @@ -1,9 +0,0 @@ -var render = require('./lib/render.jsx'); - -require('./main.scss'); - -var Navigation = require('./components/navigation/navigation.jsx'); -var Footer = require('./components/footer/footer.jsx'); - -render(, document.getElementById('navigation')); -render(