commit a8acffd81c520b83027eebedc45543f14c5a8059 Author: ellen.spertus Date: Wed Oct 30 14:46:03 2013 -0700 New initial commit with .svn directories and their contents ignored. diff --git a/COPYING b/COPYING new file mode 100644 index 000000000..6a1992987 --- /dev/null +++ b/COPYING @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2011 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/appengine/README.txt b/appengine/README.txt new file mode 100644 index 000000000..75eb0383a --- /dev/null +++ b/appengine/README.txt @@ -0,0 +1,34 @@ + + Running an App Engine server + +This directory contains the files needed to setup the optional Blockly server. +Although Blockly itself is 100% client-side, the server enables cloud storage +and sharing. Store your programs in Datastore and get a unique URL that allows +you to load the program on any computer. + +To run your own App Engine instance you'll need to create this directory +structure: + +blockly/ + |- app.yaml + |- index.yaml + |- index_redirect.py + |- README.txt + |- storage.js + |- storage.py + |- closure-library-read-only/ + `- static/ + |- apps/ + |- core/ + |- demos/ + |- generators/ + |- language/ + |- media/ + |- tests/ + `- blockly_compressed.js + +Instructions for fetching Closure may be found here: + http://code.google.com/p/blockly/wiki/Closure + +Finally, upload this directory structure to your App Engine account, +wait a minute, then go to http://YOURNAME.appspot.com/ diff --git a/appengine/app.yaml b/appengine/app.yaml new file mode 100644 index 000000000..36315433e --- /dev/null +++ b/appengine/app.yaml @@ -0,0 +1,99 @@ +application: blockly-demo +version: 1 +runtime: python27 +api_version: 1 +threadsafe: no + +handlers: +# Redirect obsolete URLs. +# Blockly files moved from /blockly to /static on 5 Dec 2012. +- url: /blockly/.* + static_files: redirect.html + upload: redirect.html +# Code, Maze and Turtle moved from demos to apps on 29 Dec 2012. +- url: /static/demos/(code|maze|turtle)/.* + static_files: redirect.html + upload: redirect.html +# Vietnamese apps moved from vn to vi on 9 Jun 2012. +- url: /static/apps/.+/vn\.html + static_files: redirect.html + upload: redirect.html +# Code moved to index.html on 7 Aug 2013. +- url: /static/apps/code/code\.html + static_files: redirect.html + upload: redirect.html +# Code became language-agnostic on 20 Jul 2013. +- url: /static/apps/code/(de|en|hu|vi|zh_tw)\.html + static_files: redirect.html + upload: redirect.html +# Graph moved to index.html on 7 Aug 2013. +- url: /static/apps/graph/graph\.html + static_files: redirect.html + upload: redirect.html +# Graph became language-agnostic on 20 Jul 2013. +- url: /static/apps/graph/(de|en|hu|vi)\.html + static_files: redirect.html + upload: redirect.html +# Maze moved to index.html on 7 Aug 2013. +- url: /static/apps/maze/maze\.html + static_files: redirect.html + upload: redirect.html +# Maze became language-agnostic on 20 Jul 2013. +- url: /static/apps/maze/(ca|cs|da|el|en|es|eu|fr|hu|it|lv|nl|pl|pt|ru|sr|sw|th|tr|vi)\.html + static_files: redirect.html + upload: redirect.html +# Plane moved to index.html on 7 Aug 2013. +- url: /static/apps/plane/plane\.html + static_files: redirect.html + upload: redirect.html +# Plane became language-agnostic on 20 Jul 2013. +- url: /static/apps/plane/(1_|2_)?(en|hu|vi|vn)\.html + static_files: redirect.html + upload: redirect.html +# Puzzle moved to index.html on 30 Jul 2013. +- url: /static/apps/puzzle/puzzle\.html + static_files: redirect.html + upload: redirect.html +# Puzzle became language-agnostic on 20 Jul 2013. +- url: /static/apps/puzzle/(af|cs|de|el|en|gl|hak|he|hu|ia|it|ja|ko|ksh|la|lb|lv|mk|ms|nl|pl|pt-br|ru|sv|sw|tzm|vi|zh-hans)\.html + static_files: redirect.html + upload: redirect.html +# Turtle moved to index.html on 7 Aug 2013. +- url: /static/apps/turtle/turtle\.html + static_files: redirect.html + upload: redirect.html +# Turtle became language-agnostic on 20 Jul 2013. +- url: /static/apps/turtle/(de|en|hu|vi)\.html + static_files: redirect.html + upload: redirect.html + + +# Storage API. +- url: /storage + script: storage.py +- url: /storage\.js + static_files: storage.js + upload: storage\.js + +# Blockly files. +- url: /static + static_dir: static + +# Closure library for uncompiled Blockly. +- url: /closure-library-read-only + static_dir: closure-library-read-only + +# Redirect for root directory. +- url: / + script: index_redirect.py + +# Favicon. +- url: /favicon\.ico + static_files: favicon.ico + upload: favicon\.ico + +# robot.txt +- url: /robots\.txt + static_files: robots.txt + upload: robots\.txt + diff --git a/appengine/favicon.ico b/appengine/favicon.ico new file mode 100644 index 000000000..683ec6d5d Binary files /dev/null and b/appengine/favicon.ico differ diff --git a/appengine/index.yaml b/appengine/index.yaml new file mode 100644 index 000000000..a3b9e05e3 --- /dev/null +++ b/appengine/index.yaml @@ -0,0 +1,11 @@ +indexes: + +# AUTOGENERATED + +# This index.yaml is automatically updated whenever the dev_appserver +# detects that a new type of query is run. If you want to manage the +# index.yaml file manually, remove the above marker line (the line +# saying "# AUTOGENERATED"). If you want to manage some indexes +# manually, move them above the marker line. The index.yaml file is +# automatically uploaded to the admin console when you next deploy +# your application using appcfg.py. diff --git a/appengine/index_redirect.py b/appengine/index_redirect.py new file mode 100644 index 000000000..2bc1d0368 --- /dev/null +++ b/appengine/index_redirect.py @@ -0,0 +1,2 @@ +print("Status: 302") +print("Location: /static/apps/index.html") diff --git a/appengine/redirect.html b/appengine/redirect.html new file mode 100644 index 000000000..3ad9988fb --- /dev/null +++ b/appengine/redirect.html @@ -0,0 +1,98 @@ + + + + + + diff --git a/appengine/report.py b/appengine/report.py new file mode 100644 index 000000000..106490424 --- /dev/null +++ b/appengine/report.py @@ -0,0 +1,53 @@ +"""Blockly Demo: Report + +Copyright 2012 Google Inc. +http://blockly.googlecode.com/ + +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. +""" + +"""Store reports about code written by users. +""" + +__author__ = "ellen.spertus@gmail.com (Ellen Spertus)" + +import cgi +import logging + +from google.appengine.ext import db + +print "Content-type: text/plain\n" + +class Report(db.Model): + identifier = db.FloatProperty() + application = db.StringProperty() + date = db.DateTimeProperty(auto_now_add=True) + level = db.IntegerProperty() + result = db.IntegerProperty() + # StringProperty is limited to 500 characters, so use TextProperty. + program = db.TextProperty() + +# Catch errors extracting form fields or converting to numeric types. +# Let any other errors propagate up. +try: + forms = cgi.FieldStorage() + identifier = float(forms["id"].value) + application = forms["app"].value + level = int(forms["level"].value) + result = int(forms["result"].value) + program = forms["program"].value + row = Report(identifier = identifier, application = application, + level = level, result = result, program = program) + row.put() +except ValueError, KeyError: + logging.error("Unable to extract all form fields.") diff --git a/appengine/robots.txt b/appengine/robots.txt new file mode 100644 index 000000000..428c409a7 --- /dev/null +++ b/appengine/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: /storage diff --git a/appengine/storage.js b/appengine/storage.js new file mode 100644 index 000000000..1fdf76744 --- /dev/null +++ b/appengine/storage.js @@ -0,0 +1,180 @@ +/** + * Blockly Demo: Storage + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Loading and saving blocks with localStorage and cloud storage. + * @author q.neutron@gmail.com (Quynh Neutron) + */ +'use strict'; + +// Create a namespace. +var BlocklyStorage = {}; + +/** + * Backup code blocks to localStorage. + * @private + */ +BlocklyStorage.backupBlocks_ = function() { + if ('localStorage' in window) { + var xml = Blockly.Xml.workspaceToDom(Blockly.getMainWorkspace()); + // Gets the current URL, not including the hash. + var url = window.location.href.split('#')[0]; + window.localStorage.setItem(url, Blockly.Xml.domToText(xml)); + } +}; + +/** + * Bind the localStorage backup function to the unload event. + */ +BlocklyStorage.backupOnUnload = function() { + window.addEventListener('unload', BlocklyStorage.backupBlocks_, false); +}; + +/** + * Restore code blocks from localStorage. + */ +BlocklyStorage.restoreBlocks = function() { + var url = window.location.href.split('#')[0]; + if ('localStorage' in window && window.localStorage[url]) { + var xml = Blockly.Xml.textToDom(window.localStorage[url]); + Blockly.Xml.domToWorkspace(Blockly.getMainWorkspace(), xml); + } +}; + +/** + * Save blocks to database and return a link containing key to XML. + */ +BlocklyStorage.link = function() { + var xml = Blockly.Xml.workspaceToDom(Blockly.getMainWorkspace()); + var data = Blockly.Xml.domToText(xml); + BlocklyStorage.makeRequest_('/storage', 'xml', data); +}; + +/** + * Retrieve XML text from database using given key. + * @param {string} key Key to XML, obtained from href. + */ +BlocklyStorage.retrieveXml = function(key) { + var xml = Blockly.Xml.workspaceToDom(Blockly.getMainWorkspace()); + BlocklyStorage.makeRequest_('/storage', 'key', key); +}; + +/** + * Global reference to current AJAX request. + * @type XMLHttpRequest + * @private + */ +BlocklyStorage.httpRequest_ = null; + +/** + * Fire a new AJAX request. + * @param {string} url URL to fetch. + * @param {string} name Name of parameter. + * @param {string} content Content of parameter. + * @private + */ +BlocklyStorage.makeRequest_ = function(url, name, content) { + if (BlocklyStorage.httpRequest_) { + // AJAX call is in-flight. + BlocklyStorage.httpRequest_.abort(); + } + BlocklyStorage.httpRequest_ = new XMLHttpRequest(); + BlocklyStorage.httpRequest_.name = name; + BlocklyStorage.httpRequest_.onreadystatechange = + BlocklyStorage.handleRequest_; + BlocklyStorage.httpRequest_.open('POST', url); + BlocklyStorage.httpRequest_.setRequestHeader('Content-Type', + 'application/x-www-form-urlencoded'); + BlocklyStorage.httpRequest_.send(name + '=' + encodeURIComponent(content)); +}; + +/** + * Callback function for AJAX call. + * @private + */ +BlocklyStorage.handleRequest_ = function() { + if (BlocklyStorage.httpRequest_.readyState == 4) { + if (BlocklyStorage.httpRequest_.status != 200) { + BlocklyStorage.alert(BlocklyStorage.HTTPREQUEST_ERROR + '\n' + + 'httpRequest_.status: ' + BlocklyStorage.httpRequest_.status); + } else { + var data = BlocklyStorage.httpRequest_.responseText.trim(); + if (BlocklyStorage.httpRequest_.name == 'xml') { + window.location.hash = data; + BlocklyStorage.alert(BlocklyStorage.LINK_ALERT.replace('%1', + window.location.href)); + } else if (BlocklyStorage.httpRequest_.name == 'key') { + if (!data.length) { + BlocklyStorage.alert(BlocklyStorage.HASH_ERROR.replace('%1', + window.location.hash)); + } else { + BlocklyStorage.loadXml_(data); + } + } + BlocklyStorage.monitorChanges_(); + } + BlocklyStorage.httpRequest_ = null; + } +}; + +/** + * Start monitoring the workspace. If a change is made that changes the XML, + * clear the key from the URL. Stop monitoring the workspace once such a + * change is detected. + * @private + */ +BlocklyStorage.monitorChanges_ = function() { + var startXmlDom = Blockly.Xml.workspaceToDom(Blockly.getMainWorkspace()); + var startXmlText = Blockly.Xml.domToText(startXmlDom); + function change() { + var xmlDom = Blockly.Xml.workspaceToDom(Blockly.getMainWorkspace()); + var xmlText = Blockly.Xml.domToText(xmlDom); + if (startXmlText != xmlText) { + window.location.hash = ''; + Blockly.removeChangeListener(bindData); + } + } + var bindData = Blockly.addChangeListener(change); +}; + +/** + * Load blocks from XML. + * @param {string} xml Text representation of XML. + * @private + */ +BlocklyStorage.loadXml_ = function(xml) { + try { + xml = Blockly.Xml.textToDom(xml); + } catch (e) { + BlocklyStorage.alert(BlocklyStorage.XML_ERROR + '\nXML: ' + xml); + return; + } + // Clear the workspace to avoid merge. + Blockly.getMainWorkspace().clear(); + Blockly.Xml.domToWorkspace(Blockly.getMainWorkspace(), xml); +}; + +/** + * Present a text message to the user. + * Designed to be overridden if an app has custom dialogs, or a butter bar. + * @param {string} message Text to alert. + */ +BlocklyStorage.alert = function(message) { + window.alert(message); +}; diff --git a/appengine/storage.py b/appengine/storage.py new file mode 100644 index 000000000..9e81e43f4 --- /dev/null +++ b/appengine/storage.py @@ -0,0 +1,85 @@ +"""Blockly Demo: Storage + +Copyright 2012 Google Inc. +http://blockly.googlecode.com/ + +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. +""" + +"""Store and retrieve XML with App Engine. +""" + +__author__ = "q.neutron@gmail.com (Quynh Neutron)" + +import cgi +from random import randint +from google.appengine.ext import db +from google.appengine.api import memcache +import logging + +print "Content-Type: text/plain\n" + +def keyGen(): + # Generate a random string of length KEY_LEN. + KEY_LEN = 6 + CHARS = "abcdefghijkmnopqrstuvwxyz23456789" # Exclude l, 0, 1. + max_index = len(CHARS) - 1 + return "".join([CHARS[randint(0, max_index)] for x in range(KEY_LEN)]) + +class Xml(db.Model): + # A row in the database. + xml_hash = db.IntegerProperty() + xml_content = db.TextProperty() + +forms = cgi.FieldStorage() +if "xml" in forms: + # Store XML and return a generated key. + xml_content = forms["xml"].value + xml_hash = hash(xml_content) + lookup_query = db.Query(Xml) + lookup_query.filter("xml_hash =", xml_hash) + lookup_result = lookup_query.get() + if lookup_result: + xml_key = lookup_result.key().name() + else: + trials = 0 + result = True + while result: + trials += 1 + if trials == 100: + raise Exception("Sorry, the generator failed to get a key for you.") + xml_key = keyGen() + result = db.get(db.Key.from_path("Xml", xml_key)) + xml = db.Text(xml_content, encoding="utf_8") + row = Xml(key_name = xml_key, xml_hash = xml_hash, xml_content = xml) + row.put() + print xml_key + +if "key" in forms: + # Retrieve stored XML based on the provided key. + key_provided = forms["key"].value + # Normalize the string. + key_provided = key_provided.lower().strip() + # Check memcache for a quick match. + xml = memcache.get("XML_" + key_provided) + if xml is None: + # Check datastore for a definitive match. + result = db.get(db.Key.from_path("Xml", key_provided)) + if not result: + xml = "" + else: + xml = result.xml_content + # Save to memcache for next hit. + if not memcache.add("XML_" + key_provided, xml, 3600): + logging.error("Memcache set failed.") + print xml.encode("utf-8") diff --git a/apps/_soy/COPYING b/apps/_soy/COPYING new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/apps/_soy/COPYING @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/apps/_soy/README b/apps/_soy/README new file mode 100644 index 000000000..e3447f2d8 --- /dev/null +++ b/apps/_soy/README @@ -0,0 +1,45 @@ +// Copyright 2009 Google Inc. +// +// 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. + + +Contents: + ++ SoyToJsSrcCompiler.jar + Executable jar that compiles template files into JavaScript files. + ++ SoyMsgExtractor.jar + Executable jar that extracts messages from template files into XLF files. + ++ soyutils.js + Helper utilities required by all JavaScript code that SoyToJsSrcCompiler + generates. Equivalent functionality to soyutils_usegoog.js, but this + version does not need Closure Library. + + +Instructions: + ++ A simple Hello World for JavaScript: + http://code.google.com/closure/templates/docs/helloworld_js.html + ++ Complete documentation: + http://code.google.com/closure/templates/ + ++ Closure Templates project on Google Code: + http://code.google.com/p/closure-templates/ + + +Notes: + ++ Closure Templates requires Java 6 or higher: + http://www.java.com/ diff --git a/apps/_soy/SoyMsgExtractor.jar b/apps/_soy/SoyMsgExtractor.jar new file mode 100644 index 000000000..d7d261984 Binary files /dev/null and b/apps/_soy/SoyMsgExtractor.jar differ diff --git a/apps/_soy/SoyToJsSrcCompiler.jar b/apps/_soy/SoyToJsSrcCompiler.jar new file mode 100644 index 000000000..540a0702a Binary files /dev/null and b/apps/_soy/SoyToJsSrcCompiler.jar differ diff --git a/apps/_soy/soyutils.js b/apps/_soy/soyutils.js new file mode 100644 index 000000000..bde8e4133 --- /dev/null +++ b/apps/_soy/soyutils.js @@ -0,0 +1,2767 @@ +/* + * Copyright 2008 Google Inc. + * + * 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. + */ + +/** + * @fileoverview + * Utility functions and classes for Soy. + * + *

+ * The top portion of this file contains utilities for Soy users:

+ * + *

+ * The bottom portion of this file contains utilities that should only be called + * by Soy-generated JS code. Please do not use these functions directly from + * your hand-writen code. Their names all start with '$$'. + * + * @author Garrett Boyer + * @author Mike Samuel + * @author Kai Huang + * @author Aharon Lanin + */ + + +// COPIED FROM nogoog_shim.js + +// Create closure namespaces. +var goog = goog || {}; + + +goog.DEBUG = false; + + +goog.inherits = function(childCtor, parentCtor) { + /** @constructor */ + function tempCtor() {} + tempCtor.prototype = parentCtor.prototype; + childCtor.superClass_ = parentCtor.prototype; + childCtor.prototype = new tempCtor(); + childCtor.prototype.constructor = childCtor; +}; + + +// Just enough browser detection for this file. +if (!goog.userAgent) { + goog.userAgent = (function() { + var userAgent = ""; + if ("undefined" !== typeof navigator && navigator + && "string" == typeof navigator.userAgent) { + userAgent = navigator.userAgent; + } + var isOpera = userAgent.indexOf('Opera') == 0; + return { + jscript: { + /** + * @type {boolean} + */ + HAS_JSCRIPT: 'ScriptEngine' in this + }, + /** + * @type {boolean} + */ + OPERA: isOpera, + /** + * @type {boolean} + */ + IE: !isOpera && userAgent.indexOf('MSIE') != -1, + /** + * @type {boolean} + */ + WEBKIT: !isOpera && userAgent.indexOf('WebKit') != -1 + }; + })(); +} + +if (!goog.asserts) { + goog.asserts = { + /** + * @param {*} condition Condition to check. + */ + assert: function (condition) { + if (!condition) { + throw Error('Assertion error'); + } + }, + /** + * @param {...*} var_args + */ + fail: function (var_args) {} + }; +} + + +// Stub out the document wrapper used by renderAs*. +if (!goog.dom) { + goog.dom = {}; + /** + * @param {Document=} d + * @constructor + */ + goog.dom.DomHelper = function(d) { + this.document_ = d || document; + }; + /** + * @return {!Document} + */ + goog.dom.DomHelper.prototype.getDocument = function() { + return this.document_; + }; + /** + * Creates a new element. + * @param {string} name Tag name. + * @return {!Element} + */ + goog.dom.DomHelper.prototype.createElement = function(name) { + return this.document_.createElement(name); + }; + /** + * Creates a new document fragment. + * @return {!DocumentFragment} + */ + goog.dom.DomHelper.prototype.createDocumentFragment = function() { + return this.document_.createDocumentFragment(); + }; +} + + +if (!goog.format) { + goog.format = { + insertWordBreaks: function(str, maxCharsBetweenWordBreaks) { + str = String(str); + + var resultArr = []; + var resultArrLen = 0; + + // These variables keep track of important state inside str. + var isInTag = false; // whether we're inside an HTML tag + var isMaybeInEntity = false; // whether we might be inside an HTML entity + var numCharsWithoutBreak = 0; // number of chars since last word break + var flushIndex = 0; // index of first char not yet flushed to resultArr + + for (var i = 0, n = str.length; i < n; ++i) { + var charCode = str.charCodeAt(i); + + // If hit maxCharsBetweenWordBreaks, and not space next, then add . + if (numCharsWithoutBreak >= maxCharsBetweenWordBreaks && + // space + charCode != 32) { + resultArr[resultArrLen++] = str.substring(flushIndex, i); + flushIndex = i; + resultArr[resultArrLen++] = goog.format.WORD_BREAK; + numCharsWithoutBreak = 0; + } + + if (isInTag) { + // If inside an HTML tag and we see '>', it's the end of the tag. + if (charCode == 62) { + isInTag = false; + } + + } else if (isMaybeInEntity) { + switch (charCode) { + // Inside an entity, a ';' is the end of the entity. + // The entity that just ended counts as one char, so increment + // numCharsWithoutBreak. + case 59: // ';' + isMaybeInEntity = false; + ++numCharsWithoutBreak; + break; + // If maybe inside an entity and we see '<', we weren't actually in + // an entity. But now we're inside and HTML tag. + case 60: // '<' + isMaybeInEntity = false; + isInTag = true; + break; + // If maybe inside an entity and we see ' ', we weren't actually in + // an entity. Just correct the state and reset the + // numCharsWithoutBreak since we just saw a space. + case 32: // ' ' + isMaybeInEntity = false; + numCharsWithoutBreak = 0; + break; + } + + } else { // !isInTag && !isInEntity + switch (charCode) { + // When not within a tag or an entity and we see '<', we're now + // inside an HTML tag. + case 60: // '<' + isInTag = true; + break; + // When not within a tag or an entity and we see '&', we might be + // inside an entity. + case 38: // '&' + isMaybeInEntity = true; + break; + // When we see a space, reset the numCharsWithoutBreak count. + case 32: // ' ' + numCharsWithoutBreak = 0; + break; + // When we see a non-space, increment the numCharsWithoutBreak. + default: + ++numCharsWithoutBreak; + break; + } + } + } + + // Flush the remaining chars at the end of the string. + resultArr[resultArrLen++] = str.substring(flushIndex); + + return resultArr.join(''); + }, + /** + * String inserted as a word break by insertWordBreaks(). Safari requires + * , Opera needs the 'shy' entity, though this will give a + * visible hyphen at breaks. Other browsers just use . + * @type {string} + * @private + */ + WORD_BREAK: goog.userAgent.WEBKIT + ? '' : goog.userAgent.OPERA ? '­' : '' + }; +} + + +if (!goog.i18n) { + goog.i18n = { + bidi: { + /** + * Check the directionality of a piece of text, return true if the piece + * of text should be laid out in RTL direction. + * @param {string} text The piece of text that need to be detected. + * @param {boolean=} opt_isHtml Whether {@code text} is HTML/HTML-escaped. + * Default: false. + * @return {boolean} + * @private + */ + detectRtlDirectionality: function(text, opt_isHtml) { + text = soyshim.$$bidiStripHtmlIfNecessary_(text, opt_isHtml); + return soyshim.$$bidiRtlWordRatio_(text) + > soyshim.$$bidiRtlDetectionThreshold_; + } + } + }; +} + +/** + * Directionality enum. + * @enum {number} + */ +goog.i18n.bidi.Dir = { + RTL: -1, + UNKNOWN: 0, + LTR: 1 +}; + + +/** + * Convert a directionality given in various formats to a goog.i18n.bidi.Dir + * constant. Useful for interaction with different standards of directionality + * representation. + * + * @param {goog.i18n.bidi.Dir|number|boolean} givenDir Directionality given in + * one of the following formats: + * 1. A goog.i18n.bidi.Dir constant. + * 2. A number (positive = LRT, negative = RTL, 0 = unknown). + * 3. A boolean (true = RTL, false = LTR). + * @return {goog.i18n.bidi.Dir} A goog.i18n.bidi.Dir constant matching the given + * directionality. + */ +goog.i18n.bidi.toDir = function(givenDir) { + if (typeof givenDir == 'number') { + return givenDir > 0 ? goog.i18n.bidi.Dir.LTR : + givenDir < 0 ? goog.i18n.bidi.Dir.RTL : goog.i18n.bidi.Dir.UNKNOWN; + } else { + return givenDir ? goog.i18n.bidi.Dir.RTL : goog.i18n.bidi.Dir.LTR; + } +}; + + +/** + * Utility class for formatting text for display in a potentially + * opposite-directionality context without garbling. Provides the following + * functionality: + * + * @param {goog.i18n.bidi.Dir|number|boolean} dir The context + * directionality as a number + * (positive = LRT, negative = RTL, 0 = unknown). + * @constructor + */ +goog.i18n.BidiFormatter = function(dir) { + this.dir_ = goog.i18n.bidi.toDir(dir); +}; + + +/** + * Returns 'dir="ltr"' or 'dir="rtl"', depending on {@code text}'s estimated + * directionality, if it is not the same as the context directionality. + * Otherwise, returns the empty string. + * + * @param {string} text Text whose directionality is to be estimated. + * @param {boolean=} opt_isHtml Whether {@code text} is HTML / HTML-escaped. + * Default: false. + * @return {string} 'dir="rtl"' for RTL text in non-RTL context; 'dir="ltr"' for + * LTR text in non-LTR context; else, the empty string. + */ +goog.i18n.BidiFormatter.prototype.dirAttr = function (text, opt_isHtml) { + var dir = soy.$$bidiTextDir(text, opt_isHtml); + return dir && dir != this.dir_ ? dir < 0 ? 'dir="rtl"' : 'dir="ltr"' : ''; +}; + +/** + * Returns the trailing horizontal edge, i.e. "right" or "left", depending on + * the global bidi directionality. + * @return {string} "left" for RTL context and "right" otherwise. + */ +goog.i18n.BidiFormatter.prototype.endEdge = function () { + return this.dir_ < 0 ? 'left' : 'right'; +}; + +/** + * Returns the Unicode BiDi mark matching the context directionality (LRM for + * LTR context directionality, RLM for RTL context directionality), or the + * empty string for neutral / unknown context directionality. + * + * @return {string} LRM for LTR context directionality and RLM for RTL context + * directionality. + */ +goog.i18n.BidiFormatter.prototype.mark = function () { + return ( + (this.dir_ > 0) ? '\u200E' /*LRM*/ : + (this.dir_ < 0) ? '\u200F' /*RLM*/ : + ''); +}; + +/** + * Returns a Unicode BiDi mark matching the context directionality (LRM or RLM) + * if the directionality or the exit directionality of {@code text} are opposite + * to the context directionality. Otherwise returns the empty string. + * + * @param {string} text The input text. + * @param {boolean=} opt_isHtml Whether {@code text} is HTML / HTML-escaped. + * Default: false. + * @return {string} A Unicode bidi mark matching the global directionality or + * the empty string. + */ +goog.i18n.BidiFormatter.prototype.markAfter = function (text, opt_isHtml) { + var dir = soy.$$bidiTextDir(text, opt_isHtml); + return soyshim.$$bidiMarkAfterKnownDir_(this.dir_, dir, text, opt_isHtml); +}; + +/** + * Formats a string of unknown directionality for use in HTML output of the + * context directionality, so an opposite-directionality string is neither + * garbled nor garbles what follows it. + * + * @param {string} str The input text. + * @param {boolean=} placeholder This argument exists for consistency with the + * Closure Library. Specifying it has no effect. + * @return {string} Input text after applying the above processing. + */ +goog.i18n.BidiFormatter.prototype.spanWrap = function(str, placeholder) { + str = String(str); + var textDir = soy.$$bidiTextDir(str, true); + var reset = soyshim.$$bidiMarkAfterKnownDir_(this.dir_, textDir, str, true); + if (textDir > 0 && this.dir_ <= 0) { + str = '' + str + ''; + } else if (textDir < 0 && this.dir_ >= 0) { + str = '' + str + ''; + } + return str + reset; +}; + +/** + * Returns the leading horizontal edge, i.e. "left" or "right", depending on + * the global bidi directionality. + * @return {string} "right" for RTL context and "left" otherwise. + */ +goog.i18n.BidiFormatter.prototype.startEdge = function () { + return this.dir_ < 0 ? 'right' : 'left'; +}; + +/** + * Formats a string of unknown directionality for use in plain-text output of + * the context directionality, so an opposite-directionality string is neither + * garbled nor garbles what follows it. + * As opposed to {@link #spanWrap}, this makes use of unicode BiDi formatting + * characters. In HTML, its *only* valid use is inside of elements that do not + * allow mark-up, e.g. an 'option' tag. + * + * @param {string} str The input text. + * @param {boolean=} placeholder This argument exists for consistency with the + * Closure Library. Specifying it has no effect. + * @return {string} Input text after applying the above processing. + */ +goog.i18n.BidiFormatter.prototype.unicodeWrap = function(str, placeholder) { + str = String(str); + var textDir = soy.$$bidiTextDir(str, true); + var reset = soyshim.$$bidiMarkAfterKnownDir_(this.dir_, textDir, str, true); + if (textDir > 0 && this.dir_ <= 0) { + str = '\u202A' + str + '\u202C'; + } else if (textDir < 0 && this.dir_ >= 0) { + str = '\u202B' + str + '\u202C'; + } + return str + reset; +}; + + +if (!goog.string) { + goog.string = { + /** + * Converts \r\n, \r, and \n to
s + * @param {*} str The string in which to convert newlines. + * @param {boolean=} opt_xml Whether to use XML compatible tags. + * @return {string} A copy of {@code str} with converted newlines. + */ + newLineToBr: function(str, opt_xml) { + + str = String(str); + + // This quick test helps in the case when there are no chars to replace, + // in the worst case this makes barely a difference to the time taken. + if (!goog.string.NEWLINE_TO_BR_RE_.test(str)) { + return str; + } + + return str.replace(/(\r\n|\r|\n)/g, opt_xml ? '
' : '
'); + }, + urlEncode: encodeURIComponent, + /** + * Regular expression used within newlineToBr(). + * @type {RegExp} + * @private + */ + NEWLINE_TO_BR_RE_: /[\r\n]/ + }; +} + +/** + * Utility class to facilitate much faster string concatenation in IE, + * using Array.join() rather than the '+' operator. For other browsers + * we simply use the '+' operator. + * + * @param {Object|number|string|boolean=} opt_a1 Optional first initial item + * to append. + * @param {...Object|number|string|boolean} var_args Other initial items to + * append, e.g., new goog.string.StringBuffer('foo', 'bar'). + * @constructor + */ +goog.string.StringBuffer = function(opt_a1, var_args) { + /** + * Internal buffer for the string to be concatenated. + * @type {string|Array} + * @private + */ + this.buffer_ = goog.userAgent.jscript.HAS_JSCRIPT ? [] : ''; + + if (opt_a1 != null) { + this.append.apply(this, arguments); + } +}; + + +/** + * Length of internal buffer (faster than calling buffer_.length). + * Only used for IE. + * @type {number} + * @private + */ +goog.string.StringBuffer.prototype.bufferLength_ = 0; + +/** + * Appends one or more items to the string. + * + * Calling this with null, undefined, or empty arguments is an error. + * + * @param {Object|number|string|boolean} a1 Required first string. + * @param {Object|number|string|boolean=} opt_a2 Optional second string. + * @param {...Object|number|string|boolean} var_args Other items to append, + * e.g., sb.append('foo', 'bar', 'baz'). + * @return {goog.string.StringBuffer} This same StringBuilder object. + */ +goog.string.StringBuffer.prototype.append = function(a1, opt_a2, var_args) { + + if (goog.userAgent.jscript.HAS_JSCRIPT) { + if (opt_a2 == null) { // no second argument (note: undefined == null) + // Array assignment is 2x faster than Array push. Also, use a1 + // directly to avoid arguments instantiation, another 2x improvement. + this.buffer_[this.bufferLength_++] = a1; + } else { + var arr = /**@type {Array.}*/(this.buffer_); + arr.push.apply(arr, arguments); + this.bufferLength_ = this.buffer_.length; + } + + } else { + + // Use a1 directly to avoid arguments instantiation for single-arg case. + this.buffer_ += a1; + if (opt_a2 != null) { // no second argument (note: undefined == null) + for (var i = 1; i < arguments.length; i++) { + this.buffer_ += arguments[i]; + } + } + } + + return this; +}; + + +/** + * Clears the string. + */ +goog.string.StringBuffer.prototype.clear = function() { + + if (goog.userAgent.jscript.HAS_JSCRIPT) { + this.buffer_.length = 0; // reuse array to avoid creating new object + this.bufferLength_ = 0; + + } else { + this.buffer_ = ''; + } +}; + + +/** + * Returns the concatenated string. + * + * @return {string} The concatenated string. + */ +goog.string.StringBuffer.prototype.toString = function() { + + if (goog.userAgent.jscript.HAS_JSCRIPT) { + var str = this.buffer_.join(''); + // Given a string with the entire contents, simplify the StringBuilder by + // setting its contents to only be this string, rather than many fragments. + this.clear(); + if (str) { + this.append(str); + } + return str; + + } else { + return /** @type {string} */ (this.buffer_); + } +}; + + +if (!goog.soy) goog.soy = { + /** + * Helper function to render a Soy template and then set the + * output string as the innerHTML of an element. It is recommended + * to use this helper function instead of directly setting + * innerHTML in your hand-written code, so that it will be easier + * to audit the code for cross-site scripting vulnerabilities. + * + * @param {Function} template The Soy template defining element's content. + * @param {Object=} opt_templateData The data for the template. + * @param {Object=} opt_injectedData The injected data for the template. + * @param {(goog.dom.DomHelper|Document)=} opt_dom The context in which DOM + * nodes will be created. + */ + renderAsElement: function( + template, opt_templateData, opt_injectedData, opt_dom) { + return /** @type {!Element} */ (soyshim.$$renderWithWrapper_( + template, opt_templateData, opt_dom, true /* asElement */, + opt_injectedData)); + }, + /** + * Helper function to render a Soy template into a single node or + * a document fragment. If the rendered HTML string represents a + * single node, then that node is returned (note that this is + * *not* a fragment, despite them name of the method). Otherwise a + * document fragment is returned containing the rendered nodes. + * + * @param {Function} template The Soy template defining element's content. + * @param {Object=} opt_templateData The data for the template. + * @param {Object=} opt_injectedData The injected data for the template. + * @param {(goog.dom.DomHelper|Document)=} opt_dom The context in which DOM + * nodes will be created. + * @return {!Node} The resulting node or document fragment. + */ + renderAsFragment: function( + template, opt_templateData, opt_injectedData, opt_dom) { + return soyshim.$$renderWithWrapper_( + template, opt_templateData, opt_dom, false /* asElement */, + opt_injectedData); + }, + /** + * Helper function to render a Soy template and then set the output string as + * the innerHTML of an element. It is recommended to use this helper function + * instead of directly setting innerHTML in your hand-written code, so that it + * will be easier to audit the code for cross-site scripting vulnerabilities. + * + * NOTE: New code should consider using goog.soy.renderElement instead. + * + * @param {Element} element The element whose content we are rendering. + * @param {Function} template The Soy template defining the element's content. + * @param {Object=} opt_templateData The data for the template. + * @param {Object=} opt_injectedData The injected data for the template. + */ + renderElement: function( + element, template, opt_templateData, opt_injectedData) { + element.innerHTML = template(opt_templateData, null, opt_injectedData); + }, + data: {} +}; + + +/** + * A type of textual content. + * + * This is an enum of type Object so that these values are unforgeable. + * + * @enum {!Object} + */ +goog.soy.data.SanitizedContentKind = { + + /** + * A snippet of HTML that does not start or end inside a tag, comment, entity, + * or DOCTYPE; and that does not contain any executable code + * (JS, {@code }s, etc.) from a different trust domain. + */ + HTML: {}, + + /** + * Executable Javascript code or expression, safe for insertion in a + * script-tag or event handler context, known to be free of any + * attacker-controlled scripts. This can either be side-effect-free + * Javascript (such as JSON) or Javascript that entirely under Google's + * control. + */ + JS: goog.DEBUG ? {sanitizedContentJsStrChars: true} : {}, + + /** + * A sequence of code units that can appear between quotes (either kind) in a + * JS program without causing a parse error, and without causing any side + * effects. + *

+ * The content should not contain unescaped quotes, newlines, or anything else + * that would cause parsing to fail or to cause a JS parser to finish the + * string its parsing inside the content. + *

+ * The content must also not end inside an escape sequence ; no partial octal + * escape sequences or odd number of '{@code \}'s at the end. + */ + JS_STR_CHARS: {}, + + /** A properly encoded portion of a URI. */ + URI: {}, + + /** + * Repeated attribute names and values. For example, + * {@code dir="ltr" foo="bar" onclick="trustedFunction()" checked}. + */ + ATTRIBUTES: goog.DEBUG ? {sanitizedContentHtmlAttribute: true} : {}, + + // TODO: Consider separating rules, declarations, and values into + // separate types, but for simplicity, we'll treat explicitly blessed + // SanitizedContent as allowed in all of these contexts. + /** + * A CSS3 declaration, property, value or group of semicolon separated + * declarations. + */ + CSS: {}, + + /** + * Unsanitized plain-text content. + * + * This is effectively the "null" entry of this enum, and is sometimes used + * to explicitly mark content that should never be used unescaped. Since any + * string is safe to use as text, being of ContentKind.TEXT makes no + * guarantees about its safety in any other context such as HTML. + */ + TEXT: {} +}; + + + +/** + * A string-like object that carries a content-type. + * + * IMPORTANT! Do not create these directly, nor instantiate the subclasses. + * Instead, use a trusted, centrally reviewed library as endorsed by your team + * to generate these objects. Otherwise, you risk accidentally creating + * SanitizedContent that is attacker-controlled and gets evaluated unescaped in + * templates. + * + * @constructor + */ +goog.soy.data.SanitizedContent = function() { + throw Error('Do not instantiate directly'); +}; + + +/** + * The context in which this content is safe from XSS attacks. + * @type {goog.soy.data.SanitizedContentKind} + */ +goog.soy.data.SanitizedContent.prototype.contentKind; + + +/** + * The already-safe content. + * @type {string} + */ +goog.soy.data.SanitizedContent.prototype.content; + + +/** @override */ +goog.soy.data.SanitizedContent.prototype.toString = function() { + return this.content; +}; + + +var soy = { esc: {} }; +var soydata = {}; +soydata.VERY_UNSAFE = {}; +var soyshim = { $$DEFAULT_TEMPLATE_DATA_: {} }; +/** + * Helper function to render a Soy template into a single node or a document + * fragment. If the rendered HTML string represents a single node, then that + * node is returned. Otherwise a document fragment is created and returned + * (wrapped in a DIV element if #opt_singleNode is true). + * + * @param {Function} template The Soy template defining the element's content. + * @param {Object=} opt_templateData The data for the template. + * @param {(goog.dom.DomHelper|Document)=} opt_dom The context in which DOM + * nodes will be created. + * @param {boolean=} opt_asElement Whether to wrap the fragment in an + * element if the template does not render a single element. If true, + * result is always an Element. + * @param {Object=} opt_injectedData The injected data for the template. + * @return {!Node} The resulting node or document fragment. + * @private + */ +soyshim.$$renderWithWrapper_ = function( + template, opt_templateData, opt_dom, opt_asElement, opt_injectedData) { + + var dom = opt_dom || document; + var wrapper = dom.createElement('div'); + wrapper.innerHTML = template( + opt_templateData || soyshim.$$DEFAULT_TEMPLATE_DATA_, undefined, + opt_injectedData); + + // If the template renders as a single element, return it. + if (wrapper.childNodes.length == 1) { + var firstChild = wrapper.firstChild; + if (!opt_asElement || firstChild.nodeType == 1 /* Element */) { + return /** @type {!Node} */ (firstChild); + } + } + + // If we're forcing it to be a single element, return the wrapper DIV. + if (opt_asElement) { + return wrapper; + } + + // Otherwise, create and return a fragment. + var fragment = dom.createDocumentFragment(); + while (wrapper.firstChild) { + fragment.appendChild(wrapper.firstChild); + } + return fragment; +}; + + +/** + * Returns a Unicode BiDi mark matching bidiGlobalDir (LRM or RLM) if the + * directionality or the exit directionality of text are opposite to + * bidiGlobalDir. Otherwise returns the empty string. + * If opt_isHtml, makes sure to ignore the LTR nature of the mark-up and escapes + * in text, making the logic suitable for HTML and HTML-escaped text. + * @param {number} bidiGlobalDir The global directionality context: 1 if ltr, -1 + * if rtl, 0 if unknown. + * @param {number} dir text's directionality: 1 if ltr, -1 if rtl, 0 if unknown. + * @param {string} text The text whose directionality is to be estimated. + * @param {boolean=} opt_isHtml Whether text is HTML/HTML-escaped. + * Default: false. + * @return {string} A Unicode bidi mark matching bidiGlobalDir, or + * the empty string when text's overall and exit directionalities both match + * bidiGlobalDir, or bidiGlobalDir is 0 (unknown). + * @private + */ +soyshim.$$bidiMarkAfterKnownDir_ = function( + bidiGlobalDir, dir, text, opt_isHtml) { + return ( + bidiGlobalDir > 0 && (dir < 0 || + soyshim.$$bidiIsRtlExitText_(text, opt_isHtml)) ? '\u200E' : // LRM + bidiGlobalDir < 0 && (dir > 0 || + soyshim.$$bidiIsLtrExitText_(text, opt_isHtml)) ? '\u200F' : // RLM + ''); +}; + + +/** + * Strips str of any HTML mark-up and escapes. Imprecise in several ways, but + * precision is not very important, since the result is only meant to be used + * for directionality detection. + * @param {string} str The string to be stripped. + * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. + * Default: false. + * @return {string} The stripped string. + * @private + */ +soyshim.$$bidiStripHtmlIfNecessary_ = function(str, opt_isHtml) { + return opt_isHtml ? str.replace(soyshim.$$BIDI_HTML_SKIP_RE_, ' ') : str; +}; + + +/** + * Simplified regular expression for am HTML tag (opening or closing) or an HTML + * escape - the things we want to skip over in order to ignore their ltr + * characters. + * @type {RegExp} + * @private + */ +soyshim.$$BIDI_HTML_SKIP_RE_ = /<[^>]*>|&[^;]+;/g; + + +/** + * A practical pattern to identify strong LTR character. This pattern is not + * theoretically correct according to unicode standard. It is simplified for + * performance and small code size. + * @type {string} + * @private + */ +soyshim.$$bidiLtrChars_ = + 'A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF' + + '\u2C00-\uFB1C\uFDFE-\uFE6F\uFEFD-\uFFFF'; + + +/** + * A practical pattern to identify strong neutral and weak character. This + * pattern is not theoretically correct according to unicode standard. It is + * simplified for performance and small code size. + * @type {string} + * @private + */ +soyshim.$$bidiNeutralChars_ = + '\u0000-\u0020!-@[-`{-\u00BF\u00D7\u00F7\u02B9-\u02FF\u2000-\u2BFF'; + + +/** + * A practical pattern to identify strong RTL character. This pattern is not + * theoretically correct according to unicode standard. It is simplified for + * performance and small code size. + * @type {string} + * @private + */ +soyshim.$$bidiRtlChars_ = '\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC'; + + +/** + * Regular expressions to check if a piece of text is of RTL directionality + * on first character with strong directionality. + * @type {RegExp} + * @private + */ +soyshim.$$bidiRtlDirCheckRe_ = new RegExp( + '^[^' + soyshim.$$bidiLtrChars_ + ']*[' + soyshim.$$bidiRtlChars_ + ']'); + + +/** + * Regular expressions to check if a piece of text is of neutral directionality. + * Url are considered as neutral. + * @type {RegExp} + * @private + */ +soyshim.$$bidiNeutralDirCheckRe_ = new RegExp( + '^[' + soyshim.$$bidiNeutralChars_ + ']*$|^http://'); + + +/** + * Check the directionality of the a piece of text based on the first character + * with strong directionality. + * @param {string} str string being checked. + * @return {boolean} return true if rtl directionality is being detected. + * @private + */ +soyshim.$$bidiIsRtlText_ = function(str) { + return soyshim.$$bidiRtlDirCheckRe_.test(str); +}; + + +/** + * Check the directionality of the a piece of text based on the first character + * with strong directionality. + * @param {string} str string being checked. + * @return {boolean} true if all characters have neutral directionality. + * @private + */ +soyshim.$$bidiIsNeutralText_ = function(str) { + return soyshim.$$bidiNeutralDirCheckRe_.test(str); +}; + + +/** + * This constant controls threshold of rtl directionality. + * @type {number} + * @private + */ +soyshim.$$bidiRtlDetectionThreshold_ = 0.40; + + +/** + * Returns the RTL ratio based on word count. + * @param {string} str the string that need to be checked. + * @return {number} the ratio of RTL words among all words with directionality. + * @private + */ +soyshim.$$bidiRtlWordRatio_ = function(str) { + var rtlCount = 0; + var totalCount = 0; + var tokens = str.split(' '); + for (var i = 0; i < tokens.length; i++) { + if (soyshim.$$bidiIsRtlText_(tokens[i])) { + rtlCount++; + totalCount++; + } else if (!soyshim.$$bidiIsNeutralText_(tokens[i])) { + totalCount++; + } + } + + return totalCount == 0 ? 0 : rtlCount / totalCount; +}; + + +/** + * Regular expressions to check if the last strongly-directional character in a + * piece of text is LTR. + * @type {RegExp} + * @private + */ +soyshim.$$bidiLtrExitDirCheckRe_ = new RegExp( + '[' + soyshim.$$bidiLtrChars_ + '][^' + soyshim.$$bidiRtlChars_ + ']*$'); + + +/** + * Regular expressions to check if the last strongly-directional character in a + * piece of text is RTL. + * @type {RegExp} + * @private + */ +soyshim.$$bidiRtlExitDirCheckRe_ = new RegExp( + '[' + soyshim.$$bidiRtlChars_ + '][^' + soyshim.$$bidiLtrChars_ + ']*$'); + + +/** + * Check if the exit directionality a piece of text is LTR, i.e. if the last + * strongly-directional character in the string is LTR. + * @param {string} str string being checked. + * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. + * Default: false. + * @return {boolean} Whether LTR exit directionality was detected. + * @private + */ +soyshim.$$bidiIsLtrExitText_ = function(str, opt_isHtml) { + str = soyshim.$$bidiStripHtmlIfNecessary_(str, opt_isHtml); + return soyshim.$$bidiLtrExitDirCheckRe_.test(str); +}; + + +/** + * Check if the exit directionality a piece of text is RTL, i.e. if the last + * strongly-directional character in the string is RTL. + * @param {string} str string being checked. + * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. + * Default: false. + * @return {boolean} Whether RTL exit directionality was detected. + * @private + */ +soyshim.$$bidiIsRtlExitText_ = function(str, opt_isHtml) { + str = soyshim.$$bidiStripHtmlIfNecessary_(str, opt_isHtml); + return soyshim.$$bidiRtlExitDirCheckRe_.test(str); +}; + + +// ============================================================================= +// COPIED FROM soyutils_usegoog.js + + +// ----------------------------------------------------------------------------- +// StringBuilder (compatible with the 'stringbuilder' code style). + + +/** + * Utility class to facilitate much faster string concatenation in IE, + * using Array.join() rather than the '+' operator. For other browsers + * we simply use the '+' operator. + * + * @param {Object} var_args Initial items to append, + * e.g., new soy.StringBuilder('foo', 'bar'). + * @constructor + */ +soy.StringBuilder = goog.string.StringBuffer; + + +// ----------------------------------------------------------------------------- +// soydata: Defines typed strings, e.g. an HTML string {@code "ac"} is +// semantically distinct from the plain text string {@code "ac"} and smart +// templates can take that distinction into account. + +/** + * A type of textual content. + * + * This is an enum of type Object so that these values are unforgeable. + * + * @enum {!Object} + */ +soydata.SanitizedContentKind = goog.soy.data.SanitizedContentKind; + + +/** + * Content of type {@link soydata.SanitizedContentKind.HTML}. + * + * The content is a string of HTML that can safely be embedded in a PCDATA + * context in your app. If you would be surprised to find that an HTML + * sanitizer produced {@code s} (e.g. it runs code or fetches bad URLs) and + * you wouldn't write a template that produces {@code s} on security or privacy + * grounds, then don't pass {@code s} here. + * + * @constructor + * @extends {goog.soy.data.SanitizedContent} + */ +soydata.SanitizedHtml = function() { + goog.soy.data.SanitizedContent.call(this); // Throws an exception. +}; +goog.inherits(soydata.SanitizedHtml, goog.soy.data.SanitizedContent); + +/** @override */ +soydata.SanitizedHtml.prototype.contentKind = soydata.SanitizedContentKind.HTML; + + +/** + * Content of type {@link soydata.SanitizedContentKind.JS}. + * + * The content is Javascript source that when evaluated does not execute any + * attacker-controlled scripts. + * + * @constructor + * @extends {goog.soy.data.SanitizedContent} + */ +soydata.SanitizedJs = function() { + goog.soy.data.SanitizedContent.call(this); // Throws an exception. +}; +goog.inherits(soydata.SanitizedJs, goog.soy.data.SanitizedContent); + +/** @override */ +soydata.SanitizedJs.prototype.contentKind = + soydata.SanitizedContentKind.JS; + + +/** + * Content of type {@link soydata.SanitizedContentKind.JS_STR_CHARS}. + * + * The content can be safely inserted as part of a single- or double-quoted + * string without terminating the string. + * + * @constructor + * @extends {goog.soy.data.SanitizedContent} + */ +soydata.SanitizedJsStrChars = function() { + goog.soy.data.SanitizedContent.call(this); // Throws an exception. +}; +goog.inherits(soydata.SanitizedJsStrChars, goog.soy.data.SanitizedContent); + +/** @override */ +soydata.SanitizedJsStrChars.prototype.contentKind = + soydata.SanitizedContentKind.JS_STR_CHARS; + + +/** + * Content of type {@link soydata.SanitizedContentKind.URI}. + * + * The content is a URI chunk that the caller knows is safe to emit in a + * template. + * + * @constructor + * @extends {goog.soy.data.SanitizedContent} + */ +soydata.SanitizedUri = function() { + goog.soy.data.SanitizedContent.call(this); // Throws an exception. +}; +goog.inherits(soydata.SanitizedUri, goog.soy.data.SanitizedContent); + +/** @override */ +soydata.SanitizedUri.prototype.contentKind = soydata.SanitizedContentKind.URI; + + +/** + * Content of type {@link soydata.SanitizedContentKind.ATTRIBUTES}. + * + * The content should be safely embeddable within an open tag, such as a + * key="value" pair. + * + * @constructor + * @extends {goog.soy.data.SanitizedContent} + */ +soydata.SanitizedHtmlAttribute = function() { + goog.soy.data.SanitizedContent.call(this); // Throws an exception. +}; +goog.inherits(soydata.SanitizedHtmlAttribute, goog.soy.data.SanitizedContent); + +/** @override */ +soydata.SanitizedHtmlAttribute.prototype.contentKind = + soydata.SanitizedContentKind.ATTRIBUTES; + + +/** + * Content of type {@link soydata.SanitizedContentKind.CSS}. + * + * The content is non-attacker-exploitable CSS, such as {@code color:#c3d9ff}. + * + * @constructor + * @extends {goog.soy.data.SanitizedContent} + */ +soydata.SanitizedCss = function() { + goog.soy.data.SanitizedContent.call(this); // Throws an exception. +}; +goog.inherits(soydata.SanitizedCss, goog.soy.data.SanitizedContent); + +/** @override */ +soydata.SanitizedCss.prototype.contentKind = + soydata.SanitizedContentKind.CSS; + + +/** + * Unsanitized plain text string. + * + * While all strings are effectively safe to use as a plain text, there are no + * guarantees about safety in any other context such as HTML. This is + * sometimes used to mark that should never be used unescaped. + * + * @param {*} content Plain text with no guarantees. + * @constructor + * @extends {goog.soy.data.SanitizedContent} + */ +soydata.UnsanitizedText = function(content) { + /** @override */ + this.content = String(content); +}; +goog.inherits(soydata.UnsanitizedText, goog.soy.data.SanitizedContent); + +/** @override */ +soydata.UnsanitizedText.prototype.contentKind = + soydata.SanitizedContentKind.TEXT; + + +/** + * Creates a factory for SanitizedContent types. + * + * This is a hack so that the soydata.VERY_UNSAFE.ordainSanitized* can + * instantiate Sanitized* classes, without making the Sanitized* constructors + * publicly usable. Requiring all construction to use the VERY_UNSAFE names + * helps callers and their reviewers easily tell that creating SanitizedContent + * is not always safe and calls for careful review. + * + * @param {function(new: T, string)} ctor A constructor. + * @return {!function(*): T} A factory that takes content and returns a + * new instance. + * @template T + * @private + */ +soydata.$$makeSanitizedContentFactory_ = function(ctor) { + /** @constructor */ + function InstantiableCtor() {} + InstantiableCtor.prototype = ctor.prototype; + return function(content) { + var result = new InstantiableCtor(); + result.content = String(content); + return result; + }; +}; + + +// ----------------------------------------------------------------------------- +// Sanitized content ordainers. Please use these with extreme caution (with the +// exception of markUnsanitizedText). A good recommendation is to limit usage +// of these to just a handful of files in your source tree where usages can be +// carefully audited. + + +/** + * Protects a string from being used in an noAutoescaped context. + * + * This is useful for content where there is significant risk of accidental + * unescaped usage in a Soy template. A great case is for user-controlled + * data that has historically been a source of vulernabilities. + * + * @param {*} content Text to protect. + * @return {!soydata.UnsanitizedText} A wrapper that is rejected by the + * Soy noAutoescape print directive. + */ +soydata.markUnsanitizedText = function(content) { + return new soydata.UnsanitizedText(content); +}; + + +/** + * Takes a leap of faith that the provided content is "safe" HTML. + * + * @param {*} content A string of HTML that can safely be embedded in + * a PCDATA context in your app. If you would be surprised to find that an + * HTML sanitizer produced {@code s} (e.g. it runs code or fetches bad URLs) + * and you wouldn't write a template that produces {@code s} on security or + * privacy grounds, then don't pass {@code s} here. + * @return {!soydata.SanitizedHtml} Sanitized content wrapper that + * indicates to Soy not to escape when printed as HTML. + */ +soydata.VERY_UNSAFE.ordainSanitizedHtml = + soydata.$$makeSanitizedContentFactory_(soydata.SanitizedHtml); + + +/** + * Takes a leap of faith that the provided content is "safe" (non-attacker- + * controlled, XSS-free) Javascript. + * + * @param {*} content Javascript source that when evaluated does not + * execute any attacker-controlled scripts. + * @return {!soydata.SanitizedJs} Sanitized content wrapper that indicates to + * Soy not to escape when printed as Javascript source. + */ +soydata.VERY_UNSAFE.ordainSanitizedJs = + soydata.$$makeSanitizedContentFactory_(soydata.SanitizedJs); + + +// TODO: This function is probably necessary, either externally or internally +// as an implementation detail. Generally, plain text will always work here, +// as there's no harm to unescaping the string and then re-escaping when +// finally printed. +/** + * Takes a leap of faith that the provided content can be safely embedded in + * a Javascript string without re-esacping. + * + * @param {*} content Content that can be safely inserted as part of a + * single- or double-quoted string without terminating the string. + * @return {!soydata.SanitizedJsStrChars} Sanitized content wrapper that + * indicates to Soy not to escape when printed in a JS string. + */ +soydata.VERY_UNSAFE.ordainSanitizedJsStrChars = + soydata.$$makeSanitizedContentFactory_(soydata.SanitizedJsStrChars); + + +/** + * Takes a leap of faith that the provided content is "safe" to use as a URI + * in a Soy template. + * + * This creates a Soy SanitizedContent object which indicates to Soy there is + * no need to escape it when printed as a URI (e.g. in an href or src + * attribute), such as if it's already been encoded or if it's a Javascript: + * URI. + * + * @param {*} content A chunk of URI that the caller knows is safe to + * emit in a template. + * @return {!soydata.SanitizedUri} Sanitized content wrapper that indicates to + * Soy not to escape or filter when printed in URI context. + */ +soydata.VERY_UNSAFE.ordainSanitizedUri = + soydata.$$makeSanitizedContentFactory_(soydata.SanitizedUri); + + +/** + * Takes a leap of faith that the provided content is "safe" to use as an + * HTML attribute. + * + * @param {*} content An attribute name and value, such as + * {@code dir="ltr"}. + * @return {!soydata.SanitizedHtmlAttribute} Sanitized content wrapper that + * indicates to Soy not to escape when printed as an HTML attribute. + */ +soydata.VERY_UNSAFE.ordainSanitizedHtmlAttribute = + soydata.$$makeSanitizedContentFactory_(soydata.SanitizedHtmlAttribute); + + +/** + * Takes a leap of faith that the provided content is "safe" to use as CSS + * in a style attribute or block. + * + * @param {*} content CSS, such as {@code color:#c3d9ff}. + * @return {!soydata.SanitizedCss} Sanitized CSS wrapper that indicates to + * Soy there is no need to escape or filter when printed in CSS context. + */ +soydata.VERY_UNSAFE.ordainSanitizedCss = + soydata.$$makeSanitizedContentFactory_(soydata.SanitizedCss); + + +// ----------------------------------------------------------------------------- +// Public utilities. + + +/** + * Helper function to render a Soy template and then set the output string as + * the innerHTML of an element. It is recommended to use this helper function + * instead of directly setting innerHTML in your hand-written code, so that it + * will be easier to audit the code for cross-site scripting vulnerabilities. + * + * NOTE: New code should consider using goog.soy.renderElement instead. + * + * @param {Element} element The element whose content we are rendering. + * @param {Function} template The Soy template defining the element's content. + * @param {Object=} opt_templateData The data for the template. + * @param {Object=} opt_injectedData The injected data for the template. + */ +soy.renderElement = goog.soy.renderElement; + + +/** + * Helper function to render a Soy template into a single node or a document + * fragment. If the rendered HTML string represents a single node, then that + * node is returned (note that this is *not* a fragment, despite them name of + * the method). Otherwise a document fragment is returned containing the + * rendered nodes. + * + * NOTE: New code should consider using goog.soy.renderAsFragment + * instead (note that the arguments are different). + * + * @param {Function} template The Soy template defining the element's content. + * @param {Object=} opt_templateData The data for the template. + * @param {Document=} opt_document The document used to create DOM nodes. If not + * specified, global document object is used. + * @param {Object=} opt_injectedData The injected data for the template. + * @return {!Node} The resulting node or document fragment. + */ +soy.renderAsFragment = function( + template, opt_templateData, opt_document, opt_injectedData) { + return goog.soy.renderAsFragment( + template, opt_templateData, opt_injectedData, + new goog.dom.DomHelper(opt_document)); +}; + + +/** + * Helper function to render a Soy template into a single node. If the rendered + * HTML string represents a single node, then that node is returned. Otherwise, + * a DIV element is returned containing the rendered nodes. + * + * NOTE: New code should consider using goog.soy.renderAsElement + * instead (note that the arguments are different). + * + * @param {Function} template The Soy template defining the element's content. + * @param {Object=} opt_templateData The data for the template. + * @param {Document=} opt_document The document used to create DOM nodes. If not + * specified, global document object is used. + * @param {Object=} opt_injectedData The injected data for the template. + * @return {!Element} Rendered template contents, wrapped in a parent DIV + * element if necessary. + */ +soy.renderAsElement = function( + template, opt_templateData, opt_document, opt_injectedData) { + return goog.soy.renderAsElement( + template, opt_templateData, opt_injectedData, + new goog.dom.DomHelper(opt_document)); +}; + + +// ----------------------------------------------------------------------------- +// Below are private utilities to be used by Soy-generated code only. + + +/** + * Builds an augmented map. The returned map will contain mappings from both + * the base map and the additional map. If the same key appears in both, then + * the value from the additional map will be visible, while the value from the + * base map will be hidden. The base map will be used, but not modified. + * + * @param {!Object} baseMap The original map to augment. + * @param {!Object} additionalMap A map containing the additional mappings. + * @return {!Object} An augmented map containing both the original and + * additional mappings. + */ +soy.$$augmentMap = function(baseMap, additionalMap) { + + // Create a new map whose '__proto__' field is set to baseMap. + /** @constructor */ + function TempCtor() {} + TempCtor.prototype = baseMap; + var augmentedMap = new TempCtor(); + + // Add the additional mappings to the new map. + for (var key in additionalMap) { + augmentedMap[key] = additionalMap[key]; + } + + return augmentedMap; +}; + + +/** + * Checks that the given map key is a string. + * @param {*} key Key to check. + * @return {string} The given key. + */ +soy.$$checkMapKey = function(key) { + if ((typeof key) != 'string') { + throw Error( + 'Map literal\'s key expression must evaluate to string' + + ' (encountered type "' + (typeof key) + '").'); + } + return key; +}; + + +/** + * Gets the keys in a map as an array. There are no guarantees on the order. + * @param {Object} map The map to get the keys of. + * @return {Array.} The array of keys in the given map. + */ +soy.$$getMapKeys = function(map) { + var mapKeys = []; + for (var key in map) { + mapKeys.push(key); + } + return mapKeys; +}; + + +/** + * Gets a consistent unique id for the given delegate template name. Two calls + * to this function will return the same id if and only if the input names are + * the same. + * + *

Important: This function must always be called with a string constant. + * + *

If Closure Compiler is not being used, then this is just this identity + * function. If Closure Compiler is being used, then each call to this function + * will be replaced with a short string constant, which will be consistent per + * input name. + * + * @param {string} delTemplateName The delegate template name for which to get a + * consistent unique id. + * @return {string} A unique id that is consistent per input name. + * + * @consistentIdGenerator + */ +soy.$$getDelTemplateId = function(delTemplateName) { + return delTemplateName; +}; + + +/** + * Map from registered delegate template key to the priority of the + * implementation. + * @type {Object} + * @private + */ +soy.$$DELEGATE_REGISTRY_PRIORITIES_ = {}; + +/** + * Map from registered delegate template key to the implementation function. + * @type {Object} + * @private + */ +soy.$$DELEGATE_REGISTRY_FUNCTIONS_ = {}; + + +/** + * Registers a delegate implementation. If the same delegate template key (id + * and variant) has been registered previously, then priority values are + * compared and only the higher priority implementation is stored (if + * priorities are equal, an error is thrown). + * + * @param {string} delTemplateId The delegate template id. + * @param {string} delTemplateVariant The delegate template variant (can be + * empty string). + * @param {number} delPriority The implementation's priority value. + * @param {Function} delFn The implementation function. + */ +soy.$$registerDelegateFn = function( + delTemplateId, delTemplateVariant, delPriority, delFn) { + + var mapKey = 'key_' + delTemplateId + ':' + delTemplateVariant; + var currPriority = soy.$$DELEGATE_REGISTRY_PRIORITIES_[mapKey]; + if (currPriority === undefined || delPriority > currPriority) { + // Registering new or higher-priority function: replace registry entry. + soy.$$DELEGATE_REGISTRY_PRIORITIES_[mapKey] = delPriority; + soy.$$DELEGATE_REGISTRY_FUNCTIONS_[mapKey] = delFn; + } else if (delPriority == currPriority) { + // Registering same-priority function: error. + throw Error( + 'Encountered two active delegates with the same priority ("' + + delTemplateId + ':' + delTemplateVariant + '").'); + } else { + // Registering lower-priority function: do nothing. + } +}; + + +/** + * Retrieves the (highest-priority) implementation that has been registered for + * a given delegate template key (id and variant). If no implementation has + * been registered for the key, then the fallback is the same id with empty + * variant. If the fallback is also not registered, and allowsEmptyDefault is + * true, then returns an implementation that is equivalent to an empty template + * (i.e. rendered output would be empty string). + * + * @param {string} delTemplateId The delegate template id. + * @param {string} delTemplateVariant The delegate template variant (can be + * empty string). + * @param {boolean} allowsEmptyDefault Whether to default to the empty template + * function if there's no active implementation. + * @return {Function} The retrieved implementation function. + */ +soy.$$getDelegateFn = function( + delTemplateId, delTemplateVariant, allowsEmptyDefault) { + + var delFn = soy.$$DELEGATE_REGISTRY_FUNCTIONS_[ + 'key_' + delTemplateId + ':' + delTemplateVariant]; + if (! delFn && delTemplateVariant != '') { + // Fallback to empty variant. + delFn = soy.$$DELEGATE_REGISTRY_FUNCTIONS_['key_' + delTemplateId + ':']; + } + + if (delFn) { + return delFn; + } else if (allowsEmptyDefault) { + return soy.$$EMPTY_TEMPLATE_FN_; + } else { + throw Error( + 'Found no active impl for delegate call to "' + delTemplateId + ':' + + delTemplateVariant + '" (and not allowemptydefault="true").'); + } +}; + + +/** + * Private helper soy.$$getDelegateFn(). This is the empty template function + * that is returned whenever there's no delegate implementation found. + * + * @param {Object.=} opt_data + * @param {soy.StringBuilder=} opt_sb + * @param {Object.=} opt_ijData + * @return {string} + * @private + */ +soy.$$EMPTY_TEMPLATE_FN_ = function(opt_data, opt_sb, opt_ijData) { + return ''; +}; + + +// ----------------------------------------------------------------------------- +// Escape/filter/normalize. + + +/** + * Escapes HTML special characters in a string. Escapes double quote '"' in + * addition to '&', '<', and '>' so that a string can be included in an HTML + * tag attribute value within double quotes. + * Will emit known safe HTML as-is. + * + * @param {*} value The string-like value to be escaped. May not be a string, + * but the value will be coerced to a string. + * @return {string} An escaped version of value. + */ +soy.$$escapeHtml = function(value) { + // TODO: Perhaps we should just ignore the contentKind property and instead + // look only at the constructor. + if (value && value.contentKind && + value.contentKind === goog.soy.data.SanitizedContentKind.HTML) { + goog.asserts.assert( + value.constructor === soydata.SanitizedHtml); + return value.content; + } + return soy.esc.$$escapeHtmlHelper(value); +}; + + +/** + * Strips unsafe tags to convert a string of untrusted HTML into HTML that + * is safe to embed. + * + * @param {*} value The string-like value to be escaped. May not be a string, + * but the value will be coerced to a string. + * @return {string} A sanitized and normalized version of value. + */ +soy.$$cleanHtml = function(value) { + if (value && value.contentKind && + value.contentKind === goog.soy.data.SanitizedContentKind.HTML) { + goog.asserts.assert( + value.constructor === soydata.SanitizedHtml); + return value.content; + } + return soy.$$stripHtmlTags(value, soy.esc.$$SAFE_TAG_WHITELIST_); +}; + + +/** + * Escapes HTML special characters in a string so that it can be embedded in + * RCDATA. + *

+ * Escapes HTML special characters so that the value will not prematurely end + * the body of a tag like {@code }. + *

+ * Will normalize known safe HTML to make sure that sanitized HTML (which could + * contain an innocuous {@code } don't prematurely end an RCDATA + * element. + * + * @param {*} value The string-like value to be escaped. May not be a string, + * but the value will be coerced to a string. + * @return {string} An escaped version of value. + */ +soy.$$escapeHtmlRcdata = function(value) { + if (value && value.contentKind && + value.contentKind === goog.soy.data.SanitizedContentKind.HTML) { + goog.asserts.assert( + value.constructor === soydata.SanitizedHtml); + return soy.esc.$$normalizeHtmlHelper(value.content); + } + return soy.esc.$$escapeHtmlHelper(value); +}; + + +/** + * Matches any/only HTML5 void elements' start tags. + * See http://www.w3.org/TR/html-markup/syntax.html#syntax-elements + * @type {RegExp} + * @private + */ +soy.$$HTML5_VOID_ELEMENTS_ = new RegExp( + '^<(?:area|base|br|col|command|embed|hr|img|input' + + '|keygen|link|meta|param|source|track|wbr)\\b'); + + +/** + * Removes HTML tags from a string of known safe HTML. + * If opt_tagWhitelist is not specified or is empty, then + * the result can be used as an attribute value. + * + * @param {*} value The HTML to be escaped. May not be a string, but the + * value will be coerced to a string. + * @param {Object.=} opt_tagWhitelist Has an own property whose + * name is a lower-case tag name and whose value is {@code 1} for + * each element that is allowed in the output. + * @return {string} A representation of value without disallowed tags, + * HTML comments, or other non-text content. + */ +soy.$$stripHtmlTags = function(value, opt_tagWhitelist) { + if (!opt_tagWhitelist) { + // If we have no white-list, then use a fast track which elides all tags. + return String(value).replace(soy.esc.$$HTML_TAG_REGEX_, '') + // This is just paranoia since callers should normalize the result + // anyway, but if they didn't, it would be necessary to ensure that + // after the first replace non-tag uses of < do not recombine into + // tags as in "<script>alert(1337)script>". + .replace(soy.esc.$$LT_REGEX_, '<'); + } + + // Escapes '[' so that we can use [123] below to mark places where tags + // have been removed. + var html = String(value).replace(/\[/g, '['); + + // Consider all uses of '<' and replace whitelisted tags with markers like + // [1] which are indices into a list of approved tag names. + // Replace all other uses of < and > with entities. + var tags = []; + html = html.replace( + soy.esc.$$HTML_TAG_REGEX_, + function(tok, tagName) { + if (tagName) { + tagName = tagName.toLowerCase(); + if (opt_tagWhitelist.hasOwnProperty(tagName) && + opt_tagWhitelist[tagName]) { + var start = tok.charAt(1) === '/' ? ''; + return '[' + index + ']'; + } + } + return ''; + }); + + // Escape HTML special characters. Now there are no '<' in html that could + // start a tag. + html = soy.esc.$$normalizeHtmlHelper(html); + + var finalCloseTags = soy.$$balanceTags_(tags); + + // Now html contains no tags or less-than characters that could become + // part of a tag via a replacement operation and tags only contains + // approved tags. + // Reinsert the white-listed tags. + html = html.replace( + /\[(\d+)\]/g, function(_, index) { return tags[index]; }); + + // Close any still open tags. + // This prevents unclosed formatting elements like

    and from + // breaking the layout of containing HTML. + return html + finalCloseTags; +}; + + +/** + * Throw out any close tags that don't correspond to start tags. + * If {@code
    } is used for formatting, embedded HTML shouldn't be able + * to use a mismatched {@code
    } to break page layout. + * + * @param {Array.} tags an array of tags that will be modified in place + * include tags, the empty string, or concatenations of empty tags. + * @return {string} zero or more closed tags that close all elements that are + * opened in tags but not closed. + * @private + */ +soy.$$balanceTags_ = function(tags) { + var open = []; + for (var i = 0, n = tags.length; i < n; ++i) { + var tag = tags[i]; + if (tag.charAt(1) === '/') { + var openTagIndex = open.length - 1; + // NOTE: This is essentially lastIndexOf, but it's not supported in IE. + while (openTagIndex >= 0 && open[openTagIndex] != tag) { + openTagIndex--; + } + if (openTagIndex < 0) { + tags[i] = ''; // Drop close tag. + } else { + tags[i] = open.slice(openTagIndex).reverse().join(''); + open.length = openTagIndex; + } + } else if (!soy.$$HTML5_VOID_ELEMENTS_.test(tag)) { + open.push('Hello World + return soy.esc.$$filterHtmlElementNameHelper(value); +}; + + +/** + * Escapes characters in the value to make it valid content for a JS string + * literal. + * + * @param {*} value The value to escape. May not be a string, but the value + * will be coerced to a string. + * @return {string} An escaped version of value. + * @deprecated + */ +soy.$$escapeJs = function(value) { + return soy.$$escapeJsString(value); +}; + + +/** + * Escapes characters in the value to make it valid content for a JS string + * literal. + * + * @param {*} value The value to escape. May not be a string, but the value + * will be coerced to a string. + * @return {string} An escaped version of value. + */ +soy.$$escapeJsString = function(value) { + if (value && + value.contentKind === goog.soy.data.SanitizedContentKind.JS_STR_CHARS) { + // TODO: It might still be worthwhile to normalize it to remove + // unescaped quotes, null, etc: replace(/(?:^|[^\])['"]/g, '\\$ + goog.asserts.assert(value.constructor === + soydata.SanitizedJsStrChars); + return value.content; + } + return soy.esc.$$escapeJsStringHelper(value); +}; + + +/** + * Encodes a value as a JavaScript literal. + * + * @param {*} value The value to escape. May not be a string, but the value + * will be coerced to a string. + * @return {string} A JavaScript code representation of the input. + */ +soy.$$escapeJsValue = function(value) { + // We surround values with spaces so that they can't be interpolated into + // identifiers by accident. + // We could use parentheses but those might be interpreted as a function call. + if (value == null) { // Intentionally matches undefined. + // Java returns null from maps where there is no corresponding key while + // JS returns undefined. + // We always output null for compatibility with Java which does not have a + // distinct undefined value. + return ' null '; + } + if (value.contentKind == goog.soy.data.SanitizedContentKind.JS) { + goog.asserts.assert(value.constructor === + soydata.SanitizedJs); + return value.content; + } + switch (typeof value) { + case 'boolean': case 'number': + return ' ' + value + ' '; + default: + return "'" + soy.esc.$$escapeJsStringHelper(String(value)) + "'"; + } +}; + + +/** + * Escapes characters in the string to make it valid content for a JS regular + * expression literal. + * + * @param {*} value The value to escape. May not be a string, but the value + * will be coerced to a string. + * @return {string} An escaped version of value. + */ +soy.$$escapeJsRegex = function(value) { + return soy.esc.$$escapeJsRegexHelper(value); +}; + + +/** + * Matches all URI mark characters that conflict with HTML attribute delimiters + * or that cannot appear in a CSS uri. + * From G.2: CSS grammar + *
    + *     url        ([!#$%&*-~]|{nonascii}|{escape})*
    + * 
    + * + * @type {RegExp} + * @private + */ +soy.$$problematicUriMarks_ = /['()]/g; + +/** + * @param {string} ch A single character in {@link soy.$$problematicUriMarks_}. + * @return {string} + * @private + */ +soy.$$pctEncode_ = function(ch) { + return '%' + ch.charCodeAt(0).toString(16); +}; + +/** + * Escapes a string so that it can be safely included in a URI. + * + * @param {*} value The value to escape. May not be a string, but the value + * will be coerced to a string. + * @return {string} An escaped version of value. + */ +soy.$$escapeUri = function(value) { + if (value && value.contentKind === goog.soy.data.SanitizedContentKind.URI) { + goog.asserts.assert(value.constructor === + soydata.SanitizedUri); + return soy.$$normalizeUri(value); + } + // Apostophes and parentheses are not matched by encodeURIComponent. + // They are technically special in URIs, but only appear in the obsolete mark + // production in Appendix D.2 of RFC 3986, so can be encoded without changing + // semantics. + var encoded = soy.esc.$$escapeUriHelper(value); + soy.$$problematicUriMarks_.lastIndex = 0; + if (soy.$$problematicUriMarks_.test(encoded)) { + return encoded.replace(soy.$$problematicUriMarks_, soy.$$pctEncode_); + } + return encoded; +}; + + +/** + * Removes rough edges from a URI by escaping any raw HTML/JS string delimiters. + * + * @param {*} value The value to escape. May not be a string, but the value + * will be coerced to a string. + * @return {string} An escaped version of value. + */ +soy.$$normalizeUri = function(value) { + return soy.esc.$$normalizeUriHelper(value); +}; + + +/** + * Vets a URI's protocol and removes rough edges from a URI by escaping + * any raw HTML/JS string delimiters. + * + * @param {*} value The value to escape. May not be a string, but the value + * will be coerced to a string. + * @return {string} An escaped version of value. + */ +soy.$$filterNormalizeUri = function(value) { + if (value && value.contentKind == goog.soy.data.SanitizedContentKind.URI) { + goog.asserts.assert(value.constructor === + soydata.SanitizedUri); + return soy.$$normalizeUri(value); + } + return soy.esc.$$filterNormalizeUriHelper(value); +}; + + +/** + * Escapes a string so it can safely be included inside a quoted CSS string. + * + * @param {*} value The value to escape. May not be a string, but the value + * will be coerced to a string. + * @return {string} An escaped version of value. + */ +soy.$$escapeCssString = function(value) { + return soy.esc.$$escapeCssStringHelper(value); +}; + + +/** + * Encodes a value as a CSS identifier part, keyword, or quantity. + * + * @param {*} value The value to escape. May not be a string, but the value + * will be coerced to a string. + * @return {string} A safe CSS identifier part, keyword, or quanitity. + */ +soy.$$filterCssValue = function(value) { + if (value && value.contentKind === goog.soy.data.SanitizedContentKind.CSS) { + goog.asserts.assert(value.constructor === + soydata.SanitizedCss); + return value.content; + } + // Uses == to intentionally match null and undefined for Java compatibility. + if (value == null) { + return ''; + } + return soy.esc.$$filterCssValueHelper(value); +}; + + +/** + * Sanity-checks noAutoescape input for explicitly tainted content. + * + * SanitizedContentKind.TEXT is used to explicitly mark input that was never + * meant to be used unescaped. + * + * @param {*} value The value to filter. + * @return {string} The value, that we dearly hope will not cause an attack. + */ +soy.$$filterNoAutoescape = function(value) { + if (value && value.contentKind === goog.soy.data.SanitizedContentKind.TEXT) { + // Fail in development mode. + goog.asserts.fail( + 'Tainted SanitizedContentKind.TEXT for |noAutoescape: `%s`', + [value.content]); + // Return innocuous data in production. + return 'zSoyz'; + } + return String(value); +}; + + +// ----------------------------------------------------------------------------- +// Basic directives/functions. + + +/** + * Converts \r\n, \r, and \n to
    s + * @param {*} str The string in which to convert newlines. + * @return {string} A copy of {@code str} with converted newlines. + */ +soy.$$changeNewlineToBr = function(str) { + return goog.string.newLineToBr(String(str), false); +}; + + +/** + * Inserts word breaks ('wbr' tags) into a HTML string at a given interval. The + * counter is reset if a space is encountered. Word breaks aren't inserted into + * HTML tags or entities. Entites count towards the character count; HTML tags + * do not. + * + * @param {*} str The HTML string to insert word breaks into. Can be other + * types, but the value will be coerced to a string. + * @param {number} maxCharsBetweenWordBreaks Maximum number of non-space + * characters to allow before adding a word break. + * @return {string} The string including word breaks. + */ +soy.$$insertWordBreaks = function(str, maxCharsBetweenWordBreaks) { + return goog.format.insertWordBreaks(String(str), maxCharsBetweenWordBreaks); +}; + + +/** + * Truncates a string to a given max length (if it's currently longer), + * optionally adding ellipsis at the end. + * + * @param {*} str The string to truncate. Can be other types, but the value will + * be coerced to a string. + * @param {number} maxLen The maximum length of the string after truncation + * (including ellipsis, if applicable). + * @param {boolean} doAddEllipsis Whether to add ellipsis if the string needs + * truncation. + * @return {string} The string after truncation. + */ +soy.$$truncate = function(str, maxLen, doAddEllipsis) { + + str = String(str); + if (str.length <= maxLen) { + return str; // no need to truncate + } + + // If doAddEllipsis, either reduce maxLen to compensate, or else if maxLen is + // too small, just turn off doAddEllipsis. + if (doAddEllipsis) { + if (maxLen > 3) { + maxLen -= 3; + } else { + doAddEllipsis = false; + } + } + + // Make sure truncating at maxLen doesn't cut up a unicode surrogate pair. + if (soy.$$isHighSurrogate_(str.charAt(maxLen - 1)) && + soy.$$isLowSurrogate_(str.charAt(maxLen))) { + maxLen -= 1; + } + + // Truncate. + str = str.substring(0, maxLen); + + // Add ellipsis. + if (doAddEllipsis) { + str += '...'; + } + + return str; +}; + +/** + * Private helper for $$truncate() to check whether a char is a high surrogate. + * @param {string} ch The char to check. + * @return {boolean} Whether the given char is a unicode high surrogate. + * @private + */ +soy.$$isHighSurrogate_ = function(ch) { + return 0xD800 <= ch && ch <= 0xDBFF; +}; + +/** + * Private helper for $$truncate() to check whether a char is a low surrogate. + * @param {string} ch The char to check. + * @return {boolean} Whether the given char is a unicode low surrogate. + * @private + */ +soy.$$isLowSurrogate_ = function(ch) { + return 0xDC00 <= ch && ch <= 0xDFFF; +}; + + +// ----------------------------------------------------------------------------- +// Bidi directives/functions. + + +/** + * Cache of bidi formatter by context directionality, so we don't keep on + * creating new objects. + * @type {!Object.} + * @private + */ +soy.$$bidiFormatterCache_ = {}; + + +/** + * Returns cached bidi formatter for bidiGlobalDir, or creates a new one. + * @param {number} bidiGlobalDir The global directionality context: 1 if ltr, -1 + * if rtl, 0 if unknown. + * @return {goog.i18n.BidiFormatter} A formatter for bidiGlobalDir. + * @private + */ +soy.$$getBidiFormatterInstance_ = function(bidiGlobalDir) { + return soy.$$bidiFormatterCache_[bidiGlobalDir] || + (soy.$$bidiFormatterCache_[bidiGlobalDir] = + new goog.i18n.BidiFormatter(bidiGlobalDir)); +}; + + +/** + * Estimate the overall directionality of text. If opt_isHtml, makes sure to + * ignore the LTR nature of the mark-up and escapes in text, making the logic + * suitable for HTML and HTML-escaped text. + * @param {string} text The text whose directionality is to be estimated. + * @param {boolean=} opt_isHtml Whether text is HTML/HTML-escaped. + * Default: false. + * @return {number} 1 if text is LTR, -1 if it is RTL, and 0 if it is neutral. + */ +soy.$$bidiTextDir = function(text, opt_isHtml) { + if (!text) { + return 0; + } + return goog.i18n.bidi.detectRtlDirectionality(text, opt_isHtml) ? -1 : 1; +}; + + +/** + * Returns 'dir="ltr"' or 'dir="rtl"', depending on text's estimated + * directionality, if it is not the same as bidiGlobalDir. + * Otherwise, returns the empty string. + * If opt_isHtml, makes sure to ignore the LTR nature of the mark-up and escapes + * in text, making the logic suitable for HTML and HTML-escaped text. + * @param {number} bidiGlobalDir The global directionality context: 1 if ltr, -1 + * if rtl, 0 if unknown. + * @param {string} text The text whose directionality is to be estimated. + * @param {boolean=} opt_isHtml Whether text is HTML/HTML-escaped. + * Default: false. + * @return {soydata.SanitizedHtmlAttribute} 'dir="rtl"' for RTL text in non-RTL + * context; 'dir="ltr"' for LTR text in non-LTR context; + * else, the empty string. + */ +soy.$$bidiDirAttr = function(bidiGlobalDir, text, opt_isHtml) { + return soydata.VERY_UNSAFE.ordainSanitizedHtmlAttribute( + soy.$$getBidiFormatterInstance_(bidiGlobalDir).dirAttr(text, opt_isHtml)); +}; + + +/** + * Returns a Unicode BiDi mark matching bidiGlobalDir (LRM or RLM) if the + * directionality or the exit directionality of text are opposite to + * bidiGlobalDir. Otherwise returns the empty string. + * If opt_isHtml, makes sure to ignore the LTR nature of the mark-up and escapes + * in text, making the logic suitable for HTML and HTML-escaped text. + * @param {number} bidiGlobalDir The global directionality context: 1 if ltr, -1 + * if rtl, 0 if unknown. + * @param {string} text The text whose directionality is to be estimated. + * @param {boolean=} opt_isHtml Whether text is HTML/HTML-escaped. + * Default: false. + * @return {string} A Unicode bidi mark matching bidiGlobalDir, or the empty + * string when text's overall and exit directionalities both match + * bidiGlobalDir, or bidiGlobalDir is 0 (unknown). + */ +soy.$$bidiMarkAfter = function(bidiGlobalDir, text, opt_isHtml) { + var formatter = soy.$$getBidiFormatterInstance_(bidiGlobalDir); + return formatter.markAfter(text, opt_isHtml); +}; + + +/** + * Returns str wrapped in a according to its directionality + * - but only if that is neither neutral nor the same as the global context. + * Otherwise, returns str unchanged. + * Always treats str as HTML/HTML-escaped, i.e. ignores mark-up and escapes when + * estimating str's directionality. + * @param {number} bidiGlobalDir The global directionality context: 1 if ltr, -1 + * if rtl, 0 if unknown. + * @param {*} str The string to be wrapped. Can be other types, but the value + * will be coerced to a string. + * @return {string} The wrapped string. + */ +soy.$$bidiSpanWrap = function(bidiGlobalDir, str) { + var formatter = soy.$$getBidiFormatterInstance_(bidiGlobalDir); + return formatter.spanWrap(str + '', true); +}; + + +/** + * Returns str wrapped in Unicode BiDi formatting characters according to its + * directionality, i.e. either LRE or RLE at the beginning and PDF at the end - + * but only if str's directionality is neither neutral nor the same as the + * global context. Otherwise, returns str unchanged. + * Always treats str as HTML/HTML-escaped, i.e. ignores mark-up and escapes when + * estimating str's directionality. + * @param {number} bidiGlobalDir The global directionality context: 1 if ltr, -1 + * if rtl, 0 if unknown. + * @param {*} str The string to be wrapped. Can be other types, but the value + * will be coerced to a string. + * @return {string} The wrapped string. + */ +soy.$$bidiUnicodeWrap = function(bidiGlobalDir, str) { + var formatter = soy.$$getBidiFormatterInstance_(bidiGlobalDir); + return formatter.unicodeWrap(str + '', true); +}; + + +// ----------------------------------------------------------------------------- +// Generated code. + + + + +// START GENERATED CODE FOR ESCAPERS. + +/** + * @type {function (*) : string} + */ +soy.esc.$$escapeUriHelper = function(v) { + return encodeURIComponent(String(v)); +}; + +/** + * Maps charcters to the escaped versions for the named escape directives. + * @type {Object.} + * @private + */ +soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_ = { + '\x00': '\x26#0;', + '\x22': '\x26quot;', + '\x26': '\x26amp;', + '\x27': '\x26#39;', + '\x3c': '\x26lt;', + '\x3e': '\x26gt;', + '\x09': '\x26#9;', + '\x0a': '\x26#10;', + '\x0b': '\x26#11;', + '\x0c': '\x26#12;', + '\x0d': '\x26#13;', + ' ': '\x26#32;', + '-': '\x26#45;', + '\/': '\x26#47;', + '\x3d': '\x26#61;', + '`': '\x26#96;', + '\x85': '\x26#133;', + '\xa0': '\x26#160;', + '\u2028': '\x26#8232;', + '\u2029': '\x26#8233;' +}; + +/** + * A function that can be used with String.replace.. + * @param {string} ch A single character matched by a compatible matcher. + * @return {string} A token in the output language. + * @private + */ +soy.esc.$$REPLACER_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_ = function(ch) { + return soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_[ch]; +}; + +/** + * Maps charcters to the escaped versions for the named escape directives. + * @type {Object.} + * @private + */ +soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_ = { + '\x00': '\\x00', + '\x08': '\\x08', + '\x09': '\\t', + '\x0a': '\\n', + '\x0b': '\\x0b', + '\x0c': '\\f', + '\x0d': '\\r', + '\x22': '\\x22', + '\x26': '\\x26', + '\x27': '\\x27', + '\/': '\\\/', + '\x3c': '\\x3c', + '\x3d': '\\x3d', + '\x3e': '\\x3e', + '\\': '\\\\', + '\x85': '\\x85', + '\u2028': '\\u2028', + '\u2029': '\\u2029', + '$': '\\x24', + '(': '\\x28', + ')': '\\x29', + '*': '\\x2a', + '+': '\\x2b', + ',': '\\x2c', + '-': '\\x2d', + '.': '\\x2e', + ':': '\\x3a', + '?': '\\x3f', + '[': '\\x5b', + ']': '\\x5d', + '^': '\\x5e', + '{': '\\x7b', + '|': '\\x7c', + '}': '\\x7d' +}; + +/** + * A function that can be used with String.replace.. + * @param {string} ch A single character matched by a compatible matcher. + * @return {string} A token in the output language. + * @private + */ +soy.esc.$$REPLACER_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_ = function(ch) { + return soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_[ch]; +}; + +/** + * Maps charcters to the escaped versions for the named escape directives. + * @type {Object.} + * @private + */ +soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_CSS_STRING_ = { + '\x00': '\\0 ', + '\x08': '\\8 ', + '\x09': '\\9 ', + '\x0a': '\\a ', + '\x0b': '\\b ', + '\x0c': '\\c ', + '\x0d': '\\d ', + '\x22': '\\22 ', + '\x26': '\\26 ', + '\x27': '\\27 ', + '(': '\\28 ', + ')': '\\29 ', + '*': '\\2a ', + '\/': '\\2f ', + ':': '\\3a ', + ';': '\\3b ', + '\x3c': '\\3c ', + '\x3d': '\\3d ', + '\x3e': '\\3e ', + '@': '\\40 ', + '\\': '\\5c ', + '{': '\\7b ', + '}': '\\7d ', + '\x85': '\\85 ', + '\xa0': '\\a0 ', + '\u2028': '\\2028 ', + '\u2029': '\\2029 ' +}; + +/** + * A function that can be used with String.replace.. + * @param {string} ch A single character matched by a compatible matcher. + * @return {string} A token in the output language. + * @private + */ +soy.esc.$$REPLACER_FOR_ESCAPE_CSS_STRING_ = function(ch) { + return soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_CSS_STRING_[ch]; +}; + +/** + * Maps charcters to the escaped versions for the named escape directives. + * @type {Object.} + * @private + */ +soy.esc.$$ESCAPE_MAP_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_ = { + '\x00': '%00', + '\x01': '%01', + '\x02': '%02', + '\x03': '%03', + '\x04': '%04', + '\x05': '%05', + '\x06': '%06', + '\x07': '%07', + '\x08': '%08', + '\x09': '%09', + '\x0a': '%0A', + '\x0b': '%0B', + '\x0c': '%0C', + '\x0d': '%0D', + '\x0e': '%0E', + '\x0f': '%0F', + '\x10': '%10', + '\x11': '%11', + '\x12': '%12', + '\x13': '%13', + '\x14': '%14', + '\x15': '%15', + '\x16': '%16', + '\x17': '%17', + '\x18': '%18', + '\x19': '%19', + '\x1a': '%1A', + '\x1b': '%1B', + '\x1c': '%1C', + '\x1d': '%1D', + '\x1e': '%1E', + '\x1f': '%1F', + ' ': '%20', + '\x22': '%22', + '\x27': '%27', + '(': '%28', + ')': '%29', + '\x3c': '%3C', + '\x3e': '%3E', + '\\': '%5C', + '{': '%7B', + '}': '%7D', + '\x7f': '%7F', + '\x85': '%C2%85', + '\xa0': '%C2%A0', + '\u2028': '%E2%80%A8', + '\u2029': '%E2%80%A9', + '\uff01': '%EF%BC%81', + '\uff03': '%EF%BC%83', + '\uff04': '%EF%BC%84', + '\uff06': '%EF%BC%86', + '\uff07': '%EF%BC%87', + '\uff08': '%EF%BC%88', + '\uff09': '%EF%BC%89', + '\uff0a': '%EF%BC%8A', + '\uff0b': '%EF%BC%8B', + '\uff0c': '%EF%BC%8C', + '\uff0f': '%EF%BC%8F', + '\uff1a': '%EF%BC%9A', + '\uff1b': '%EF%BC%9B', + '\uff1d': '%EF%BC%9D', + '\uff1f': '%EF%BC%9F', + '\uff20': '%EF%BC%A0', + '\uff3b': '%EF%BC%BB', + '\uff3d': '%EF%BC%BD' +}; + +/** + * A function that can be used with String.replace.. + * @param {string} ch A single character matched by a compatible matcher. + * @return {string} A token in the output language. + * @private + */ +soy.esc.$$REPLACER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_ = function(ch) { + return soy.esc.$$ESCAPE_MAP_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_[ch]; +}; + +/** + * Matches characters that need to be escaped for the named directives. + * @type RegExp + * @private + */ +soy.esc.$$MATCHER_FOR_ESCAPE_HTML_ = /[\x00\x22\x26\x27\x3c\x3e]/g; + +/** + * Matches characters that need to be escaped for the named directives. + * @type RegExp + * @private + */ +soy.esc.$$MATCHER_FOR_NORMALIZE_HTML_ = /[\x00\x22\x27\x3c\x3e]/g; + +/** + * Matches characters that need to be escaped for the named directives. + * @type RegExp + * @private + */ +soy.esc.$$MATCHER_FOR_ESCAPE_HTML_NOSPACE_ = /[\x00\x09-\x0d \x22\x26\x27\x2d\/\x3c-\x3e`\x85\xa0\u2028\u2029]/g; + +/** + * Matches characters that need to be escaped for the named directives. + * @type RegExp + * @private + */ +soy.esc.$$MATCHER_FOR_NORMALIZE_HTML_NOSPACE_ = /[\x00\x09-\x0d \x22\x27\x2d\/\x3c-\x3e`\x85\xa0\u2028\u2029]/g; + +/** + * Matches characters that need to be escaped for the named directives. + * @type RegExp + * @private + */ +soy.esc.$$MATCHER_FOR_ESCAPE_JS_STRING_ = /[\x00\x08-\x0d\x22\x26\x27\/\x3c-\x3e\\\x85\u2028\u2029]/g; + +/** + * Matches characters that need to be escaped for the named directives. + * @type RegExp + * @private + */ +soy.esc.$$MATCHER_FOR_ESCAPE_JS_REGEX_ = /[\x00\x08-\x0d\x22\x24\x26-\/\x3a\x3c-\x3f\x5b-\x5e\x7b-\x7d\x85\u2028\u2029]/g; + +/** + * Matches characters that need to be escaped for the named directives. + * @type RegExp + * @private + */ +soy.esc.$$MATCHER_FOR_ESCAPE_CSS_STRING_ = /[\x00\x08-\x0d\x22\x26-\x2a\/\x3a-\x3e@\\\x7b\x7d\x85\xa0\u2028\u2029]/g; + +/** + * Matches characters that need to be escaped for the named directives. + * @type RegExp + * @private + */ +soy.esc.$$MATCHER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_ = /[\x00- \x22\x27-\x29\x3c\x3e\\\x7b\x7d\x7f\x85\xa0\u2028\u2029\uff01\uff03\uff04\uff06-\uff0c\uff0f\uff1a\uff1b\uff1d\uff1f\uff20\uff3b\uff3d]/g; + +/** + * A pattern that vets values produced by the named directives. + * @type RegExp + * @private + */ +soy.esc.$$FILTER_FOR_FILTER_CSS_VALUE_ = /^(?!-*(?:expression|(?:moz-)?binding))(?:[.#]?-?(?:[_a-z0-9-]+)(?:-[_a-z0-9-]+)*-?|-?(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)(?:[a-z]{1,2}|%)?|!important|)$/i; + +/** + * A pattern that vets values produced by the named directives. + * @type RegExp + * @private + */ +soy.esc.$$FILTER_FOR_FILTER_NORMALIZE_URI_ = /^(?:(?:https?|mailto):|[^&:\/?#]*(?:[\/?#]|$))/i; + +/** + * A pattern that vets values produced by the named directives. + * @type RegExp + * @private + */ +soy.esc.$$FILTER_FOR_FILTER_HTML_ATTRIBUTES_ = /^(?!style|on|action|archive|background|cite|classid|codebase|data|dsync|href|longdesc|src|usemap)(?:[a-z0-9_$:-]*)$/i; + +/** + * A pattern that vets values produced by the named directives. + * @type RegExp + * @private + */ +soy.esc.$$FILTER_FOR_FILTER_HTML_ELEMENT_NAME_ = /^(?!script|style|title|textarea|xmp|no)[a-z0-9_$:-]*$/i; + +/** + * A helper for the Soy directive |escapeHtml + * @param {*} value Can be of any type but will be coerced to a string. + * @return {string} The escaped text. + */ +soy.esc.$$escapeHtmlHelper = function(value) { + var str = String(value); + return str.replace( + soy.esc.$$MATCHER_FOR_ESCAPE_HTML_, + soy.esc.$$REPLACER_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_); +}; + +/** + * A helper for the Soy directive |normalizeHtml + * @param {*} value Can be of any type but will be coerced to a string. + * @return {string} The escaped text. + */ +soy.esc.$$normalizeHtmlHelper = function(value) { + var str = String(value); + return str.replace( + soy.esc.$$MATCHER_FOR_NORMALIZE_HTML_, + soy.esc.$$REPLACER_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_); +}; + +/** + * A helper for the Soy directive |escapeHtmlNospace + * @param {*} value Can be of any type but will be coerced to a string. + * @return {string} The escaped text. + */ +soy.esc.$$escapeHtmlNospaceHelper = function(value) { + var str = String(value); + return str.replace( + soy.esc.$$MATCHER_FOR_ESCAPE_HTML_NOSPACE_, + soy.esc.$$REPLACER_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_); +}; + +/** + * A helper for the Soy directive |normalizeHtmlNospace + * @param {*} value Can be of any type but will be coerced to a string. + * @return {string} The escaped text. + */ +soy.esc.$$normalizeHtmlNospaceHelper = function(value) { + var str = String(value); + return str.replace( + soy.esc.$$MATCHER_FOR_NORMALIZE_HTML_NOSPACE_, + soy.esc.$$REPLACER_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_); +}; + +/** + * A helper for the Soy directive |escapeJsString + * @param {*} value Can be of any type but will be coerced to a string. + * @return {string} The escaped text. + */ +soy.esc.$$escapeJsStringHelper = function(value) { + var str = String(value); + return str.replace( + soy.esc.$$MATCHER_FOR_ESCAPE_JS_STRING_, + soy.esc.$$REPLACER_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_); +}; + +/** + * A helper for the Soy directive |escapeJsRegex + * @param {*} value Can be of any type but will be coerced to a string. + * @return {string} The escaped text. + */ +soy.esc.$$escapeJsRegexHelper = function(value) { + var str = String(value); + return str.replace( + soy.esc.$$MATCHER_FOR_ESCAPE_JS_REGEX_, + soy.esc.$$REPLACER_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_); +}; + +/** + * A helper for the Soy directive |escapeCssString + * @param {*} value Can be of any type but will be coerced to a string. + * @return {string} The escaped text. + */ +soy.esc.$$escapeCssStringHelper = function(value) { + var str = String(value); + return str.replace( + soy.esc.$$MATCHER_FOR_ESCAPE_CSS_STRING_, + soy.esc.$$REPLACER_FOR_ESCAPE_CSS_STRING_); +}; + +/** + * A helper for the Soy directive |filterCssValue + * @param {*} value Can be of any type but will be coerced to a string. + * @return {string} The escaped text. + */ +soy.esc.$$filterCssValueHelper = function(value) { + var str = String(value); + if (!soy.esc.$$FILTER_FOR_FILTER_CSS_VALUE_.test(str)) { + return 'zSoyz'; + } + return str; +}; + +/** + * A helper for the Soy directive |normalizeUri + * @param {*} value Can be of any type but will be coerced to a string. + * @return {string} The escaped text. + */ +soy.esc.$$normalizeUriHelper = function(value) { + var str = String(value); + return str.replace( + soy.esc.$$MATCHER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_, + soy.esc.$$REPLACER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_); +}; + +/** + * A helper for the Soy directive |filterNormalizeUri + * @param {*} value Can be of any type but will be coerced to a string. + * @return {string} The escaped text. + */ +soy.esc.$$filterNormalizeUriHelper = function(value) { + var str = String(value); + if (!soy.esc.$$FILTER_FOR_FILTER_NORMALIZE_URI_.test(str)) { + return '#zSoyz'; + } + return str.replace( + soy.esc.$$MATCHER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_, + soy.esc.$$REPLACER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_); +}; + +/** + * A helper for the Soy directive |filterHtmlAttributes + * @param {*} value Can be of any type but will be coerced to a string. + * @return {string} The escaped text. + */ +soy.esc.$$filterHtmlAttributesHelper = function(value) { + var str = String(value); + if (!soy.esc.$$FILTER_FOR_FILTER_HTML_ATTRIBUTES_.test(str)) { + return 'zSoyz'; + } + return str; +}; + +/** + * A helper for the Soy directive |filterHtmlElementName + * @param {*} value Can be of any type but will be coerced to a string. + * @return {string} The escaped text. + */ +soy.esc.$$filterHtmlElementNameHelper = function(value) { + var str = String(value); + if (!soy.esc.$$FILTER_FOR_FILTER_HTML_ELEMENT_NAME_.test(str)) { + return 'zSoyz'; + } + return str; +}; + +/** + * Matches all tags, HTML comments, and DOCTYPEs in tag soup HTML. + * By removing these, and replacing any '<' or '>' characters with + * entities we guarantee that the result can be embedded into a + * an attribute without introducing a tag boundary. + * + * @type {RegExp} + * @private + */ +soy.esc.$$HTML_TAG_REGEX_ = /<(?:!|\/?([a-zA-Z][a-zA-Z0-9:\-]*))(?:[^>'"]|"[^"]*"|'[^']*')*>/g; + +/** + * Matches all occurrences of '<'. + * + * @type {RegExp} + * @private + */ +soy.esc.$$LT_REGEX_ = /} + * @private + */ +soy.esc.$$SAFE_TAG_WHITELIST_ = {'b': 1, 'br': 1, 'em': 1, 'i': 1, 's': 1, 'sub': 1, 'sup': 1, 'u': 1}; + +// END GENERATED CODE diff --git a/apps/blockfactory/blocks.js b/apps/blockfactory/blocks.js new file mode 100644 index 000000000..b7873529e --- /dev/null +++ b/apps/blockfactory/blocks.js @@ -0,0 +1,684 @@ +/** + * Blockly Apps: Block Factory Blocks + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Blocks for Blockly's Block Factory application. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +Blockly.Blocks['factory_base'] = { + // Base of new block. + init: function() { + this.setColour(120); + this.appendDummyInput() + .appendTitle('name') + .appendTitle(new Blockly.FieldTextInput('math_foo'), 'NAME'); + this.appendStatementInput('INPUTS') + .setCheck('Input') + .appendTitle('inputs'); + var dropdown = new Blockly.FieldDropdown([ + ['external inputs', 'EXT'], + ['inline inputs', 'INT']]); + this.appendDummyInput() + .appendTitle(dropdown, 'INLINE'); + dropdown = new Blockly.FieldDropdown([ + ['no connections', 'NONE'], + ['left output', 'LEFT'], + ['top+bottom connections', 'BOTH'], + ['top connection', 'TOP'], + ['bottom connection', 'BOTTOM']], + function(option) { + var block = this.sourceBlock_; + var outputExists = block.getInput('OUTPUTTYPE'); + var topExists = block.getInput('TOPTYPE'); + var bottomExists = block.getInput('BOTTOMTYPE'); + if (option == 'LEFT') { + if (!outputExists) { + block.appendValueInput('OUTPUTTYPE') + .setCheck('Type') + .appendTitle('output type'); + block.moveInputBefore('OUTPUTTYPE', 'COLOUR'); + } + } else if (outputExists) { + block.removeInput('OUTPUTTYPE'); + } + if (option == 'TOP' || option == 'BOTH') { + if (!topExists) { + block.appendValueInput('TOPTYPE') + .setCheck('Type') + .appendTitle('top type'); + block.moveInputBefore('TOPTYPE', 'COLOUR'); + } + } else if (topExists) { + block.removeInput('TOPTYPE'); + } + if (option == 'BOTTOM' || option == 'BOTH') { + if (!bottomExists) { + block.appendValueInput('BOTTOMTYPE') + .setCheck('Type') + .appendTitle('bottom type'); + block.moveInputBefore('BOTTOMTYPE', 'COLOUR'); + } + } else if (bottomExists) { + block.removeInput('BOTTOMTYPE'); + } + }); + this.appendDummyInput() + .appendTitle(dropdown, 'CONNECTIONS'); + this.appendValueInput('COLOUR') + .setCheck('Colour') + .appendTitle('colour'); + /* + this.appendValueInput('TOOLTIP') + .setCheck('String') + .appendTitle('tooltip'); + this.appendValueInput('HELP') + .setCheck('String') + .appendTitle('help url'); + */ + this.setTooltip('Build a custom block by plugging\n' + + 'titles, inputs and other blocks here.'); + } +}; + +var ALIGNMENT_OPTIONS = + [['left', 'LEFT'], ['right', 'RIGHT'], ['centre', 'CENTRE']]; + +Blockly.Blocks['input_value'] = { + // Value input. + init: function() { + this.setColour(210); + this.appendDummyInput() + .appendTitle('value input') + .appendTitle(new Blockly.FieldTextInput('NAME'), 'INPUTNAME'); + this.appendStatementInput('TITLES') + .setCheck('Title') + .appendTitle('titles') + .appendTitle(new Blockly.FieldDropdown(ALIGNMENT_OPTIONS), 'ALIGN'); + this.appendValueInput('TYPE') + .setCheck('Type') + .setAlign(Blockly.ALIGN_RIGHT) + .appendTitle('type'); + this.setPreviousStatement(true, 'Input'); + this.setNextStatement(true, 'Input'); + this.setTooltip('A value socket for horizontal connections.'); + }, + onchange: function() { + if (!this.workspace) { + // Block has been deleted. + return; + } + inputNameCheck(this); + } +}; + +Blockly.Blocks['input_statement'] = { + // Statement input. + init: function() { + this.setColour(210); + this.appendDummyInput() + .appendTitle('statement input') + .appendTitle(new Blockly.FieldTextInput('NAME'), 'INPUTNAME'); + this.appendStatementInput('TITLES') + .setCheck('Title') + .appendTitle('titles') + .appendTitle(new Blockly.FieldDropdown(ALIGNMENT_OPTIONS), 'ALIGN'); + this.appendValueInput('TYPE') + .setCheck('Type') + .setAlign(Blockly.ALIGN_RIGHT) + .appendTitle('type'); + this.setPreviousStatement(true, 'Input'); + this.setNextStatement(true, 'Input'); + this.setTooltip('A statement socket for enclosed vertical stacks.'); + }, + onchange: function() { + if (!this.workspace) { + // Block has been deleted. + return; + } + inputNameCheck(this); + } +}; + +Blockly.Blocks['input_dummy'] = { + // Dummy input. + init: function() { + this.setColour(210); + this.appendDummyInput() + .appendTitle('dummy input'); + this.appendStatementInput('TITLES') + .setCheck('Title') + .appendTitle('titles') + .appendTitle(new Blockly.FieldDropdown(ALIGNMENT_OPTIONS), 'ALIGN'); + this.setPreviousStatement(true, 'Input'); + this.setNextStatement(true, 'Input'); + this.setTooltip('For adding titles on a separate\n' + + 'row with no connections.\n' + + 'Alignment options (left, right, centre)\n' + + 'apply only to multi-line titles.'); + } +}; + +Blockly.Blocks['title_static'] = { + // Text value. + init: function() { + this.setColour(160); + this.appendDummyInput() + .appendTitle('text') + .appendTitle(new Blockly.FieldTextInput(''), 'TEXT'); + this.setPreviousStatement(true, 'Title'); + this.setNextStatement(true, 'Title'); + this.setTooltip('Static text that serves as a label.'); + } +}; + +Blockly.Blocks['title_input'] = { + // Text input. + init: function() { + this.setColour(160); + this.appendDummyInput() + .appendTitle('text input') + .appendTitle(new Blockly.FieldTextInput('default'), 'TEXT') + .appendTitle(',') + .appendTitle(new Blockly.FieldTextInput('NAME'), 'TITLENAME'); + this.setPreviousStatement(true, 'Title'); + this.setNextStatement(true, 'Title'); + this.setTooltip('An input field for the user to enter text.'); + }, + onchange: function() { + if (!this.workspace) { + // Block has been deleted. + return; + } + titleNameCheck(this); + } +}; + +Blockly.Blocks['title_angle'] = { + // Angle input. + init: function() { + this.setColour(160); + this.appendDummyInput() + .appendTitle('angle input') + .appendTitle(new Blockly.FieldAngle('90'), 'ANGLE') + .appendTitle(',') + .appendTitle(new Blockly.FieldTextInput('NAME'), 'TITLENAME'); + this.setPreviousStatement(true, 'Title'); + this.setNextStatement(true, 'Title'); + this.setTooltip('An input field for the user to enter an angle.'); + }, + onchange: function() { + if (!this.workspace) { + // Block has been deleted. + return; + } + titleNameCheck(this); + } +}; + +Blockly.Blocks['title_dropdown'] = { + // Dropdown menu. + init: function() { + this.setColour(160); + this.appendDummyInput() + .appendTitle('dropdown') + .appendTitle(new Blockly.FieldTextInput('NAME'), 'TITLENAME'); + this.appendDummyInput('OPTION0') + .appendTitle(new Blockly.FieldTextInput('option'), 'USER0') + .appendTitle(',') + .appendTitle(new Blockly.FieldTextInput('OPTIONNAME'), 'CPU0'); + this.appendDummyInput('OPTION1') + .appendTitle(new Blockly.FieldTextInput('option'), 'USER1') + .appendTitle(',') + .appendTitle(new Blockly.FieldTextInput('OPTIONNAME'), 'CPU1'); + this.appendDummyInput('OPTION2') + .appendTitle(new Blockly.FieldTextInput('option'), 'USER2') + .appendTitle(',') + .appendTitle(new Blockly.FieldTextInput('OPTIONNAME'), 'CPU2'); + this.setPreviousStatement(true, 'Title'); + this.setNextStatement(true, 'Title'); + this.setMutator(new Blockly.Mutator(['title_dropdown_option'])); + this.setTooltip('Dropdown menu with a list of options.'); + this.optionCount_ = 3; + }, + mutationToDom: function(workspace) { + var container = document.createElement('mutation'); + container.setAttribute('options', this.optionCount_); + return container; + }, + domToMutation: function(container) { + for (var x = 0; x < this.optionCount_; x++) { + this.removeInput('OPTION' + x); + } + this.optionCount_ = parseInt(container.getAttribute('options'), 10); + for (var x = 0; x < this.optionCount_; x++) { + var input = this.appendDummyInput('OPTION' + x); + input.appendTitle(new Blockly.FieldTextInput('option'), 'USER' + x); + input.appendTitle(','); + input.appendTitle(new Blockly.FieldTextInput('OPTIONNAME'), 'CPU' + x); + } + }, + decompose: function(workspace) { + var containerBlock = new Blockly.Block(workspace, + 'title_dropdown_container'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var x = 0; x < this.optionCount_; x++) { + var optionBlock = new Blockly.Block(workspace, 'title_dropdown_option'); + optionBlock.initSvg(); + connection.connect(optionBlock.previousConnection); + connection = optionBlock.nextConnection; + } + return containerBlock; + }, + compose: function(containerBlock) { + // Disconnect all input blocks and remove all inputs. + for (var x = this.optionCount_ - 1; x >= 0; x--) { + this.removeInput('OPTION' + x); + } + this.optionCount_ = 0; + // Rebuild the block's inputs. + var optionBlock = containerBlock.getInputTargetBlock('STACK'); + while (optionBlock) { + this.appendDummyInput('OPTION' + this.optionCount_) + .appendTitle(new Blockly.FieldTextInput( + optionBlock.userData_ || 'option'), 'USER' + this.optionCount_) + .appendTitle(',') + .appendTitle(new Blockly.FieldTextInput( + optionBlock.cpuData_ || 'OPTIONNAME'), 'CPU' + this.optionCount_); + this.optionCount_++; + optionBlock = optionBlock.nextConnection && + optionBlock.nextConnection.targetBlock(); + } + }, + saveConnections: function(containerBlock) { + // Store names and values for each option. + var optionBlock = containerBlock.getInputTargetBlock('STACK'); + var x = 0; + while (optionBlock) { + optionBlock.userData_ = this.getTitleValue('USER' + x); + optionBlock.cpuData_ = this.getTitleValue('CPU' + x); + x++; + optionBlock = optionBlock.nextConnection && + optionBlock.nextConnection.targetBlock(); + } + }, + onchange: function() { + if (!this.workspace) { + // Block has been deleted. + return; + } + if (this.optionCount_ < 1) { + this.setWarningText('Drop down menu must\nhave at least one option.'); + } else { + titleNameCheck(this); + } + } +}; + +Blockly.Blocks['title_dropdown_container'] = { + // Container. + init: function() { + this.setColour(160); + this.appendDummyInput() + .appendTitle('add options'); + this.appendStatementInput('STACK'); + this.setTooltip('Add, remove, or reorder options\n' + + 'to reconfigure this dropdown menu.'); + this.contextMenu = false; + } +}; + +Blockly.Blocks['title_dropdown_option'] = { + // Add option. + init: function() { + this.setColour(160); + this.appendDummyInput() + .appendTitle('option'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip('Add a new option to the dropdown menu.'); + this.contextMenu = false; + } +}; + +Blockly.Blocks['title_checkbox'] = { + // Checkbox. + init: function() { + this.setColour(160); + this.appendDummyInput() + .appendTitle('checkbox') + .appendTitle(new Blockly.FieldCheckbox('TRUE'), 'CHECKED') + .appendTitle(',') + .appendTitle(new Blockly.FieldTextInput('NAME'), 'TITLENAME'); + this.setPreviousStatement(true, 'Title'); + this.setNextStatement(true, 'Title'); + this.setTooltip('Checkbox field.'); + }, + onchange: function() { + if (!this.workspace) { + // Block has been deleted. + return; + } + titleNameCheck(this); + } +}; + +Blockly.Blocks['title_colour'] = { + // Colour input. + init: function() { + this.setColour(160); + this.appendDummyInput() + .appendTitle('colour') + .appendTitle(new Blockly.FieldColour('#ff0000'), 'COLOUR') + .appendTitle(',') + .appendTitle(new Blockly.FieldTextInput('NAME'), 'TITLENAME'); + this.setPreviousStatement(true, 'Title'); + this.setNextStatement(true, 'Title'); + this.setTooltip('Colour input field.'); + }, + onchange: function() { + if (!this.workspace) { + // Block has been deleted. + return; + } + titleNameCheck(this); + } +}; + +Blockly.Blocks['title_variable'] = { + // Dropdown for variables. + init: function() { + this.setColour(160); + this.appendDummyInput() + .appendTitle('variable') + .appendTitle(new Blockly.FieldTextInput('item'), 'TEXT') + .appendTitle(',') + .appendTitle(new Blockly.FieldTextInput('NAME'), 'TITLENAME'); + this.setPreviousStatement(true, 'Title'); + this.setNextStatement(true, 'Title'); + this.setTooltip('Dropdown menu for variable names.'); + }, + onchange: function() { + if (!this.workspace) { + // Block has been deleted. + return; + } + titleNameCheck(this); + } +}; + +Blockly.Blocks['title_image'] = { + // Image. + init: function() { + this.setColour(160); + var src = 'http://www.gstatic.com/codesite/ph/images/star_on.gif'; + this.appendDummyInput() + .appendTitle('image') + .appendTitle(new Blockly.FieldTextInput(src), 'SRC'); + this.appendDummyInput() + .appendTitle('width') + .appendTitle(new Blockly.FieldTextInput('15'), 'WIDTH') + .appendTitle('height') + .appendTitle(new Blockly.FieldTextInput('15'), 'HEIGHT'); + this.setPreviousStatement(true, 'Title'); + this.setNextStatement(true, 'Title'); + this.setTooltip('Static image (JPEG, PNG, GIF, SVG, BMP).\n' + + 'Retains aspect ratio regardless of height and width.'); + } +}; + +Blockly.Blocks['type_group'] = { + // Group of types. + init: function() { + this.setColour(230); + this.appendValueInput('TYPE0') + .setCheck('Type') + .appendTitle('any of'); + this.appendValueInput('TYPE1') + .setCheck('Type'); + this.setOutput(true, 'Type'); + this.setMutator(new Blockly.Mutator(['type_group_item'])); + this.setTooltip('Allows more than one type to be accepted.'); + this.typeCount_ = 2; + }, + mutationToDom: function(workspace) { + var container = document.createElement('mutation'); + container.setAttribute('types', this.typeCount_); + return container; + }, + domToMutation: function(container) { + for (var x = 0; x < this.typeCount_; x++) { + this.removeInput('TYPE' + x); + } + this.typeCount_ = parseInt(container.getAttribute('types'), 10); + for (var x = 0; x < this.typeCount_; x++) { + var input = this.appendValueInput('TYPE' + x) + .setCheck('Type'); + if (x == 0) { + input.appendTitle('any of'); + } + } + }, + decompose: function(workspace) { + var containerBlock = new Blockly.Block(workspace, + 'type_group_container'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var x = 0; x < this.typeCount_; x++) { + var typeBlock = new Blockly.Block(workspace, 'type_group_item'); + typeBlock.initSvg(); + connection.connect(typeBlock.previousConnection); + connection = typeBlock.nextConnection; + } + return containerBlock; + }, + compose: function(containerBlock) { + // Disconnect all input blocks and remove all inputs. + for (var x = this.typeCount_ - 1; x >= 0; x--) { + this.removeInput('TYPE' + x); + } + this.typeCount_ = 0; + // Rebuild the block's inputs. + var typeBlock = containerBlock.getInputTargetBlock('STACK'); + while (typeBlock) { + var input = this.appendValueInput('TYPE' + this.typeCount_) + .setCheck('Type'); + if (this.typeCount_ == 0) { + input.appendTitle('any of'); + } + // Reconnect any child blocks. + if (typeBlock.valueConnection_) { + input.connection.connect(typeBlock.valueConnection_); + } + this.typeCount_++; + typeBlock = typeBlock.nextConnection && + typeBlock.nextConnection.targetBlock(); + } + }, + saveConnections: function(containerBlock) { + // Store a pointer to any connected child blocks. + var typeBlock = containerBlock.getInputTargetBlock('STACK'); + var x = 0; + while (typeBlock) { + var input = this.getInput('TYPE' + x); + typeBlock.valueConnection_ = input && input.connection.targetConnection; + x++; + typeBlock = typeBlock.nextConnection && + typeBlock.nextConnection.targetBlock(); + } + } +}; + +Blockly.Blocks['type_group_container'] = { + // Container. + init: function() { + this.setColour(230); + this.appendDummyInput() + .appendTitle('add types'); + this.appendStatementInput('STACK'); + this.setTooltip('Add, or remove allowed type.'); + this.contextMenu = false; + } +}; + +Blockly.Blocks['type_group_item'] = { + // Add type. + init: function() { + this.setColour(230); + this.appendDummyInput() + .appendTitle('type'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip('Add a new allowed type.'); + this.contextMenu = false; + } +}; + +Blockly.Blocks['type_null'] = { + // Null type. + valueType: 'null', + init: function() { + this.setColour(230); + this.appendDummyInput() + .appendTitle('any'); + this.setOutput(true, 'Type'); + this.setTooltip('Any type is allowed.'); + } +}; + +Blockly.Blocks['type_boolean'] = { + // Boolean type. + valueType: 'Boolean', + init: function() { + this.setColour(230); + this.appendDummyInput() + .appendTitle('boolean'); + this.setOutput(true, 'Type'); + this.setTooltip('Booleans (true/false) are allowed.'); + } +}; + +Blockly.Blocks['type_number'] = { + // Number type. + valueType: 'Number', + init: function() { + this.setColour(230); + this.appendDummyInput() + .appendTitle('number'); + this.setOutput(true, 'Type'); + this.setTooltip('Numbers (int/float) are allowed.'); + } +}; + +Blockly.Blocks['type_string'] = { + // String type. + valueType: 'String', + init: function() { + this.setColour(230); + this.appendDummyInput() + .appendTitle('string'); + this.setOutput(true, 'Type'); + this.setTooltip('Strings (text) are allowed.'); + } +}; + +Blockly.Blocks['type_list'] = { + // List type. + valueType: 'Array', + init: function() { + this.setColour(230); + this.appendDummyInput() + .appendTitle('list'); + this.setOutput(true, 'Type'); + this.setTooltip('Arrays (lists) are allowed.'); + } +}; + +Blockly.Blocks['type_other'] = { + // Other type. + init: function() { + this.setColour(230); + this.appendDummyInput() + .appendTitle('other') + .appendTitle(new Blockly.FieldTextInput(''), 'TYPE'); + this.setOutput(true, 'Type'); + this.setTooltip('Custom type to allow.'); + } +}; + +Blockly.Blocks['colour_hue'] = { + // Set the colour of the block. + init: function() { + this.appendDummyInput() + .appendTitle('hue:') + .appendTitle(new Blockly.FieldAngle('0', this.validator), 'HUE'); + this.setOutput(true, 'Colour'); + this.setTooltip('Paint the block with this colour.'); + }, + validator: function(text) { + // Update the current block's colour to match. + this.sourceBlock_.setColour(text); + } +}; + +/** + * Check to see if more than one title has this name. + * Highly inefficient (On^2), but n is small. + * @param {!Blockly.Block} referenceBlock Block to check. + */ +function titleNameCheck(referenceBlock) { + var name = referenceBlock.getTitleValue('TITLENAME').toLowerCase(); + var count = 0; + var blocks = referenceBlock.workspace.getAllBlocks(); + for (var x = 0, block; block = blocks[x]; x++) { + var otherName = block.getTitleValue('TITLENAME'); + if (otherName) { + if (otherName.toLowerCase() == name) { + count++; + } + } + } + var msg = (count > 1) ? + 'There are ' + count + ' title blocks\n with this name.' : null; + referenceBlock.setWarningText(msg); +} + +/** + * Check to see if more than one input has this name. + * Highly inefficient (On^2), but n is small. + * @param {!Blockly.Block} referenceBlock Block to check. + */ +function inputNameCheck(referenceBlock) { + var name = referenceBlock.getTitleValue('INPUTNAME').toLowerCase(); + var count = 0; + var blocks = referenceBlock.workspace.getAllBlocks(); + for (var x = 0, block; block = blocks[x]; x++) { + var otherName = block.getTitleValue('INPUTNAME'); + if (otherName) { + if (otherName.toLowerCase() == name) { + count++; + } + } + } + var msg = (count > 1) ? + 'There are ' + count + ' input blocks\n with this name.' : null; + referenceBlock.setWarningText(msg); +} diff --git a/apps/blockfactory/factory.js b/apps/blockfactory/factory.js new file mode 100644 index 000000000..d32a5124a --- /dev/null +++ b/apps/blockfactory/factory.js @@ -0,0 +1,427 @@ +/** + * Blockly Apps: Block Factory + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview JavaScript for Blockly's Block Factory application. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +/** + * The uneditable container block that everything else attaches to. + * @type {Blockly.Block} + */ +var rootBlock = null; + +/** + * The type of the generated block. + */ +var blockType = ''; + +/** + * Initialize Blockly. Called on page load. + * @param {!Function} updateFunc Function to update the preview. + */ +function initPreview(updateFunc) { + updatePreview.updateFunc = updateFunc; + updatePreview(); +} + +/** + * When the workspace changes, update the three other displays. + */ +function onchange() { + var name = rootBlock.getTitleValue('NAME'); + blockType = name.replace(/\W/g, '_').replace(/^(\d)/, '_\\1').toLowerCase(); + if (!blockType) { + blockType = 'unnamed'; + } + updateLanguage(); + updateGenerator(); + updatePreview(); +} + +/** + * Update the language code. + */ +function updateLanguage() { + // Generate name. + var code = []; + code.push("Blockly.Blocks['" + blockType + "'] = {"); + code.push(" init: function() {"); + code.push(" this.setHelpUrl('http://www.example.com/');"); + // Generate colour. + var colourBlock = rootBlock.getInputTargetBlock('COLOUR'); + if (colourBlock) { + var hue = parseInt(colourBlock.getTitleValue('HUE'), 10); + code.push(' this.setColour(' + hue + ');'); + } + // Generate inputs. + var TYPES = {'input_value': 'appendValueInput', + 'input_statement': 'appendStatementInput', + 'input_dummy': 'appendDummyInput'}; + var inputVarDefined = false; + var contentsBlock = rootBlock.getInputTargetBlock('INPUTS'); + while (contentsBlock) { + var align = contentsBlock.getTitleValue('ALIGN'); + var titles = getTitles(contentsBlock.getInputTargetBlock('TITLES')); + var name = ''; + // Dummy inputs don't have names. Other inputs do. + if (contentsBlock.type != 'input_dummy') { + name = escapeString(contentsBlock.getTitleValue('INPUTNAME')); + } + var check = getOptTypesFrom(contentsBlock, 'TYPE'); + code.push(' this.' + TYPES[contentsBlock.type] + + '(' + name + ')'); + if (check && check != 'null') { + code.push(' .setCheck(' + check + ')'); + } + if (align != 'LEFT') { + code.push(' .setAlign(Blockly.ALIGN_' + align + ')'); + } + for (var x = 0; x < titles.length; x++) { + code.push(' .appendTitle(' + titles[x] + ')'); + } + // Add semicolon to last line to finish the statement. + code[code.length - 1] += ';'; + contentsBlock = contentsBlock.nextConnection && + contentsBlock.nextConnection.targetBlock(); + } + // Generate inline/external switch. + if (rootBlock.getTitleValue('INLINE') == 'INT') { + code.push(' this.setInputsInline(true);'); + } + // Generate output, or next/previous connections. + switch (rootBlock.getTitleValue('CONNECTIONS')) { + case 'LEFT': + code.push(connectionLine_('setOutput', 'OUTPUTTYPE')); + break; + case 'BOTH': + code.push(connectionLine_('setPreviousStatement', 'TOPTYPE')); + code.push(connectionLine_('setNextStatement', 'BOTTOMTYPE')); + break; + case 'TOP': + code.push(connectionLine_('setPreviousStatement', 'TOPTYPE')); + break; + case 'BOTTOM': + code.push(connectionLine_('setNextStatement', 'BOTTOMTYPE')); + break; + } + code.push(" this.setTooltip('');"); + code.push(" }"); + code.push("};"); + + injectCode(code, 'languagePre'); +} + +/** + * Create JS code required to create a top, bottom, or value connection. + * @param {string} functionName JavaScript function name. + * @param {string} typeName Name of type input. + * @return {string} Line of JavaScript code to create connection. + * @private + */ +function connectionLine_(functionName, typeName) { + var type = getOptTypesFrom(rootBlock, typeName); + if (type) { + type = ', ' + type; + } + return ' this.' + functionName + '(true' + type + ');'; +} + +/** + * Returns a title string and any config. + * @param {!Blockly.Block} block Title block. + * @return {string} Title string. + */ +function getTitles(block) { + var titles = []; + while (block) { + switch (block.type) { + case 'title_static': + // Result: 'hello' + titles.push(escapeString(block.getTitleValue('TEXT'))); + break; + case 'title_input': + // Result: new Blockly.FieldTextInput('Hello'), 'GREET' + titles.push('new Blockly.FieldTextInput(' + + escapeString(block.getTitleValue('TEXT')) + '), ' + + escapeString(block.getTitleValue('TITLENAME'))); + break; + case 'title_angle': + // Result: new Blockly.FieldAngle(90), 'ANGLE' + titles.push('new Blockly.FieldAngle(' + + escapeString(block.getTitleValue('ANGLE')) + '), ' + + escapeString(block.getTitleValue('TITLENAME'))); + break; + case 'title_checkbox': + // Result: new Blockly.FieldCheckbox('TRUE'), 'CHECK' + titles.push('new Blockly.FieldCheckbox(' + + escapeString(block.getTitleValue('CHECKED')) + '), ' + + escapeString(block.getTitleValue('TITLENAME'))); + break; + case 'title_colour': + // Result: new Blockly.FieldColour('#ff0000'), 'COLOUR' + titles.push('new Blockly.FieldColour(' + + escapeString(block.getTitleValue('COLOUR')) + '), ' + + escapeString(block.getTitleValue('TITLENAME'))); + break; + case 'title_variable': + // Result: + // new Blockly.FieldVariable('item'), 'VAR' + var varname = block.getTitleValue('TEXT'); + varname = varname ? escapeString(varname) : 'null'; + titles.push('new Blockly.FieldVariable(' + varname + '), ' + + escapeString(block.getTitleValue('TITLENAME'))); + break; + case 'title_dropdown': + // Result: + // new Blockly.FieldDropdown([['yes', '1'], ['no', '0']]), 'TOGGLE' + var options = []; + for (var x = 0; x < block.optionCount_; x++) { + options[x] = '[' + escapeString(block.getTitleValue('USER' + x)) + + ', ' + escapeString(block.getTitleValue('CPU' + x)) + ']'; + } + if (options.length) { + titles.push('new Blockly.FieldDropdown([' + + options.join(', ') + ']), ' + + escapeString(block.getTitleValue('TITLENAME'))); + } + break; + case 'title_image': + // Result: new Blockly.FieldImage('http://...', 80, 60) + var src = escapeString(block.getTitleValue('SRC')); + var width = Number(block.getTitleValue('WIDTH')); + var height = Number(block.getTitleValue('HEIGHT')); + titles.push('new Blockly.FieldImage(' + + src + ', ' + width + ', ' + height + ')'); + break; + } + block = block.nextConnection && block.nextConnection.targetBlock(); + } + return titles; +} + +/** + * Escape a string. + * @param {string} string String to escape. + * @return {string} Escaped string surrouned by quotes. + */ +function escapeString(string) { + if (JSON && JSON.stringify) { + return JSON.stringify(string); + } + // Hello MSIE 8. + return '"' + string.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"'; +} + +/** + * Fetch the type(s) defined in the given input. + * Format as a string for appending to the generated code. + * @param {!Blockly.Block} block Block with input. + * @param {string} name Name of the input. + * @return {string} String defining the types. + */ +function getOptTypesFrom(block, name) { + var types = getTypesFrom_(block, name); + if (types.length == 0) { + return ''; + } else if (types.length == 1) { + return types[0]; + } else if (types.indexOf('null') != -1) { + return 'null'; + } else { + return '[' + types.join(', ') + ']'; + } +} + +/** + * Fetch the type(s) defined in the given input. + * @param {!Blockly.Block} block Block with input. + * @param {string} name Name of the input. + * @return {!Array.} List of types. + * @private + */ +function getTypesFrom_(block, name) { + var typeBlock = block.getInputTargetBlock(name); + var types; + if (!typeBlock) { + types = []; + } else if (typeBlock.type == 'type_other') { + types = [escapeString(typeBlock.getTitleValue('TYPE'))]; + } else if (typeBlock.type == 'type_group') { + types = []; + for (var n = 0; n < typeBlock.typeCount_; n++) { + types = types.concat(getTypesFrom_(typeBlock, 'TYPE' + n)); + } + // Remove duplicates. + var hash = Object.create(null); + for (var n = types.length - 1; n >= 0; n--) { + if (hash[types[n]]) { + types.splice(n, 1); + } + hash[types[n]] = true; + } + } else { + types = [escapeString(typeBlock.valueType)]; + } + return types; +} + +/** + * Update the generator code. + */ +function updateGenerator() { + function makeVar(root, name) { + name = name.toLowerCase().replace(/\W/g, '_'); + return ' var ' + root + '_' + name; + } + var language = document.getElementById('language').value; + var code = []; + code.push("Blockly." + language + "['" + blockType + "'] = function(block) {"); + // Loop through every block, and generate getters for any fields or inputs. + var blocks = rootBlock.getDescendants(); + for (var x = 0, block; block = blocks[x]; x++) { + switch (block.type) { + case 'title_input': + var name = block.getTitleValue('TITLENAME'); + code.push(makeVar('text', name) + + " = block.getTitleValue('" + name + "');"); + break; + case 'title_angle': + var name = block.getTitleValue('TITLENAME'); + code.push(makeVar('angle', name) + + " = block.getTitleValue('" + name + "');"); + break; + case 'title_dropdown': + var name = block.getTitleValue('TITLENAME'); + code.push(makeVar('dropdown', name) + + " = block.getTitleValue('" + name + "');"); + break; + case 'title_checkbox': + var name = block.getTitleValue('TITLENAME'); + code.push(makeVar('checkbox', name) + + " = block.getTitleValue('" + name + "') == 'TRUE';"); + break; + case 'title_colour': + var name = block.getTitleValue('TITLENAME'); + code.push(makeVar('colour', name) + + " = block.getTitleValue('" + name + "');"); + break; + case 'title_variable': + var name = block.getTitleValue('TITLENAME'); + code.push(makeVar('variable', name) + + " = Blockly." + language + + ".variableDB_.getName(block.getTitleValue('" + name + + "'), Blockly.Variables.NAME_TYPE);"); + break; + case 'input_value': + var name = block.getTitleValue('INPUTNAME'); + code.push(makeVar('value', name) + + " = Blockly." + language + ".valueToCode(block, '" + name + + "', Blockly." + language + ".ORDER_ATOMIC);"); + break; + case 'input_statement': + var name = block.getTitleValue('INPUTNAME'); + code.push(makeVar('statements', name) + + " = Blockly.' + language + '.statementToCode(block, '" + + name + "');"); + break; + } + } + code.push(" // TODO: Assemble ' + language + ' into code variable."); + code.push(" var code = \'...\';"); + if (rootBlock.getTitleValue('CONNECTIONS') == 'LEFT') { + code.push(" // TODO: Change ORDER_NONE to the correct strength."); + code.push(" return [code, Blockly.' + language + '.ORDER_NONE];"); + } else { + code.push(" return code;"); + } + code.push("};"); + + injectCode(code, 'generatorPre'); +} + +var oldDir = 'ltr'; + +/** + * Update the preview display. + */ +function updatePreview() { + var newDir = document.getElementById('direction').value; + if (oldDir != newDir) { + document.getElementById('previewFrame').src = 'preview.html?' + newDir; + oldDir = newDir; + } else if (updatePreview.updateFunc) { + var code = document.getElementById('languagePre').textContent; + updatePreview.updateFunc(blockType, code); + } +} + +/** + * Inject code into a pre tag, with syntax highlighting. + * Safe from HTML/script injection. + * @param {!Array.} code Array of lines of code. + * @param {string} id ID of
     element to inject into.
    + */
    +function injectCode(code, id) {
    +  var pre = document.getElementById(id);
    +  pre.textContent = code.join('\n');
    +  code = pre.innerHTML;
    +  code = prettyPrintOne(code, 'js');
    +  pre.innerHTML = code;
    +}
    +
    +/**
    + * Initialize Blockly and layout.  Called on page load.
    + */
    +function init() {
    +  var expandList = [
    +    document.getElementById('blockly'),
    +    document.getElementById('previewFrame'),
    +    document.getElementById('languagePre'),
    +    document.getElementById('generatorPre')
    +  ];
    +  var onresize = function(e) {
    +    for (var i = 0, expand; expand = expandList[i]; i++) {
    +      expand.style.width = (expand.parentNode.offsetWidth - 2) + 'px';
    +      expand.style.height = (expand.parentNode.offsetHeight - 2) + 'px';
    +    }
    +  };
    +  onresize();
    +  window.addEventListener('resize', onresize);
    +
    +  var toolbox = document.getElementById('toolbox');
    +  Blockly.inject(document.getElementById('blockly'),
    +                 {path: '../../', toolbox: toolbox});
    +
    +  // Create the root block.
    +  rootBlock = new Blockly.Block(Blockly.mainWorkspace, 'factory_base');
    +  rootBlock.initSvg();
    +  rootBlock.render();
    +  rootBlock.setMovable(false);
    +  rootBlock.setDeletable(false);
    +
    +  Blockly.addChangeListener(onchange);
    +  document.getElementById('direction')
    +      .addEventListener('change', updatePreview);
    +  document.getElementById('language')
    +      .addEventListener('change', updateGenerator);
    +}
    +window.addEventListener('load', init);
    diff --git a/apps/blockfactory/index.html b/apps/blockfactory/index.html
    new file mode 100644
    index 000000000..42aaf5371
    --- /dev/null
    +++ b/apps/blockfactory/index.html
    @@ -0,0 +1,152 @@
    +
    +
    +
    +  
    +  
    +  Blockly : Block Factory
    +  
    +  
    +  
    +  
    +  
    +  
    +  
    +
    +
    +  
    +    
    +      
    +      
    +    
    +    
    +      
    +      
    +    
    +  
    +

    Blockly : Block Factory

    +
    +

    Preview: + +

    +
    +
    +
    + + + + + + + + + + + + + + + + +
    + +
    +

    Language code:

    +
    +
    
    +            
    +

    Generator stub: + +

    +
    +
    
    +            
    +
    + + + diff --git a/apps/blockfactory/preview.html b/apps/blockfactory/preview.html new file mode 100644 index 000000000..1f1c447d0 --- /dev/null +++ b/apps/blockfactory/preview.html @@ -0,0 +1,26 @@ + + + + + + Block Factory Preview + + + + + + + + diff --git a/apps/blockfactory/preview.js b/apps/blockfactory/preview.js new file mode 100644 index 000000000..1aed69263 --- /dev/null +++ b/apps/blockfactory/preview.js @@ -0,0 +1,76 @@ +/** + * Blockly Apps: Block Factory + * + * Copyright 2013 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview JavaScript for Blockly's Block Factory preview. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +/** + * The uneditable preview block. + * @type {Blockly.Block} + */ +var previewBlock = null; + +/** + * Create the specified block in this preview pane. + * @param {string} type Name of block. + * @param {string} code JavaScript code to create a block. + */ +function updateFunc(type, code) { + if (previewBlock) { + previewBlock.dispose(); + previewBlock = null; + } + eval(code); + // Create the preview block. + previewBlock = new Blockly.Block(Blockly.mainWorkspace, type); + previewBlock.initSvg(); + previewBlock.render(); + previewBlock.setMovable(false); + previewBlock.setDeletable(false); +} + +/** + * Initialize Blockly. Called on page load. + */ +function init() { + var rtl = (document.location.search == '?rtl'); + Blockly.inject(document.body, {path: '../../', rtl: rtl}); + + if (window.parent.initPreview) { + // Let the top-level application know that Blockly is ready. + window.parent.initPreview(updateFunc); + } else { + // Attempt to diagnose the problem. + var msg = 'Error: Unable to communicate between frames.\n' + + 'The preview frame will not be functional.\n\n'; + if (window.parent == window) { + msg += 'Try loading index.html instead of preview.html'; + } else if (window.location.protocol == 'file:') { + msg += 'This may be due to a security restriction preventing\n' + + 'access when using the file:// protocol.\n' + + 'http://code.google.com/p/chromium/issues/detail?id=47416'; + } + alert(msg); + } +} + +window.addEventListener('load', init); diff --git a/apps/code/code.js b/apps/code/code.js new file mode 100644 index 000000000..b2d680d55 --- /dev/null +++ b/apps/code/code.js @@ -0,0 +1,220 @@ +/** + * Blockly Apps: Code + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview JavaScript for Blockly's Code application. + * @author fraser@google.com (Neil Fraser) + */ + +// Supported languages. +BlocklyApps.LANGUAGES = ['en', 'de', 'fa', 'hu', 'it', 'ru', 'uk', 'vi', 'zh-tw']; +BlocklyApps.LANG = BlocklyApps.getLang(); + +document.write('\n'); + +/** + * Create a namespace for the application. + */ +var Code = {}; + +/** + * List of tab names. + * @private + */ +Code.TABS_ = ['blocks', 'javascript', 'python', 'xml']; + +Code.selected = 'blocks'; + +/** + * Switch the visible pane when a tab is clicked. + * @param {string} clickedName Name of tab clicked. + */ +Code.tabClick = function(clickedName) { + // If the XML tab was open, save and render the content. + if (document.getElementById('tab_xml').className == 'tabon') { + var xmlTextarea = document.getElementById('content_xml'); + var xmlText = xmlTextarea.value; + var xmlDom = null; + try { + xmlDom = Blockly.Xml.textToDom(xmlText); + } catch (e) { + var q = + window.confirm(BlocklyApps.getMsg('Code_badXml').replace('%1', e)); + if (!q) { + // Leave the user on the XML tab. + return; + } + } + if (xmlDom) { + Blockly.mainWorkspace.clear(); + Blockly.Xml.domToWorkspace(Blockly.mainWorkspace, xmlDom); + } + } + + // Deselect all tabs and hide all panes. + for (var i = 0; i < Code.TABS_.length; i++) { + var name = Code.TABS_[i]; + document.getElementById('tab_' + name).className = 'taboff'; + document.getElementById('content_' + name).style.visibility = 'hidden'; + } + + // Select the active tab. + Code.selected = clickedName; + document.getElementById('tab_' + clickedName).className = 'tabon'; + // Show the selected pane. + document.getElementById('content_' + clickedName).style.visibility = + 'visible'; + Code.renderContent(); + Blockly.fireUiEvent(window, 'resize'); +}; + +/** + * Populate the currently selected pane with content generated from the blocks. + */ +Code.renderContent = function() { + var content = document.getElementById('content_' + Code.selected); + // Initialize the pane. + if (content.id == 'content_xml') { + var xmlTextarea = document.getElementById('content_xml'); + var xmlDom = Blockly.Xml.workspaceToDom(Blockly.mainWorkspace); + var xmlText = Blockly.Xml.domToPrettyText(xmlDom); + xmlTextarea.value = xmlText; + xmlTextarea.focus(); + } else if (content.id == 'content_javascript') { + var code = Blockly.JavaScript.workspaceToCode(); + content.textContent = code; + if (typeof prettyPrintOne == 'function') { + code = content.innerHTML; + code = prettyPrintOne(code, 'js'); + content.innerHTML = code; + } + } else if (content.id == 'content_python') { + code = Blockly.Python.workspaceToCode(); + content.textContent = code; + if (typeof prettyPrintOne == 'function') { + code = content.innerHTML; + code = prettyPrintOne(code, 'py'); + content.innerHTML = code; + } + } +}; + +/** + * Initialize Blockly. Called on page load. + */ +Code.init = function() { + BlocklyApps.init(); + + var rtl = BlocklyApps.isRtl(); + var toolbox = document.getElementById('toolbox'); + Blockly.inject(document.getElementById('content_blocks'), + {path: '../../', + rtl: rtl, + toolbox: toolbox}); + + // Add to reserved word list: Local variables in execution evironment (runJS) + // and the infinite loop detection function. + Blockly.JavaScript.addReservedWords('code,timeouts,checkTimeout'); + + var container = document.getElementById('content_area'); + var onresize = function(e) { + var bBox = BlocklyApps.getBBox_(container); + for (var i = 0; i < Code.TABS_.length; i++) { + var el = document.getElementById('content_' + Code.TABS_[i]); + el.style.top = bBox.y + 'px'; + el.style.left = bBox.x + 'px'; + // Height and width need to be set, read back, then set again to + // compensate for scrollbars. + el.style.height = bBox.height + 'px'; + el.style.height = (2 * bBox.height - el.offsetHeight) + 'px'; + el.style.width = bBox.width + 'px'; + el.style.width = (2 * bBox.width - el.offsetWidth) + 'px'; + } + // Make the 'Blocks' tab line up with the toolbox. + if (Blockly.Toolbox.width) { + document.getElementById('tab_blocks').style.minWidth = + (Blockly.Toolbox.width - 38) + 'px'; + // Account for the 19 pixel margin and on each side. + } + }; + window.addEventListener('resize', onresize, false); + + BlocklyApps.loadBlocks(''); + + if ('BlocklyStorage' in window) { + // Hook a save function onto unload. + BlocklyStorage.backupOnUnload(); + } + + Code.tabClick(Code.selected); + Blockly.fireUiEvent(window, 'resize'); + + BlocklyApps.bindClick('trashButton', + function() {Code.discard(); Code.renderContent();}); + BlocklyApps.bindClick('runButton', Code.runJS); + + for (var i = 0; i < Code.TABS_.length; i++) { + var name = Code.TABS_[i]; + BlocklyApps.bindClick('tab_' + name, + function(name_) {return function() {Code.tabClick(name_);};}(name)); + } + + // Lazy-load the syntax-highlighting. + window.setTimeout(BlocklyApps.importPrettify, 1); +}; + +if (window.location.pathname.match(/readonly.html$/)) { + window.addEventListener('load', BlocklyApps.initReadonly); +} else { + window.addEventListener('load', Code.init); +} + +/** + * Execute the user's code. + * Just a quick and dirty eval. Catch infinite loops. + */ +Code.runJS = function() { + Blockly.JavaScript.INFINITE_LOOP_TRAP = ' checkTimeout();\n'; + var timeouts = 0; + var checkTimeout = function() { + if (timeouts++ > 1000000) { + throw BlocklyApps.getMsg('Code_timeout'); + } + }; + var code = Blockly.JavaScript.workspaceToCode(); + Blockly.JavaScript.INFINITE_LOOP_TRAP = null; + try { + eval(code); + } catch (e) { + alert(BlocklyApps.getMsg('Code_badCode').replace('%1', e)); + } +}; + +/** + * Discard all blocks from the workspace. + */ +Code.discard = function() { + var count = Blockly.mainWorkspace.getAllBlocks().length; + if (count < 2 || + window.confirm(BlocklyApps.getMsg('Code_discard').replace('%1', count))) { + Blockly.mainWorkspace.clear(); + window.location.hash = ''; + } +}; diff --git a/apps/code/generated/af.js b/apps/code/generated/af.js new file mode 100644 index 000000000..95e0f2655 --- /dev/null +++ b/apps/code/generated/af.js @@ -0,0 +1,55 @@ +// This file was automatically generated from common.soy. +// Please don't edit this file by hand. + +if (typeof apps == 'undefined') { var apps = {}; } + + +apps.messages = function(opt_data, opt_ignored, opt_ijData) { + return '
    a visual programming environmentBlocklySee generated JavaScript code.Save and link to blocks.Run the program defined by the blocks in the workspace.Run ProgramResetOKCancelLogicLoopsMathTextListsColourVariablesProceduresThere was a problem with the request.Share your blocks with this link:\\n\\n%1Sorry, \'%1\' doesn\'t correspond with any saved program.Could not load your saved file. Perhaps it was created with a different version of Blockly?listtext
    '; +}; + + +apps.dialog = function(opt_data, opt_ignored, opt_ijData) { + return '
    '; +}; + + +apps.codeDialog = function(opt_data, opt_ignored, opt_ijData) { + return '
    ' + apps.ok(null, null, opt_ijData) + '
    '; +}; + + +apps.storageDialog = function(opt_data, opt_ignored, opt_ijData) { + return '
    ' + apps.ok(null, null, opt_ijData) + '
    '; +}; + + +apps.ok = function(opt_data, opt_ignored, opt_ijData) { + return '
    '; +}; + +; +// This file was automatically generated from template.soy. +// Please don't edit this file by hand. + +if (typeof codepage == 'undefined') { var codepage = {}; } + + +codepage.messages = function(opt_data, opt_ignored, opt_ijData) { + return apps.messages(null, null, opt_ijData) + '
    Error parsing XML:\\n%1\\n\\nSelect \'OK\' to abandon your changes or \'Cancel\' to further edit the XML.Program error:\\n%1Maximum execution iterations exceeded.Delete all %1 blocks?
    '; +}; + + +codepage.start = function(opt_data, opt_ignored, opt_ijData) { + return codepage.messages(null, null, opt_ijData) + ' + + + + + + + + diff --git a/apps/code/readonly.html b/apps/code/readonly.html new file mode 100644 index 000000000..40bd9d61c --- /dev/null +++ b/apps/code/readonly.html @@ -0,0 +1,36 @@ + + + + + + Blockly : Code Readonly + + + + + + + + + diff --git a/apps/code/style.css b/apps/code/style.css new file mode 100644 index 000000000..dfd1a09e4 --- /dev/null +++ b/apps/code/style.css @@ -0,0 +1,105 @@ +html, body { + height: 100%; +} +body { + margin: 0; + overflow: hidden; +} +h1 { + margin-left: 5px; + margin-right: 5px; +} + +/* Tabs */ +#tabRow>td { + border: 1px solid #ccc; +} +td.tabon { + border-bottom-color: #ddd !important; + background-color: #ddd; + padding: 5px 19px; +} +td.taboff { + cursor: pointer; + padding: 5px 19px; +} +td.taboff:hover { + background-color: #eee; +} +td.tabmin { + border-top-style: none !important; + border-left-style: none !important; + border-right-style: none !important; +} +td.tabmax { + border-top-style: none !important; + border-left-style: none !important; + border-right-style: none !important; + width: 99%; + padding-left: 10px; + padding-right: 10px; + text-align: right; +} +html[dir=rtl] td.tabmax { + text-align: left; +} + +table { + border-collapse: collapse; + margin: 0; + padding: 0; + border: none; +} +td { + padding: 0; + vertical-align: top; +} +.content { + visibility: hidden; + margin: 0; + padding: 1ex; + position: absolute; +} +pre.content { + overflow: scroll; +} +#content_blocks { + padding: 0; +} +.blocklySvg { + border-top: none !important; +} +#content_xml { + resize: none; + outline: none; + border: none; + font-family: monospace; + overflow: scroll; +} +#languageMenu { + vertical-align: top; + margin-top: 15px; + margin-right: 15px; +} + +/* Buttons */ +button { + padding: 1px 10px; + margin: 1px 5px; +} + +/* Sprited icons. */ +.icon21 { + height: 21px; + width: 21px; + background-image: url(icons.png); +} +.trash { + background-position: 0px 0px; +} +.link { + background-position: -21px 0px; +} +.run { + background-position: -42px 0px; +} diff --git a/apps/code/template.soy b/apps/code/template.soy new file mode 100644 index 000000000..8897f85fd --- /dev/null +++ b/apps/code/template.soy @@ -0,0 +1,276 @@ +{namespace codepage} + +/** + * This is a Closure Template. + * + * To regenerate just en.js, run this command: + * java -jar ../_soy/SoyToJsSrcCompiler.jar --outputPathFormat generated/en.js --srcs ../common.soy,template.soy + * + * To regenerate all files, see: trunk/apps/template.soy. + */ + +/** + * Translated messages for use in JavaScript. + */ +{template .messages} + {call apps.messages /} +
    + {msg meaning="Code.badXml" desc="alert - Message shown when the user tries switching from the XML tab after entering XML text that could not be parsed. This asks whether they wish to abandon the XML they added. If they select 'OK' (or the translated equivalent), the XML is cleared, and the other tab is shown. If they select 'Cancel', they remain on the XML tab with the bad XML.\n\nUsed in JavaScript \u003Ccode\u003Ewindow.confirm()\u003C/code\u003E."}Error parsing XML:\n%1\n\nSelect 'OK' to abandon your changes or 'Cancel' to further edit the XML.{/msg} + {msg meaning="Code.badCode" desc="alert - Message shown if an error occurs while interpreting the user program. The error description follows."}Program error:\n%1{/msg} + {msg meaning="Code.timeout" desc="alert - Message shown if the program has run for more than the permitted number of steps. This exists so that programs with infinite loops do not run forever."}Maximum execution iterations exceeded.{/msg} + {msg meaning="Code.discard" desc="alert - Message shown after the user clicks on the 'discard all' icon. Selecting 'OK' (or the translated equivalent) causes all of the blocks to be discarded. Selecting 'Cancel' prevents blocks from being deleted.\n\nParameters:\n* %1 - number of blocks to be deleted. It is always an integer greater than or equal to 2."}Delete all %1 blocks?{/msg} +
    +{/template} + +/** + * Web page structure. + */ +{template .start} + {call .messages /} + + + + + + + + + + + + + + + + +
    +

    + + {msg meaning="Apps.blocklyMessage" desc="IBID"}Blockly{/msg} + {sp}:{sp} + {msg meaning="Code.title" desc="title - Title of this application, indicating that it is for writing arbitrary programs."} + Code + {/msg} + +

    +
    + +
    + + + + + + + + + + + +
    {msg meaning="Code.blocks" desc="tab text - Displays and allows editing of the user's program as blocks."}Blocks{/msg} JavaScript Python XML + {sp} + {sp} + +
    +
    + {call .toolbox /} +
    +
    +
    
    +  
    
    +  
    +  {call apps.dialog /}
    +  {call apps.storageDialog /}
    +{/template}
    +
    +/**
    + * Toolbox.
    + */
    +{template .toolbox}
    +  
    +{/template}
    +
    +/**
    + * Readonly Blockly in an iframe.
    + */
    +{template .readonly}
    +  {call .messages /}
    +
    +  
    +  
    +  
    +  
    +{/template} diff --git a/apps/common.css b/apps/common.css new file mode 100644 index 000000000..ce57787a7 --- /dev/null +++ b/apps/common.css @@ -0,0 +1,119 @@ +body { + background-color: #fff; + font-family: sans-serif; + margin-top: 0; +} +h1 { + font-weight: normal; + font-size: 140%; +} +a:hover { + color: #f00; +} +.farSide { + text-align: right; +} +html[dir="RTL"] .farSide { + text-align: left; +} + +/* Buttons */ +button { + margin: 5px; + padding: 10px; + border-radius: 4px; + border: 1px solid #ddd; + font-size: large; + background-color: #eee; + color: #000; +} +button.primary { + border: 1px solid #dd4b39; + background-color: #dd4b39; + color: #fff; +} +button.secondary { + border: 1px solid #4d90fe; + background-color: #4d90fe; + color: #fff; +} +button.primary>img, +button.secondary>img { + opacity: 1; +} +button>img { + opacity: 0.6; + vertical-align: text-bottom; +} +button:hover>img { + opacity: 1; +} +button:active { + border: 1px solid #888 !important; +} +button:hover { + box-shadow: 2px 2px 5px #888; +} +button.disabled:hover>img { + opacity: 0.6; +} +button.disabled { + display: none; +} +button.notext { + font-size: 10%; +} + +/* Dialogs */ +#dialog { + visibility: hidden; + background-color: #fff; + color: #000; + border: 1px solid #ccc; + position: absolute; + border-radius: 8px; + box-shadow: 5px 5px 5px #888; + padding: 10px; +} +#dialogBorder { + visibility: hidden; + position: absolute; + background-color: #fff; + color: #000; + border: 1px solid #000; + border-radius: 6px; + box-shadow: 5px 5px 5px #888; +} +#dialogShadow { + visibility: hidden; + position: fixed; + top: 0; + left: 0; + height: 100%; + width: 100%; + background-color: #000; + opacity: 0.3 +} +.dialogAnimate { + transition-property: width height left top opacity; + transition-duration: 0.2s; + transition-timing-function: linear; +} +.dialogHiddenContent { + visibility: hidden; + position: absolute; + top: 0; + left: 0; + z-index: -1; +} +#dialogHeader { + height: 25px; + margin: -10px -10px 15px; + border-top-left-radius: 8px; + border-top-right-radius: 8px; + background-color: #ddd; + cursor: move; +} +#dialog button { + min-width: 4em; +} diff --git a/apps/common.js b/apps/common.js new file mode 100644 index 000000000..183070d98 --- /dev/null +++ b/apps/common.js @@ -0,0 +1,834 @@ +/** + * Blockly Apps: Common code + * + * Copyright 2013 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Common support code for Blockly apps. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +var BlocklyApps = {}; + +/** + * Lookup for names of languages. Keys should be in ISO 639 format. + */ +BlocklyApps.LANGUAGE_NAME = { + 'af': 'Afrikaans', + 'ar': 'العربية', + 'be-tarask': 'Taraškievica', + 'br': 'Brezhoneg', + 'ca': 'Català', + 'cdo': '閩東語', + 'cs': 'Česky', + 'da': 'Dansk', + 'de': 'Deutsch', + 'el': 'Ελληνικά', + 'en': 'English', + 'es': 'Español', + 'eu': 'Euskara', + 'fa': 'فارسی', + 'fi': 'Suomi', + 'fo': 'Føroyskt', + 'fr': 'Français', + 'frr': 'Frasch', + 'gl': 'Galego', + 'hak': '客家話', + 'he': 'עברית', + 'hu': 'Magyar', + 'ia': 'Interlingua', + 'it': 'Italiano', + 'ja': '日本語', + 'ka': 'ქართული', + 'km': 'ភាសាខ្មែរ', + 'ko': '한국어', + 'ksh': 'Ripoarėsch', + 'ky': 'Кыргызча', + 'la': 'Latine', + 'lb': 'Lëtzebuergesch', + 'lt': 'Lietuvių', + 'lv': 'Latviešu', + 'ml': 'മലയാളം', + 'mk': 'Македонски', + 'mr': 'मराठी', + 'ms': 'Bahasa Melayu', + 'mzn': 'مازِرونی', + 'nb': 'Norsk Bokmål', + 'nl': 'Nederlands, Vlaams', + 'oc': 'Lenga d\'òc', + 'pa': 'पंजाबी', + 'pl': 'Polski', + 'pms': 'Piemontèis', + 'ps': 'پښتو', + 'pt': 'Português', + 'ro': 'Română', + 'pt-br': 'Português Brasileiro', + 'ru': 'Русский', + 'sk': 'Slovenčina', + 'sr': 'Српски', + 'sv': 'Svenska', + 'sw': 'Kishwahili', + 'th': 'ภาษาไทย', + 'tr': 'Türkçe', + 'uk': 'Українська', + 'vi': 'Tiếng Việt', + 'zh-hans': '简体字', + 'zh-hant': '中文', + 'zh-tw': '國語' +}; + +/** + * List of RTL languages. + */ +BlocklyApps.LANGUAGE_RTL = ['ar', 'fa', 'he', 'mzn', 'ps']; + +/** + * Lookup for Blockly core block language pack. + */ +BlocklyApps.LANGUAGE_PACK = { + 'cdo': 'msg/js/zh_tw.js', + 'de': 'msg/js/de.js', + 'fa': 'msg/js/fa.js', + 'frr': 'msg/js/de.js', + 'hu': 'msg/js/hu.js', + 'it': 'msg/js/it.js', + 'ksh': 'msg/js/de.js', + 'lb': 'msg/js/de.js', + 'pt': 'msg/js/pt_br.js', + 'pt-br': 'msg/js/pt_br.js', + 'ru': 'msg/js/ru.js', + 'uk': 'msg/js/uk.js', + 'vi': 'msg/js/vi.js', + 'zh-hans': 'msg/js/zh_tw.js', + 'zh-hant': 'msg/js/zh_tw.js', + 'zh-tw': 'msg/js/zh_tw.js', + 'default': 'msg/js/en.js' +}; + +/** + * User's language (e.g. "en"). + * @type string= + */ +BlocklyApps.LANG = undefined; + +/** + * List of languages supported by this app. Values should be in ISO 639 format. + * @type !Array.= + */ +BlocklyApps.LANGUAGES = undefined; + +/** + * Extracts a parameter from the URL. + * If the parameter is absent default_value is returned. + * @param {string} name The name of the parameter. + * @param {string} defaultValue Value to return if paramater not found. + * @return {string} The parameter value or the default value if not found. + */ +BlocklyApps.getStringParamFromUrl = function(name, defaultValue) { + var val = + window.location.search.match(new RegExp('[?&]' + name + '=([^&]+)')); + return val ? decodeURIComponent(val[1].replace(/\+/g, '%20')) : defaultValue; +}; + +/** + * Extracts a numeric parameter from the URL. + * If the parameter is absent or less than min_value, min_value is + * returned. If it is greater than max_value, max_value is returned. + * @param {string} name The name of the parameter. + * @param {number} minValue The minimum legal value. + * @param {number} maxValue The maximum legal value. + * @return {number} A number in the range [min_value, max_value]. + */ +BlocklyApps.getNumberParamFromUrl = function(name, minValue, maxValue) { + var val = Number(BlocklyApps.getStringParamFromUrl(name, 'NaN')); + return isNaN(val) ? minValue : Math.min(Math.max(minValue, val), maxValue); +}; + +/** + * Use a series of heuristics that determine the likely language of this user. + * Use a session cookie to load/save the language preference. + * @return {string} User's language. + * @throws {string} If no languages exist in this app. + */ +BlocklyApps.getLang = function() { + // First choice: The URL specified language. + var lang = BlocklyApps.getStringParamFromUrl('lang', ''); + if (BlocklyApps.LANGUAGES.indexOf(lang) != -1) { + // Save this explicit choice as cookie. + // Use of a session cookie for saving language is explicitly permitted + // in the EU's Cookie Consent Exemption policy. Section 3.6: + // http://ec.europa.eu/justice/data-protection/article-29/documentation/ + // opinion-recommendation/files/2012/wp194_en.pdf + document.cookie = 'lang=' + escape(lang) + '; path=/'; + return lang; + } + // Second choice: Language cookie. + var cookie = document.cookie.match(/(^|;)\s*lang=(\w+)/); + if (cookie) { + lang = unescape(cookie[2]); + if (BlocklyApps.LANGUAGES.indexOf(lang) != -1) { + return lang; + } + } + // Third choice: The browser's language. + lang = navigator.language; + if (BlocklyApps.LANGUAGES.indexOf(lang) != -1) { + return lang; + } + // Fourth choice: English. + lang = 'en'; + if (BlocklyApps.LANGUAGES.indexOf(lang) != -1) { + return lang; + } + // Fifth choice: I'm feeling lucky. + if (BlocklyApps.LANGUAGES.length) { + return BlocklyApps.LANGUAGES[0]; + } + // Sixth choice: Die. + throw 'No languages available.'; +}; + +/** + * Is the current language (BlocklyApps.LANG) an RTL language? + * @return {boolean} True if RTL, false if LTR. + */ +BlocklyApps.isRtl = function() { + return BlocklyApps.LANGUAGE_RTL.indexOf(BlocklyApps.LANG) != -1; +}; + +/** + * Look up the Blockly language pack for current language (BlocklyApps.LANG). + * @return {string} URL to langugae pack (e.g. 'msg/js/en.js'). + */ +BlocklyApps.languagePack = function() { + return BlocklyApps.LANGUAGE_PACK[BlocklyApps.LANG] || + BlocklyApps.LANGUAGE_PACK['default']; +}; + +/** + * Common startup tasks for all apps. + */ +BlocklyApps.init = function() { + // Set the page title with the content of the H1 title. + document.title = document.getElementById('title').textContent; + + // Set the HTML's language and direction. + // document.dir fails in Mozilla, use document.body.parentNode.dir instead. + // https://bugzilla.mozilla.org/show_bug.cgi?id=151407 + var rtl = BlocklyApps.isRtl(); + document.head.parentElement.setAttribute('dir', rtl ? 'rtl' : 'ltr'); + document.head.parentElement.setAttribute('lang', BlocklyApps.LANG); + + // Sort languages alphabetically. + var languages = []; + for (var i = 0; i < BlocklyApps.LANGUAGES.length; i++) { + var lang = BlocklyApps.LANGUAGES[i]; + languages.push([BlocklyApps.LANGUAGE_NAME[lang], lang]); + } + var comp = function(a, b) { + // Sort based on first argument ('English', 'Русский', '简体字', etc). + if (a[0] > b[0]) return 1; + if (a[0] < b[0]) return -1; + return 0; + }; + languages.sort(comp); + // Populate the language selection menu. + var languageMenu = document.getElementById('languageMenu'); + languageMenu.options.length = 0; + for (var i = 0; i < languages.length; i++) { + var tuple = languages[i]; + var lang = tuple[tuple.length - 1]; + var option = new Option(tuple[0], lang); + if (lang == BlocklyApps.LANG) { + option.selected = true; + } + languageMenu.options.add(option); + } + languageMenu.addEventListener('change', BlocklyApps.changeLanguage, true); + + // Disable the link button if page isn't backed by App Engine storage. + var linkButton = document.getElementById('linkButton'); + if ('BlocklyStorage' in window) { + BlocklyStorage['HTTPREQUEST_ERROR'] = + BlocklyApps.getMsg('httpRequestError'); + BlocklyStorage['LINK_ALERT'] = BlocklyApps.getMsg('linkAlert'); + BlocklyStorage['HASH_ERROR'] = BlocklyApps.getMsg('hashError'); + BlocklyStorage['XML_ERROR'] = BlocklyApps.getMsg('xmlError'); + // Swap out the BlocklyStorage's alert() for a nicer dialog. + BlocklyStorage.alert = BlocklyApps.storageAlert; + BlocklyApps.bindClick('linkButton', BlocklyStorage.link); + } else if (linkButton) { + linkButton.className = 'disabled'; + } + + if (document.getElementById('codeButton')) { + BlocklyApps.bindClick('codeButton', BlocklyApps.showCode); + } + + // Fixes viewport for small screens. + var viewport = document.querySelector('meta[name="viewport"]'); + if (viewport && screen.availWidth < 725) { + viewport.setAttribute('content', + 'width=725, initial-scale=.35, user-scalable=no'); + } +}; + +/** + * Initialize Blockly for a readonly iframe. Called on page load. + * XML argument may be generated from the console with: + * encodeURIComponent(Blockly.Xml.domToText(Blockly.Xml.workspaceToDom(Blockly.mainWorkspace)).slice(5, -6)) + */ +BlocklyApps.initReadonly = function() { + Blockly.inject(document.getElementById('blockly'), + {path: '../../', + readOnly: true, + rtl: BlocklyApps.isRtl(), + scrollbars: false}); + + // Add the blocks. + var xml = BlocklyApps.getStringParamFromUrl('xml', ''); + xml = Blockly.Xml.textToDom('' + xml + ''); + Blockly.Xml.domToWorkspace(Blockly.mainWorkspace, xml); +}; + +/** + * Load blocks saved on App Engine Storage or in session/local storage. + * @param {string} defaultXml Text representation of default blocks. + */ +BlocklyApps.loadBlocks = function(defaultXml) { + try { + var loadOnce = window.sessionStorage.loadOnceBlocks; + } catch(e) { + // Firefox sometimes throws a SecurityError when accessing sessionStorage. + // Restarting Firefox fixes this, so it looks like a bug. + var loadOnce = null; + } + if ('BlocklyStorage' in window && window.location.hash.length > 1) { + // An href with #key trigers an AJAX call to retrieve saved blocks. + BlocklyStorage.retrieveXml(window.location.hash.substring(1)); + } else if (loadOnce) { + // Language switching stores the blocks during the reload. + delete window.sessionStorage.loadOnceBlocks; + var xml = Blockly.Xml.textToDom(loadOnce); + Blockly.Xml.domToWorkspace(Blockly.mainWorkspace, xml); + } else if (defaultXml) { + // Load the editor with default starting blocks. + var xml = Blockly.Xml.textToDom(defaultXml); + Blockly.Xml.domToWorkspace(Blockly.mainWorkspace, xml); + } else if ('BlocklyStorage' in window) { + // Restore saved blocks in a separate thread so that subsequent + // initialization is not affected from a failed load. + window.setTimeout(BlocklyStorage.restoreBlocks, 0); + } +}; + +/** + * Save the blocks and reload with a different language. + */ +BlocklyApps.changeLanguage = function() { + // Store the blocks for the duration of the reload. + var xml = Blockly.Xml.workspaceToDom(Blockly.mainWorkspace); + var text = Blockly.Xml.domToText(xml); + window.sessionStorage.loadOnceBlocks = text; + + var languageMenu = document.getElementById('languageMenu'); + var newLang = encodeURIComponent( + languageMenu.options[languageMenu.selectedIndex].value); + var search = window.location.search; + if (search.length <= 1) { + search = '?lang=' + newLang; + } else if (search.match(/[?&]lang=[^&]*/)) { + search = search.replace(/([?&]lang=)[^&]*/, '$1' + newLang); + } else { + search = search.replace(/\?/, '?lang=' + newLang + '&'); + } + + window.location = window.location.protocol + '//' + + window.location.host + window.location.pathname + search; +}; + +/** + * Highlight the block (or clear highlighting). + * @param {?string} id ID of block that triggered this action. + */ +BlocklyApps.highlight = function(id) { + if (id) { + var m = id.match(/^block_id_(\d+)$/); + if (m) { + id = m[1]; + } + } + Blockly.mainWorkspace.highlightBlock(id); +}; + +/** + * If the user has executed too many actions, we're probably in an infinite + * loop. Sadly I wasn't able to solve the Halting Problem. + * @param {?string} opt_id ID of loop block to highlight. + * @throws {Infinity} Throws an error to terminate the user's program. + */ +BlocklyApps.checkTimeout = function(opt_id) { + if (opt_id) { + BlocklyApps.log.push([null, opt_id]); + } + if (BlocklyApps.ticks-- < 0) { + throw Infinity; + } +}; + +/** + * Is the dialog currently onscreen? + * @private + */ +BlocklyApps.isDialogVisible_ = false; + +/** + * A closing dialog should animate towards this element. + * @type Element + * @private + */ +BlocklyApps.dialogOrigin_ = null; + +/** + * A function to call when a dialog closes. + * @type Function + * @private + */ +BlocklyApps.dialogDispose_ = null; + +/** + * Show the dialog pop-up. + * @param {!Element} content DOM element to display in the dialog. + * @param {Element} origin Animate the dialog opening/closing from/to this + * DOM element. If null, don't show any animations for opening or closing. + * @param {boolean} animate Animate the dialog opening (if origin not null). + * @param {boolean} modal If true, grey out background and prevent interaction. + * @param {!Object} style A dictionary of style rules for the dialog. + * @param {Function} disposeFunc An optional function to call when the dialog + * closes. Normally used for unhooking events. + */ +BlocklyApps.showDialog = function(content, origin, animate, modal, style, + disposeFunc) { + if (BlocklyApps.isDialogVisible_) { + BlocklyApps.hideDialog(false); + } + BlocklyApps.isDialogVisible_ = true; + BlocklyApps.dialogOrigin_ = origin; + BlocklyApps.dialogDispose_ = disposeFunc; + var dialog = document.getElementById('dialog'); + var shadow = document.getElementById('dialogShadow'); + var border = document.getElementById('dialogBorder'); + + // Copy all the specified styles to the dialog. + for (var name in style) { + dialog.style[name] = style[name]; + } + if (modal) { + shadow.style.visibility = 'visible'; + shadow.style.opacity = 0.3; + var header = document.createElement('div'); + header.id = 'dialogHeader'; + dialog.appendChild(header); + BlocklyApps.dialogMouseDownWrapper_ = + Blockly.bindEvent_(header, 'mousedown', null, + BlocklyApps.dialogMouseDown_); + } + dialog.appendChild(content); + content.className = content.className.replace('dialogHiddenContent', ''); + + function endResult() { + // Check that the dialog wasn't closed during opening. + if (BlocklyApps.isDialogVisible_) { + dialog.style.visibility = 'visible'; + dialog.style.zIndex = 1; + border.style.visibility = 'hidden'; + } + } + if (animate && origin) { + BlocklyApps.matchBorder_(origin, false, 0.2); + BlocklyApps.matchBorder_(dialog, true, 0.8); + // In 175ms show the dialog and hide the animated border. + window.setTimeout(endResult, 175); + } else { + // No animation. Just set the final state. + endResult(); + } +}; + +/** + * Horizontal start coordinate of dialog drag. + */ +BlocklyApps.dialogStartX_ = 0; + +/** + * Vertical start coordinate of dialog drag. + */ +BlocklyApps.dialogStartY_ = 0; + +/** + * Handle start of drag of dialog. + * @param {!Event} e Mouse down event. + * @private + */ +BlocklyApps.dialogMouseDown_ = function(e) { + BlocklyApps.dialogUnbindDragEvents_(); + if (Blockly.isRightButton(e)) { + // Right-click. + return; + } + // Left click (or middle click). + // Record the starting offset between the current location and the mouse. + var dialog = document.getElementById('dialog'); + BlocklyApps.dialogStartX_ = dialog.offsetLeft - e.clientX; + BlocklyApps.dialogStartY_ = dialog.offsetTop - e.clientY; + + BlocklyApps.dialogMouseUpWrapper_ = Blockly.bindEvent_(document, + 'mouseup', null, BlocklyApps.dialogUnbindDragEvents_); + BlocklyApps.dialogMouseMoveWrapper_ = Blockly.bindEvent_(document, + 'mousemove', null, BlocklyApps.dialogMouseMove_); + // This event has been handled. No need to bubble up to the document. + e.stopPropagation(); +}; + +/** + * Drag the dialog to follow the mouse. + * @param {!Event} e Mouse move event. + * @private + */ +BlocklyApps.dialogMouseMove_ = function(e) { + var dialog = document.getElementById('dialog'); + var dialogLeft = BlocklyApps.dialogStartX_ + e.clientX; + var dialogTop = BlocklyApps.dialogStartY_ + e.clientY; + dialogTop = Math.max(dialogTop, 0); + dialogTop = Math.min(dialogTop, window.innerHeight - dialog.offsetHeight); + dialogLeft = Math.max(dialogLeft, 0); + dialogLeft = Math.min(dialogLeft, window.innerWidth - dialog.offsetWidth); + dialog.style.left = dialogLeft + 'px'; + dialog.style.top = dialogTop + 'px'; +}; + +/** + * Stop binding to the global mouseup and mousemove events. + * @private + */ +BlocklyApps.dialogUnbindDragEvents_ = function() { + if (BlocklyApps.dialogMouseUpWrapper_) { + Blockly.unbindEvent_(BlocklyApps.dialogMouseUpWrapper_); + BlocklyApps.dialogMouseUpWrapper_ = null; + } + if (BlocklyApps.dialogMouseMoveWrapper_) { + Blockly.unbindEvent_(BlocklyApps.dialogMouseMoveWrapper_); + BlocklyApps.dialogMouseMoveWrapper_ = null; + } +}; + +/** + * Hide the dialog pop-up. + * @param {boolean} opt_animate Animate the dialog closing. Defaults to true. + * Requires that origin was not null when dialog was opened. + */ +BlocklyApps.hideDialog = function(opt_animate) { + if (!BlocklyApps.isDialogVisible_) { + return; + } + BlocklyApps.dialogUnbindDragEvents_(); + if (BlocklyApps.dialogMouseDownWrapper_) { + Blockly.unbindEvent_(BlocklyApps.dialogMouseDownWrapper_); + BlocklyApps.dialogMouseDownWrapper_ = null; + } + + BlocklyApps.isDialogVisible_ = false; + BlocklyApps.dialogDispose_ && BlocklyApps.dialogDispose_(); + BlocklyApps.dialogDispose_ = null; + var origin = (opt_animate === false) ? null : BlocklyApps.dialogOrigin_; + var dialog = document.getElementById('dialog'); + var shadow = document.getElementById('dialogShadow'); + var border = document.getElementById('dialogBorder'); + + shadow.style.opacity = 0; + + function endResult() { + shadow.style.visibility = 'hidden'; + border.style.visibility = 'hidden'; + } + if (origin) { + BlocklyApps.matchBorder_(dialog, false, 0.8); + BlocklyApps.matchBorder_(origin, true, 0.2); + // In 175ms hide both the shadow and the animated border. + window.setTimeout(endResult, 175); + } else { + // No animation. Just set the final state. + endResult(); + } + dialog.style.visibility = 'hidden'; + dialog.style.zIndex = -1; + var header = document.getElementById('dialogHeader'); + if (header) { + header.parentNode.removeChild(header); + } + while (dialog.firstChild) { + var content = dialog.firstChild; + content.className += ' dialogHiddenContent'; + document.body.appendChild(content); + } +}; + +/** + * Match the animated border to the a element's size and location. + * @param {!Element} element Element to match. + * @param {boolean} animate Animate to the new location. + * @param {number} opacity Opacity of border. + * @private + */ +BlocklyApps.matchBorder_ = function(element, animate, opacity) { + if (!element) { + return; + } + var border = document.getElementById('dialogBorder'); + var bBox = BlocklyApps.getBBox_(element); + function change() { + border.style.width = bBox.width + 'px'; + border.style.height = bBox.height + 'px'; + border.style.left = bBox.x + 'px'; + border.style.top = bBox.y + 'px'; + border.style.opacity = opacity; + } + if (animate) { + border.className = 'dialogAnimate'; + window.setTimeout(change, 1); + } else { + border.className = ''; + change(); + } + border.style.visibility = 'visible'; +}; + +/** + * Compute the absolute coordinates and dimensions of an HTML or SVG element. + * @param {!Element} element Element to match. + * @return {!Object} Contains height, width, x, and y properties. + * @private + */ +BlocklyApps.getBBox_ = function(element) { + if (element.getBBox) { + // SVG element. + var bBox = element.getBBox(); + var height = bBox.height; + var width = bBox.width; + var xy = Blockly.getAbsoluteXY_(element); + var x = xy.x; + var y = xy.y; + } else { + // HTML element. + var height = element.offsetHeight; + var width = element.offsetWidth; + var x = 0; + var y = 0; + do { + x += element.offsetLeft; + y += element.offsetTop; + element = element.offsetParent; + } while (element); + } + return { + height: height, + width: width, + x: x, + y: y + }; +}; + +/** + * Display a storage-related modal dialog. + * @param {string} message Text to alert. + */ +BlocklyApps.storageAlert = function(message) { + var container = document.getElementById('containerStorage'); + container.textContent = ''; + var lines = message.split('\n'); + for (var i = 0; i < lines.length; i++) { + var p = document.createElement('p'); + p.appendChild(document.createTextNode(lines[i])); + container.appendChild(p); + } + + var content = document.getElementById('dialogStorage'); + var origin = document.getElementById('linkButton'); + var style = { + width: '50%', + left: '25%', + top: '5em' + }; + BlocklyApps.showDialog(content, origin, true, true, style, + BlocklyApps.stopDialogKeyDown()); + BlocklyApps.startDialogKeyDown(); +}; + +/** + * Convert the user's code to raw JavaScript. + * @param {string} code Generated code. + * @return {string} The code without serial numbers and timeout checks. + */ +BlocklyApps.stripCode = function(code) { + // Strip out serial numbers. + code = code.replace(/(,\s*)?'block_id_\d+'\)/g, ')'); + // Remove timeouts. + var regex = new RegExp(Blockly.JavaScript.INFINITE_LOOP_TRAP + .replace('(%1)', '\\((\'\\d+\')?\\)'), 'g'); + return code.replace(regex, ''); +}; + +/** + * Show the user's code in raw JavaScript. + * @param {!Event} e Mouse or touch event. + */ +BlocklyApps.showCode = function(e) { + var origin = e.target; + var code = Blockly.JavaScript.workspaceToCode(); + code = BlocklyApps.stripCode(code); + var pre = document.getElementById('containerCode'); + pre.textContent = code; + if (typeof prettyPrintOne == 'function') { + code = pre.innerHTML; + code = prettyPrintOne(code, 'js'); + pre.innerHTML = code; + } + + var content = document.getElementById('dialogCode'); + var style = { + width: '40%', + left: '30%', + top: '5em' + }; + BlocklyApps.showDialog(content, origin, true, true, style, + BlocklyApps.stopDialogKeyDown); + BlocklyApps.startDialogKeyDown(); +}; + +/** + * If the user preses enter, escape, or space, hide the dialog. + * @param {!Event} e Keyboard event. + * @private + */ +BlocklyApps.dialogKeyDown_ = function(e) { + if (BlocklyApps.isDialogVisible_) { + if (e.keyCode == 13 || + e.keyCode == 27 || + e.keyCode == 32) { + BlocklyApps.hideDialog(true); + e.stopPropagation(); + e.preventDefault(); + } + } +}; + +/** + * Start listening for BlocklyApps.dialogKeyDown_. + */ +BlocklyApps.startDialogKeyDown = function() { + document.body.addEventListener('keydown', + BlocklyApps.dialogKeyDown_, true); +}; + +/** + * Stop listening for BlocklyApps.dialogKeyDown_. + */ +BlocklyApps.stopDialogKeyDown = function() { + document.body.removeEventListener('keydown', + BlocklyApps.dialogKeyDown_, true); +}; + +/** + * Gets the message with the given key from the document. + * @param {string} key The key of the document element. + * @return {string} The textContent of the specified element, + * or an error message if the element was not found. + */ +BlocklyApps.getMsg = function(key) { + var msg = BlocklyApps.getMsgOrNull(key); + return msg === null ? '[Unknown message: ' + key + ']' : msg; +}; + +/** + * Gets the message with the given key from the document. + * @param {string} key The key of the document element. + * @return {string} The textContent of the specified element, + * or null if the element was not found. + */ +BlocklyApps.getMsgOrNull = function(key) { + var element = document.getElementById(key); + if (element) { + var text = element.textContent; + // Convert newline sequences. + text = text.replace(/\\n/g, '\n'); + return text; + } else { + return null; + } +}; + +/** + * On touch enabled browsers, add touch-friendly variants of event handlers + * for elements such as buttons whose event handlers are specified in the + * markup. For example, ontouchend is treated as equivalent to onclick. + */ +BlocklyApps.addTouchEvents = function() { + // Do nothing if the browser doesn't support touch. + if (!('ontouchstart' in document.documentElement)) { + return; + } + // Treat ontouchend as equivalent to onclick for buttons. + var buttons = document.getElementsByTagName('button'); + for (var i = 0, button; button = buttons[i]; i++) { + if (!button.ontouchend) { + button.ontouchend = button.onclick; + } + } +}; + +// Add events for touch devices when the window is done loading. +window.addEventListener('load', BlocklyApps.addTouchEvents, false); + +/** + * Bind a function to a button's click event. + * On touch enabled browsers, ontouchend is treated as equivalent to onclick. + * @param {string} id ID of button element. + * @param {!Function} func Event handler to bind. + */ +BlocklyApps.bindClick = function(id, func) { + var el = document.getElementById(id); + el.addEventListener('click', func, true); + el.addEventListener('touchend', func, true); +}; + +/** + * Load the Prettify CSS and JavaScript. + */ +BlocklyApps.importPrettify = function() { + // + // + var link = document.createElement('link'); + link.setAttribute('rel', 'stylesheet'); + link.setAttribute('type', 'text/css'); + link.setAttribute('href', '../prettify.css'); + document.head.appendChild(link); + var script = document.createElement('script'); + script.setAttribute('type', 'text/javascript'); + script.setAttribute('src', '../prettify.js'); + document.head.appendChild(script); +}; diff --git a/apps/common.soy b/apps/common.soy new file mode 100644 index 000000000..716954320 --- /dev/null +++ b/apps/common.soy @@ -0,0 +1,104 @@ +{namespace apps} + +/** + * This is a Closure Template. + * + * Run the following command after changing the messages in any of the + * included apps subdirectories. If building on Windows, you may need to + * substitute '\' for '/'. + * + * java -jar _soy/SoyMsgExtractor.jar --outputFile extracted_msgs.xlf --srcs common.soy,code/template.soy,graph/template.soy,maze/template.soy,plane/template.soy,puzzle/template.soy,turtle/template.soy + * + * Create en.json, keys.json, and qqq.json. + * ../i18n/xliff_to_json.py --xlf extracted_msgs.xlf --templates common.soy {code,graph,maze,plane,puzzle,turtle}/template.soy + * + * Generate .js files for each project: + * for i in code graph maze plane puzzle turtle; do ../i18n/json_to_js.py --output_dir=$i/generated --template common.soy,$i/template.soy json/*.json; done + */ + +/** + * All messages to be translated. + */ +{template .messages} +
    + // Only used externally. + {msg meaning="Apps.subtitle" desc="A short description of Blockly."}a visual programming environment{/msg} + + // Common messages used in multiple applications are defined here. + // The applications' template.soy file may also contain msg statements + // with the same "meaning" value. The "desc" value must be set to "IBID" + // (case-insensitive) or identical to the one in this file (not + // recommended), or an error will be raised during generation of qqq.json. + // The source-language text in the applications' definitions is ignored. + {msg meaning="Apps.blocklyMessage" desc="The project name. If readers of your language would know approximately how to pronounce 'Blockly', leave unchanged. Otherwise, include a transliteration in parentheses, such as the Russian: 'Blockly (\u0411\u043bo\u043a\u043b\u0438)'."}Blockly{/msg} + + // Buttons and tooltips. + {msg meaning="Apps.codeTooltip" desc="tooltip - Pressing the button causes a program in the JavaScript computer language to be displayed, based on the program created by the user."}See generated JavaScript code.{/msg} + {msg meaning="Apps.linkTooltip" desc="tooltip - Clicking on this button will cause the current program to be saved and for a URL to be shown to later retrieve it."}Save and link to blocks.{/msg} + {msg meaning="Apps.runTooltip" desc="tooltip - Pressing this button runs the computer program the user has written."}Run the program defined by the blocks in the workspace.{/msg} + {msg meaning="Apps.runProgram" desc="button label - Pressing the button runs the computer program the user has written."}Run Program{/msg} + {msg meaning="Apps.resetProgram" desc="button label - Pressing the button causes the output of the program to be erased but does not delete the user's program)."}Reset{/msg} + {{msg meaning="Apps.dialogOk" desc="Label on button for user to press when done reading help information.\n{lb}{lb}Identical|OK{rb}{rb}"}}OK{{/msg}} + {{msg meaning="Apps.dialogCancel" desc="Label on button for user to press when not wanting to proceed.\n{lb}{lb}Identical|Cancel{rb}{rb}"}}Cancel{{/msg}} + + // Categories. Apps can use these names or their own. + {msg meaning="Apps.catLogic" desc="category - Blocks related to [https://code.google.com/p/blockly/wiki/Logic logic]."}Logic{/msg} + {msg meaning="Apps.catLoops" desc="category - Blocks related to [http://en.wikipedia.org/wiki/Control_flow#Loops loops]."}Loops{/msg} + {msg meaning="Apps.catMath" desc="category - Blocks related to mathematics."}Math{/msg} + {msg meaning="Apps.catText" desc="category - Blocks related to [https://code.google.com/p/blockly/wiki/Text text processing]."}Text{/msg} + {msg meaning="Apps.catLists" desc="category - Blocks related to [https://code.google.com/p/blockly/wiki/Lists lists]."}Lists{/msg} + {msg meaning="Apps.catColour" desc="category - Blocks related to [https://code.google.com/p/blockly/wiki/Colour colour]."}Colour{/msg} + {msg meaning="Apps.catVariables" desc="category - Blocks related to [https://code.google.com/p/blockly/wiki/Variables variables]."}Variables{/msg} + {msg meaning="Apps.catProcedures" desc="category - Blocks related to [http://en.wikipedia.org/wiki/Subroutine defining or using procedures/functions]."}Procedures{/msg} + + // Error messages related to loading/storing user programs. + {msg meaning="Apps.httpRequestError" desc="alert - The URL is invalid or a server error occurred. This message will be followed by technical information useful to engineers trying to understand the problem."}There was a problem with the request.{/msg} + {msg meaning="Apps.linkAlert" desc="alert - After the user has pressed a button to save his/her program, this provides the URL (%1) to retrieve the program. The characters '\n\n' indicate that a blank line will be displayed before the URL (in English). Leave those in unless you move %1 to the beginning or middle of the text, in which case you should use your judgment about where blank lines would be most useful.\n\nParameters:\n* %1 - URL of saved program."}Share your blocks with this link:\n\n%1{/msg} + {{msg meaning="Apps.hashError" desc="alert - A request to retrieve a stored program does not have a valid URL. %1 is the invalid portion of the URL."}}Sorry, '%1' doesn't correspond with any saved program.{{/msg}} + {msg meaning="Apps.xmlError" desc="alert - There was a problem loading a file previously saved by the user. The most likely reason for the problem is that it was created with an earlier, incompatible version of Blockly. This message will be followed by technical information useful to engineers trying to understand the problem."}Could not load your saved file. Perhaps it was created with a different version of Blockly?{/msg} + + // Default variable names. + {msg meaning="Apps.listVariable" desc="variable name - Default [https://code.google.com/p/blockly/wiki/Variables variable] representing a [https://code.google.com/p/blockly/wiki/Lists list]. This should be a single word, preferably short."}list{/msg} + {msg meaning="Apps.textVariable" desc="variable name - Default [https://code.google.com/p/blockly/wiki/Variables variable] representing a [https://code.google.com/p/blockly/wiki/Text piece of text]. This should be a single word, preferably short."}text{/msg} +
    +{/template} + +/** + * Dialogs. + */ +{template .dialog private="true"} +
    +
    +
    +{/template} + +/** + * Code dialog. + */ +{template .codeDialog private="true"} +
    +
    
    +    {call apps.ok /}
    +  
    +{/template} + +/** + * Storage dialog. + */ +{template .storageDialog private="true"} +
    +
    + {call apps.ok /} +
    +{/template} + +/** + * OK button for dialogs. + */ +{template .ok private="true"} +
    + +
    +{/template} diff --git a/apps/graph/blocks.js b/apps/graph/blocks.js new file mode 100644 index 000000000..61161d028 --- /dev/null +++ b/apps/graph/blocks.js @@ -0,0 +1,59 @@ +/** + * Blockly Apps: Graphing Calculator Blocks + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Blocks for Blockly's Graphing Calculator application. + * @author q.neutron@gmail.com (Quynh Neutron) + */ +'use strict'; + +Blockly.Blocks['graph_get_x'] = { + // x variable getter. + init: function() { + this.setHelpUrl(Blockly.Msg.VARIABLES_GET_HELPURL); + this.setColour(330); + this.appendDummyInput() + .appendTitle('x'); + this.setOutput(true, 'Number'); + this.setTooltip(Blockly.Msg.VARIABLES_GET_TOOLTIP); + } +}; + +Blockly.JavaScript['graph_get_x'] = function(block) { + // x variable getter. + return ['x', Blockly.JavaScript.ORDER_ATOMIC]; +}; + +Blockly.Blocks['graph_set_y'] = { + // y variable setter. + init: function() { + this.setHelpUrl(Blockly.Msg.VARIABLES_SET_HELPURL); + this.setColour(330); + this.appendValueInput('VALUE') + .appendTitle('y ='); + this.setTooltip(Blockly.Msg.VARIABLES_SET_TOOLTIP); + } +}; + +Blockly.JavaScript['graph_set_y'] = function(block) { + // y variable setter. + var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE', + Blockly.JavaScript.ORDER_ASSIGNMENT) || ''; + return argument0 + ';'; +}; diff --git a/apps/graph/generated/af.js b/apps/graph/generated/af.js new file mode 100644 index 000000000..058529cab --- /dev/null +++ b/apps/graph/generated/af.js @@ -0,0 +1,50 @@ +// This file was automatically generated from common.soy. +// Please don't edit this file by hand. + +if (typeof apps == 'undefined') { var apps = {}; } + + +apps.messages = function(opt_data, opt_ignored, opt_ijData) { + return '
    a visual programming environmentBlocklySee generated JavaScript code.Save and link to blocks.Run the program defined by the blocks in the workspace.Run ProgramResetOKCancelLogicLoopsMathTextListsColourVariablesProceduresThere was a problem with the request.Share your blocks with this link:\\n\\n%1Sorry, \'%1\' doesn\'t correspond with any saved program.Could not load your saved file. Perhaps it was created with a different version of Blockly?listtext
    '; +}; + + +apps.dialog = function(opt_data, opt_ignored, opt_ijData) { + return '
    '; +}; + + +apps.codeDialog = function(opt_data, opt_ignored, opt_ijData) { + return '
    ' + apps.ok(null, null, opt_ijData) + '
    '; +}; + + +apps.storageDialog = function(opt_data, opt_ignored, opt_ijData) { + return '
    ' + apps.ok(null, null, opt_ijData) + '
    '; +}; + + +apps.ok = function(opt_data, opt_ignored, opt_ijData) { + return '
    '; +}; + +; +// This file was automatically generated from template.soy. +// Please don't edit this file by hand. + +if (typeof graphpage == 'undefined') { var graphpage = {}; } + + +graphpage.messages = function(opt_data, opt_ignored, opt_ijData) { + return apps.messages(null, null, opt_ijData); +}; + + +graphpage.start = function(opt_data, opt_ignored, opt_ijData) { + return graphpage.messages(null, null, opt_ijData) + '

    Blockly : Graphing Calculator

       
    ...
    \n'); + +/** + * Create a namespace for the application. + */ +var Graph = {}; + +/** + * Initialize Blockly and the graph. Called on page load. + */ +Graph.init = function() { + BlocklyApps.init(); + + var rtl = BlocklyApps.isRtl(); + var toolbox = document.getElementById('toolbox'); + Blockly.inject(document.getElementById('blockly'), + {path: '../../', + rtl: rtl, + toolbox: toolbox}); + + var blocklyDiv = document.getElementById('blockly'); + var visualization = document.getElementById('visualization'); + var onresize = function(e) { + var top = visualization.offsetTop; + blocklyDiv.style.top = Math.max(10, top - window.scrollY) + 'px'; + blocklyDiv.style.left = rtl ? '10px' : '420px'; + blocklyDiv.style.width = (window.innerWidth - 440) + 'px'; + }; + window.addEventListener('scroll', function() { + onresize(); + Blockly.fireUiEvent(window, 'resize'); + }); + window.addEventListener('resize', onresize); + onresize(); + Blockly.fireUiEvent(window, 'resize'); + + var defaultXml = + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ''; + BlocklyApps.loadBlocks(defaultXml); + + Blockly.mainWorkspace.getCanvas().addEventListener('blocklyWorkspaceChange', + window.parent.Graph.drawVisualization, false); +}; + +window.addEventListener('load', Graph.init); + +/** + * Cached copy of the function string. + * @type !string + * @private + */ +Graph.oldFormula_ = null; + +/** + * Visualize the graph of y = f(x) using Google Chart Tools. + * For more documentation on Google Chart Tools, see this linechart example: + * google-developers.appspot.com/chart/interactive/docs/gallery/linechart + */ +Graph.drawVisualization = function() { + var tuple = Graph.getFunction(); + var defs = tuple[0]; + var formula = tuple[1]; + if (formula === Graph.oldFormula_) { + // No change in the formula, don't recompute. + return; + } + Graph.oldFormula_ = formula; + + // Create and populate the data table. + var data = google.visualization.arrayToDataTable(Graph.plot(defs + formula)); + + var options = { //curveType: "function", + width: 400, height: 400, + chartArea: {left: '10%', width: '85%', height: '85%'} + }; + + // Create and draw the visualization, passing in the data and options. + new google.visualization.LineChart(document.getElementById('visualization')). + draw(data, options); + var funcText = document.getElementById('funcText'); + if (funcText.lastChild) { + funcText.removeChild(funcText.lastChild); + } + // Remove the ";" generally ending the JavaScript statement y = {code};. + formula = formula.replace(/;$/, ''); + funcText.appendChild(document.createTextNode('y = ' + formula)); +}; + +/** + * Plot points on the function y = f(x). + * @param {string} code JavaScript code. + * @return {!Array.} 2D Array of points on the graph. + */ +Graph.plot = function(code) { + // Initialize a table with two column headings. + var table = []; + var y; + // TODO: Improve range and scale of graph. + for (var x = -10; x <= 10; x = Math.round((x + 0.1) * 10) / 10) { + try { + y = eval(code); + } catch (e) { + y = NaN; + } + if (!isNaN(y)) { + // Prevent y from being displayed inconsistently, some in decimals, some + // in scientific notation, often when y has accumulated rounding errors. + y = Math.round(y * Math.pow(10, 14)) / Math.pow(10, 14); + table.push([x, y]); + } + } + // Add column heading to table. + if (table.length) { + table.unshift(['x', 'y']); + } else { + // If the table is empty, add a [0, 0] row to prevent graph error. + table.unshift(['x', 'y'], [0, 0]); + } + return table; +}; + +/** + * Get from blocks the right hand side content of the function y = f(x). + * @return {!Array.} Tuple of any function definitions and the formula + * in JavaScipt for f(x). + */ +Graph.getFunction = function() { + var topBlocks = Blockly.mainWorkspace.getTopBlocks(false); + var yBlock; + // Set yBlock to only the code plugged into 'graph_set_y'. + for (var j = 0; j < topBlocks.length; j++) { + if (topBlocks[j].type == 'graph_set_y') { + yBlock = topBlocks[j]; + } + } + if (!yBlock) { + return NaN; + } + Blockly.JavaScript.init(); + var code = Blockly.JavaScript.blockToCode(yBlock); + var defs = Blockly.JavaScript.finish(''); + return [defs, code]; +}; diff --git a/apps/graph/index.html b/apps/graph/index.html new file mode 100644 index 000000000..dd8c93452 --- /dev/null +++ b/apps/graph/index.html @@ -0,0 +1,22 @@ + + + + + + + Blockly : Graphing Calculator + + + + + + + + + + + + diff --git a/apps/graph/link.png b/apps/graph/link.png new file mode 100644 index 000000000..e930fd794 Binary files /dev/null and b/apps/graph/link.png differ diff --git a/apps/graph/style.css b/apps/graph/style.css new file mode 100644 index 000000000..f7fe8974f --- /dev/null +++ b/apps/graph/style.css @@ -0,0 +1,27 @@ +#linkButton { + padding: 5px 10px; +} + +#funcText { + margin-top: 1em; + margin-left: 1.5em; + font-family: sans-serif; + font-size: small; +} +#funcText>img { + height: 3px; + width: 15px; + vertical-align: middle; + margin-right: .5em; +} +#y1 { + background-color: #36c; +} +#blockly { + position: fixed; + bottom: 10px; +} +#languageMenu { + vertical-align: top; + margin-top: 12px; +} diff --git a/apps/graph/template.soy b/apps/graph/template.soy new file mode 100644 index 000000000..e27fbef57 --- /dev/null +++ b/apps/graph/template.soy @@ -0,0 +1,115 @@ +{namespace graphpage} + +/** + * This is a Closure Template. + * + * To regenerate just en.js, run this command: + * java -jar ../_soy/SoyToJsSrcCompiler.jar --outputPathFormat generated/en.js --srcs ../common.soy,template.soy + * + * To regenerate all files, see: trunk/apps/template.soy. + */ + +/** + * Translated messages for use in JavaScript. + */ +{template .messages} + {call apps.messages /} +{/template} + +/** + * Web page structure. + */ +{template .start} + {call .messages /} + + + + + +
    +

    + + {msg meaning="Apps.blocklyMessage" desc="IBID"}Blockly{/msg} + {sp}:{sp} + {msg meaning="Graph.title" desc="title - Brief title for this graphic calculator application."} + Graphing Calculator + {/msg} + +

    +
    + +     + + +
    +
    +
    + + ... +
    + + + + + + + {call .toolbox /} +
    + {call apps.dialog /} + {call apps.storageDialog /} +{/template} + +/** + * Toolbox. + */ +{template .toolbox} + +{/template} diff --git a/apps/index.html b/apps/index.html new file mode 100644 index 000000000..3830a8d55 --- /dev/null +++ b/apps/index.html @@ -0,0 +1,45 @@ + + + + + Blockly Apps + + + +

    Blockly Apps

    + +

    Below are some sample applications that use Blockly.

    + +
    +
    Puzzle
    +
    Learn to use Blockly's interface.
    +
    Maze
    +
    Use Blockly to solve a maze.
    +
    Turtle Graphics
    +
    Use Blockly to draw.
    +
    Graphing Calculator
    +
    Plot functions with Blockly.
    +
    Code
    +
    Export a Blockly program into JavaScript, Python or XML.
    +
    Plane seat calculator
    +
    Solve a math problem with one or two variables.
    +
    Block Factory
    +
    Build custom blocks using Blockly.
    +
    + + diff --git a/apps/json/af.json b/apps/json/af.json new file mode 100644 index 000000000..a686b6215 --- /dev/null +++ b/apps/json/af.json @@ -0,0 +1,35 @@ +{ + "Puzzle.tryAgain": "Die gemerkte blok is nie korrek nie.\nHou aan om te probeer.", + "Puzzle.country3City2": "Shanghai", + "Puzzle.country3City1": "Beijing", + "Puzzle.country3Language": "Sjinees", + "Puzzle.checkAnswers": "Kontroleer antwoorde", + "Puzzle.language": "taal:", + "Apps.dialogOk": "OK", + "Puzzle.country1HelpUrl": "http://af.wikipedia.org/wiki/Australië", + "Puzzle.languageChoose": "kies...", + "Puzzle.country4City2": "São Paulo", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country2": "Duitsland", + "Puzzle.helpText": "Vir elke land (groen), koppel die vlag, kies die taal en maak 'n stapel van sy stede.", + "Puzzle.flag": "vlag:", + "Puzzle.country1Language": "Engels", + "Puzzle.country4HelpUrl": "http://af.wikipedia.org/wiki/Brasilië", + "Puzzle.country2HelpUrl": "http://af.wikipedia.org/wiki/Duitsland", + "Puzzle.country3HelpUrl": "http://af.wikipedia.org/wiki/Sjina", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country2Language": "Duits", + "Puzzle.country3": "Sjina", + "Puzzle.country4Language": "Portugees", + "Puzzle.country1": "Australië", + "Puzzle.error1": "Byna! Eén blok is inkorrek.", + "Puzzle.error0": "Perfek!\nAl %1 blokke is korrek.", + "Puzzle.country4": "Brasilië", + "Puzzle.error2": "%1 blokke is inkorrek.", + "Puzzle.help": "Hulp", + "Puzzle.title": "Legkaart", + "Puzzle.country2City1": "Berlyn", + "Puzzle.cities": "stede:", + "Puzzle.country2City2": "München" +} diff --git a/apps/json/ar.json b/apps/json/ar.json new file mode 100644 index 000000000..36df77275 --- /dev/null +++ b/apps/json/ar.json @@ -0,0 +1,120 @@ +{ + "@metadata": { + "authors": [ + "Kuwaity26", + "Meno25", + "Mgi92" + ] + }, + "Apps.subtitle": "\u0628\u064a\u0626\u0629 \u0628\u0631\u0645\u062c\u0629 \u0645\u0631\u0626\u064a\u0629", + "Apps.blocklyMessage": "\u0628\u0644\u0648\u0643\u0644\u064a", + "Apps.codeTooltip": "\u0631\u0627\u062c\u0639 \u0625\u0646\u0634\u0627\u0621 \u062a\u0639\u0644\u064a\u0645\u0627\u062a \u0628\u0631\u0645\u062c\u064a\u0629 JavaScript.", + "Apps.runProgram": "\u0634\u063a\u0650\u0651\u0644 \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062c", + "Apps.resetProgram": "\u0625\u0639\u0627\u062f\u0629 \u0636\u0628\u0637", + "Apps.dialogOk": "\u062d\u0633\u0646", + "Apps.dialogCancel": "\u0625\u0644\u063a\u0627\u0621 \u0627\u0644\u0623\u0645\u0631", + "Apps.catLogic": "\u0645\u0646\u0637\u0642", + "Apps.catLoops": "\u0627\u0644\u062d\u0644\u0642\u0627\u062a", + "Apps.catMath": "\u0631\u064a\u0627\u0636\u064a\u0627\u062a", + "Apps.catText": "\u0646\u0635", + "Apps.catLists": "\u0642\u0648\u0627\u0626\u0645", + "Apps.catColour": "\u0644\u0648\u0646", + "Apps.catVariables": "\u0645\u062a\u063a\u064a\u0631\u0627\u062a", + "Apps.catProcedures": "\u0625\u062c\u0631\u0627\u0621\u0627\u062a", + "Apps.httpRequestError": "\u0643\u0627\u0646\u062a \u0647\u0646\u0627\u0643 \u0645\u0634\u0643\u0644\u0629 \u0645\u0639 \u0647\u0630\u0627 \u0627\u0644\u0637\u0644\u0628.", + "Apps.hashError": "\u0639\u0630\u0631\u0627\u064b\u060c\u0627\u0644 '1%' \u0644\u0627 \u062a\u062a\u0648\u0627\u0641\u0642 \u0645\u0639 \u0623\u064a \u0628\u0631\u0646\u0627\u0645\u062c \u062a\u0645 \u062d\u0641\u0638\u0647.", + "Apps.xmlError": "\u062a\u0639\u0630\u0631 \u062a\u062d\u0645\u064a\u0644 \u0627\u0644\u0645\u0644\u0641 \u0627\u0644\u0645\u062d\u0641\u0648\u0638\u0629 \u0627\u0644\u062e\u0627\u0635\u0629 \u0628\u0643. \u0631\u0628\u0645\u0627 \u062a\u0645 \u0625\u0646\u0634\u0627\u0624\u0647 \u0628\u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u0625\u0635\u062f\u0627\u0631 \u0645\u062e\u062a\u0644\u0641 \u0645\u0646 \u0628\u0644\u0648\u0643\u0644\u064a\u061f", + "Apps.listVariable": "\u0642\u0627\u0626\u0645\u0629", + "Apps.textVariable": "\u0646\u0635", + "Code.badXml": "\u062e\u0637\u0623 \u0641\u064a \u062a\u0648\u0632\u064a\u0639 \u0627\u0644 \"XML\":\n %1\n\n\u062d\u062f\u062f '\u0645\u0648\u0627\u0641\u0642' \u0644\u0644\u062a\u062e\u0644\u064a \u0639\u0646 \u0627\u0644\u062a\u063a\u064a\u064a\u0631\u0627\u062a \u0623\u0648 '\u0625\u0644\u063a\u0627\u0621 \u0627\u0644\u0623\u0645\u0631' \u0644\u0645\u0648\u0627\u0635\u0644\u0629 \u062a\u062d\u0631\u064a\u0631 \u0627\u0644\"XML\".", + "Code.badCode": "\u062e\u0637\u0623 \u0641\u064a \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062c:\n %1", + "Code.timeout": "\u062a\u0645 \u062a\u062c\u0627\u0648\u0632 \u0627\u0644\u062d\u062f \u0627\u0644\u0623\u0642\u0635\u0649 \u0644\u062a\u0643\u0631\u0627\u0631\u0627\u062a \u0627\u0644\u062a\u0646\u0641\u064a\u0630 .", + "Code.title": "\u0643\u0648\u062f", + "Code.blocks": "\u0627\u0644\u0628\u0644\u0648\u0643\u0627\u062a", + "Maze.moveForward": "\u062a\u062d\u0631\u0651\u0643 \u0625\u0644\u0649 \u0627\u0644\u0623\u0645\u0627\u0645", + "Maze.turnLeft": "\u0627\u0633\u062a\u062f\u0631 \u0625\u0644\u0649 \u0627\u0644\u064a\u0633\u0627\u0631", + "Maze.turnRight": "\u0627\u0633\u062a\u062f\u0631 \u0627\u0644\u0649 \u0627\u0644\u064a\u0645\u064a\u0646", + "Maze.doCode": "\u0627\u0641\u0639\u0644", + "Maze.elseCode": "\u063a\u064a\u0631", + "Maze.pathLeft": "\u0625\u0630\u0627 \u0643\u0627\u0646 \u0627\u0644\u0645\u0633\u0627\u0631 \u0625\u0644\u0649 \u0627\u0644\u064a\u0633\u0627\u0631", + "Maze.pathRight": "\u0625\u0630\u0627 \u0643\u0627\u0646 \u0627\u0644\u0645\u0633\u0627\u0631 \u0625\u0644\u0649 \u0627\u0644\u064a\u0645\u064a\u0646", + "Maze.repeatUntil": "\u0643\u0631\u0650\u0651\u0631 \u062d\u062a\u0649", + "Maze.moveForwardTooltip": "\u064a\u062a\u062d\u0631\u0643 \u0627\u0644\u0644\u0627\u0639\u0628 \u0645\u0633\u0627\u0641\u0629 \u0648\u0627\u062d\u062f\u0629 \u0625\u0644\u0649 \u0627\u0644\u0623\u0645\u0627\u0645.", + "Maze.turnTooltip": "\u064a\u0646\u0639\u0637\u0641 \u0627\u0644\u0644\u0627\u0639\u0628 \u0627\u0644\u0649 \u0627\u0644\u064a\u0645\u064a\u0646 \u0623\u0648 \u0627\u0644\u064a\u0633\u0627\u0631 \u0628\u0645\u0642\u062f\u0627\u0631 90 \u062f\u0631\u062c\u0629.", + "Maze.ifTooltip": "\u0625\u0630\u0627 \u0643\u0627\u0646 \u0647\u0646\u0627\u0643 \u0645\u0633\u0627\u0631 \u0641\u064a \u0627\u0644\u0627\u062a\u062c\u0627\u0647 \u0627\u0644\u0645\u062d\u062f\u062f\u060c \u0627\u0646\u062c\u0632 \u0628\u0639\u0636 \u0627\u0644\u0625\u062c\u0631\u0627\u0621\u0627\u062a.", + "Maze.nextLevel": "\u062a\u0647\u0627\u0646\u064a\u0646\u0627! \u0647\u0644 \u0623\u0646\u062a \u0645\u0633\u062a\u0639\u062f \u0644\u0644\u0645\u0636\u064a \u0642\u062f\u0645\u0627 \u0625\u0644\u0649 \u0645\u0633\u062a\u0648\u0649 1% \u061f", + "Maze.maze": "\u0627\u0644\u0645\u062a\u0627\u0647\u0629", + "Maze.resetTooltip": " \u0627\u0633\u062a\u0631\u062c\u0627\u0639 \u0627\u0644\u0644\u0627\u0639\u0628 \u0627\u0644\u0649 \u0628\u062f\u0627\u064a\u0629 \u0627\u0644\u0645\u062a\u0627\u0647\u0629.", + "Maze.helpRun": "\u0642\u0645 \u0628\u062a\u0634\u063a\u064a\u0644 \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062c \u0627\u0644\u062e\u0627\u0635 \u0628\u0643 \u0644\u0631\u0624\u064a\u0629 \u0645\u0627 \u064a\u062d\u062f\u062b.", + "Maze.helpReset": "\u0628\u0631\u0646\u0627\u0645\u062c\u0643 \u0644\u0645 \u064a\u062d\u0644 \u0627\u0644\u0645\u062a\u0627\u0647\u0629. \u0627\u0636\u063a\u0637 '\u0625\u0639\u0627\u062f\u0629' \u0648\u062d\u0627\u0648\u0644 \u0645\u0631\u0629 \u0623\u062e\u0631\u0649.", + "Maze.helpWallFollow": "\u0647\u0644 \u064a\u0645\u0643\u0646\u0643 \u062d\u0644 \u0647\u0630\u0647 \u0627\u0644\u0645\u062a\u0627\u0647\u0629 \u0627\u0644\u0645\u0639\u0642\u062f\u0629\u061f \u062d\u0627\u0648\u0644 \u0627\u0646 \u062a\u0644\u062d\u0642 \u0627\u0644\u062c\u062f\u0627\u0631 \u0627\u0644\u0623\u064a\u0633\u0631. \u0644\u0644\u0645\u0628\u0631\u0645\u062c\u064a\u0646 \u0627\u0644\u0645\u062a\u0642\u062f\u0645\u064a\u0646 \u0641\u0642\u0637!", + "Plane.rows": "\u0627\u0644\u0635\u0641\u0648\u0641: 1%", + "Plane.getRows": "\u0627\u0644\u0635\u0641\u0648\u0641 (1%)", + "Plane.rows1": "\u0635\u0641\u0648\u0641 \u0627\u0644\u0637\u0628\u0642\u0629 \u0627\u0644\u0623\u0648\u0644\u0649: 1%", + "Plane.getRows1": "\u0635\u0641\u0648\u0641 \u0627\u0644\u0637\u0628\u0642\u0629 \u0627\u0644\u0623\u0648\u0644\u0649 (1%)", + "Plane.rows2": "\u0635\u0641\u0648\u0641 \u0627\u0644\u0641\u0626\u0629 \u0627\u0644\u062b\u0627\u0646\u064a\u0629: 1%", + "Plane.getRows2": "\u0635\u0641\u0648\u0641 \u0627\u0644\u0641\u0626\u0629 \u0627\u0644\u062b\u0627\u0646\u064a\u0629: (1%)", + "Plane.seats": "\u0627\u0644\u0645\u0642\u0627\u0639\u062f: 1%", + "Plane.placeholder": "\u061f", + "Plane.setSeats": "\u0627\u0644\u0645\u0642\u0627\u0639\u062f =", + "Plane.plane": "\u0627\u0644\u0637\u0627\u0626\u0631\u0629", + "Plane.description1": "\u0647\u0646\u0627\u0644\u0643 \u0637\u0627\u0626\u0631\u0629 \u062a\u062d\u062a\u0648\u064a \u0639\u0644\u0649 \u0639\u062f\u062f \u0645\u0646 \u0635\u0641\u0648\u0641 \u0645\u0642\u0627\u0639\u062f \u0627\u0644\u0631\u0643\u0627\u0628. \u0643\u0644 \u0635\u0641 \u064a\u062d\u062a\u0648\u064a \u0639\u0644\u0649 \u0623\u0631\u0628\u0639\u0629 \u0645\u0642\u0627\u0639\u062f.", + "Puzzle.country1": "\u0623\u0633\u062a\u0631\u0627\u0644\u064a\u0627", + "Puzzle.country1Language": "\u0627\u0644\u0625\u0646\u0643\u0644\u064a\u0632\u064a\u0629", + "Puzzle.country1City1": "\u0645\u0644\u0628\u0648\u0631\u0646", + "Puzzle.country1City2": "\u0633\u062f\u0646\u064a", + "Puzzle.country1HelpUrl": "https://ar.wikipedia.org/\u0623\u0633\u062a\u0631\u0627\u0644\u064a\u0627", + "Puzzle.country2": "\u0623\u0644\u0645\u0627\u0646\u064a\u0627", + "Puzzle.country2Language": "\u0623\u0644\u0645\u0627\u0646\u064a", + "Puzzle.country2City1": "\u0628\u0631\u0644\u064a\u0646", + "Puzzle.country2City2": "\u0645\u064a\u0648\u0646\u064a\u062e", + "Puzzle.country2HelpUrl": "https://ar.wikipedia.org/wiki/\u0623\u0644\u0645\u0627\u0646\u064a\u0627", + "Puzzle.country3": "\u0627\u0644\u0635\u064a\u0646", + "Puzzle.country3Language": "\u0627\u0644\u0635\u064a\u0646\u064a\u0629", + "Puzzle.country3City1": "\u0628\u0643\u064a\u0646", + "Puzzle.country3City2": "\u0634\u0646\u063a\u0647\u0627\u064a", + "Puzzle.country3HelpUrl": "https://ar.wikipedia.org/wiki/\u0627\u0644\u0635\u064a\u0646", + "Puzzle.country4": "\u0627\u0644\u0628\u0631\u0627\u0632\u064a\u0644", + "Puzzle.country4Language": "\u0627\u0644\u0628\u0631\u062a\u063a\u0627\u0644\u064a\u0629", + "Puzzle.country4City1": "\u0631\u064a\u0648\u062f\u064a\u062c\u0627\u0646\u064a\u0631\u0648", + "Puzzle.country4City2": "\u0633\u0627\u0648\u0628\u0627\u0648\u0644\u0648", + "Puzzle.country4HelpUrl": "https://ar.wikipedia.org/\u0627\u0644\u0628\u0631\u0627\u0632\u064a\u0644", + "Puzzle.flag": "\u0631\u0627\u064a\u0629:", + "Puzzle.language": "\u0627\u0644\u0644\u063a\u0629:", + "Puzzle.languageChoose": "\u0627\u062e\u062a\u0631...", + "Puzzle.cities": "\u0627\u0644\u0645\u064f\u062f\u064f\u0646:", + "Puzzle.error0": "\u0645\u0645\u062a\u0627\u0632!\n\u0643\u0644 \u0627\u0644\u0645\u0643\u0639\u0628\u0627\u062a %1 \u0635\u062d\u064a\u062d\u0629.", + "Puzzle.error1": "\u0627\u0642\u062a\u0631\u0628\u062a! \u0645\u0643\u0639\u0651\u0628 \u0648\u0627\u062d\u062f \u063a\u064a\u0631 \u0635\u062d\u064a\u062d.", + "Puzzle.error2": "%1 \u0645\u0643\u0639\u0628\u0627\u062a \u063a\u064a\u0631 \u0635\u062d\u064a\u062d\u0629.", + "Puzzle.tryAgain": "\u0627\u0644\u0643\u062a\u0644\u0651\u0629 \u0627\u0644\u0645\u064f\u0628\u0631\u064e\u0632\u064e\u0629 \u063a\u064a\u0631 \u0635\u062d\u064a\u062d\u0629.\n\u0648\u0627\u0635\u0644 \u0627\u0644\u0645\u062d\u0627\u0648\u0644\u0629.", + "Puzzle.title": "\u0623\u062d\u062c\u064a\u0629", + "Puzzle.help": "\u0645\u0633\u0627\u0639\u062f\u0629", + "Puzzle.checkAnswers": "\u062a\u062d\u0642\u0651\u0642 \u0645\u0646 \u0627\u0644\u0625\u062c\u0627\u0628\u0627\u062a", + "Puzzle.helpText": "\u0644\u0643\u0644 \u0628\u0644\u062f (\u0628\u0627\u0644\u0623\u062e\u0636\u0631) \u0635\u0650\u0644 \u0627\u0644\u0639\u0644\u0645 \u0648 \u0627\u062e\u062a\u0631 \u0644\u063a\u062a\u0647\u0627 \u0648 \u062c\u0645\u0651\u0639 \u0645\u062f\u0646\u0647\u0627.", + "Turtle.moveTooltip": "\u062a\u062d\u0631\u064a\u0643 \u0627\u0644\u0633\u0644\u062d\u0641\u0627\u0629 \u0625\u0644\u0649 \u0627\u0644\u0623\u0645\u0627\u0645 \u0623\u0648 \u0625\u0644\u0649 \u0627\u0644\u062e\u0644\u0641 \u0628\u0645\u0642\u062f\u0627\u0631 \u0645\u062d\u062f\u062f.", + "Turtle.turnTooltip": "\u062a\u062d\u0648\u064a\u0644 \u0627\u0644\u0633\u0644\u062d\u0641\u0627\u0629 \u0627\u0644\u0649 \u0627\u0644\u0623\u064a\u0645\u0646 \u0623\u0648 \u0627\u0644\u0623\u064a\u0633\u0631 \u0628\u0639\u062f\u062f \u0645\u0639\u064a\u0646 \u0645\u0646 \u0627\u0644\u062f\u0631\u062c\u0627\u062a.", + "Turtle.widthTooltip": "\u062a\u063a\u064a\u064a\u0631 \u0639\u0631\u0636 \u0627\u0644\u0642\u0644\u0645.", + "Turtle.setWidth": "\u062a\u0639\u064a\u064a\u0646 \u0627\u0644\u0639\u0631\u0636 \u0625\u0644\u0649", + "Turtle.colourTooltip": "\u062a\u063a\u064a\u064a\u0631 \u0644\u0648\u0646 \u0627\u0644\u0642\u0644\u0645.", + "Turtle.setColour": "\u062a\u0639\u064a\u064a\u0646 \u0627\u0644\u0644\u0648\u0646 \u0625\u0644\u0649", + "Turtle.penTooltip": "\u064a\u0631\u0641\u0639 \u0623\u0648 \u064a\u062e\u0641\u0636 \u0627\u0644\u0642\u0644\u0645\u060c \u0644\u064a\u062a\u0645 \u0625\u064a\u0642\u0627\u0641 \u0623\u0648 \u0628\u062f\u0621 \u0627\u0644\u0631\u0633\u0645.", + "Turtle.penUp": "\u0631\u0641\u0639 \u0627\u0644\u0642\u0644\u0645", + "Turtle.penDown": "\u0627\u0646\u0632\u0627\u0644 \u0627\u0644\u0642\u0644\u0645", + "Turtle.turtleVisibilityTooltip": "\u062c\u0639\u0644 \u0627\u0644\u0633\u0644\u062d\u0641\u0627\u0629 (\u062f\u0627\u0626\u0631\u0629 \u0648\u0633\u0647\u0645) \u0645\u0631\u0626\u064a\u0629 \u0623\u0648 \u063a\u064a\u0631 \u0645\u0631\u0626\u064a\u0629.", + "Turtle.hideTurtle": "\u0625\u062e\u0641\u0627\u0621 \u0627\u0644\u0633\u0644\u062d\u0641\u0627\u0629", + "Turtle.showTurtle": "\u0625\u0638\u0647\u0627\u0631 \u0627\u0644\u0633\u0644\u062d\u0641\u0627\u0629", + "Turtle.printHelpUrl": "http://en.wikipedia.org/wiki/Printing", + "Turtle.printTooltip": "\u0631\u0633\u0645/\u0637\u0628\u0627\u0639\u0629 \u0627\u0644\u0646\u0635 \u0641\u064a \u0641\u064a \u0645\u0648\u0642\u0639 \u0627\u062a\u062c\u0627\u0647 \u0633\u0644\u062d\u0641\u0627\u0629 .", + "Turtle.print": "\u0625\u0637\u0628\u0639", + "Turtle.fontHelpUrl": "http://en.wikipedia.org/wiki/Font", + "Turtle.font": "\u0627\u0644\u062e\u0637", + "Turtle.fontSize": "\u062d\u062c\u0645 \u0627\u0644\u062e\u0637", + "Turtle.fontNormal": "\u0639\u0627\u062f\u064a", + "Turtle.fontBold": "\u063a\u0627\u0645\u0642", + "Turtle.fontItalic": "\u0645\u0627\u0626\u0644", + "Turtle.unloadWarning": "\u062a\u0631\u0643 \u0647\u0630\u0647 \u0627\u0644\u0635\u0641\u062d\u0629 \u0648\u0633\u0648\u0641 \u064a\u0624\u062f\u064a \u0625\u0644\u0649 \u0641\u0642\u062f\u0627\u0646 \u0627\u0644\u0639\u0645\u0644 \u0627\u0644\u062e\u0627\u0635 \u0628\u0643.", + "Turtle.title": "\u0631\u0633\u0648\u0645\u0627\u062a \u0627\u0644\u0633\u0644\u062d\u0641\u0627\u0629", + "Turtle.captureTooltip": "\u062d\u0641\u0638 \u0627\u0644\u0631\u0633\u0645.", + "Turtle.imgFilename": "\u0627\u0644\u0631\u0633\u0645\u0629.png", + "Turtle.catTurtle": "\u0627\u0644\u0633\u0644\u062d\u0641\u0627\u0629" +} \ No newline at end of file diff --git a/apps/json/arz.json b/apps/json/arz.json new file mode 100644 index 000000000..4c792f5de --- /dev/null +++ b/apps/json/arz.json @@ -0,0 +1,21 @@ +{ + "Puzzle.country3": "الصين", + "Puzzle.country2": "المانيا", + "Puzzle.country1": "اوستراليا", + "Puzzle.country2HelpUrl": "https://arz.wikipedia.org/wiki/المانيا", + "Puzzle.country4": "برازيل", + "Puzzle.error2": "%1 مكعبات غلط.", + "Puzzle.country3HelpUrl": "https://arz.wikipedia.org/wiki/الصين", + "Puzzle.country4HelpUrl": "https://arz.wikipedia.org/wiki/برازيل", + "Puzzle.country3City1": "بيكين", + "Puzzle.checkAnswers": "شوف الإجابات", + "Puzzle.country4City2": "ساو باولو", + "Puzzle.country1Language": "انجليزى", + "Puzzle.country3Language": "صينى", + "Puzzle.country2City1": "برلين", + "Puzzle.country1HelpUrl": "https://arz.wikipedia.org/wiki/%D8%A7%D9%88%D8%B3%D8%AA%D8%B1%D8%A7%D9%84%D9%8A%D8%A7", + "Puzzle.country2City2": "ميونيخ", + "Puzzle.country1City1": "ميلبورن", + "Puzzle.country1City2": "سيدنى", + "Puzzle.country2Language": "المانى" +} diff --git a/apps/json/be-tarask.json b/apps/json/be-tarask.json new file mode 100644 index 000000000..d55878a5e --- /dev/null +++ b/apps/json/be-tarask.json @@ -0,0 +1,35 @@ +{ + "Puzzle.tryAgain": "Вылучаны блёк зьмешчаны няправільна.\nСпрабуйце далей.", + "Puzzle.country3City2": "Шанхай", + "Puzzle.country3HelpUrl": "http://be-x-old.wikipedia.org/wiki/Кітай", + "Puzzle.country3Language": "кітайская", + "Puzzle.checkAnswers": "Праверыць адказы", + "Puzzle.language": "мова:", + "Apps.dialogOk": "OK", + "Puzzle.title": "Мазгатня", + "Puzzle.country1HelpUrl": "http://be-x-old.wikipedia.org/wiki/Аўстралія", + "Puzzle.languageChoose": "выберыце...", + "Puzzle.country4City2": "Сан-Паўлу", + "Puzzle.country4City1": "Рыё-дэ-Жанэйра", + "Puzzle.country4Language": "партугальская", + "Puzzle.helpText": "Далучыце да кожнай краіны (зялёны) яе сьцяг, выберыце яе афіцыйную мову і вызначыце гарады, што ёсьць у гэтай краіне.", + "Puzzle.flag": "сьцяг", + "Puzzle.country4HelpUrl": "http://be-x-old.wikipedia.org/wiki/Бразылія", + "Puzzle.error1": "Бязмала! Адзін блёк зьмешчаны няправільна.", + "Puzzle.country3City1": "Пэкін", + "Puzzle.country1City1": "Мэльбурн", + "Puzzle.country1City2": "Сыднэй", + "Puzzle.country2Language": "нямецкая", + "Puzzle.country3": "Кітай", + "Puzzle.country2": "Нямеччына", + "Puzzle.country1": "Аўстралія", + "Puzzle.country2HelpUrl": "http://be-x-old.wikipedia.org/wiki/Нямеччына", + "Puzzle.error0": "Выдатна!\nУсе блёкі (%1) зьмешчаныя правільна.", + "Puzzle.country4": "Бразылія", + "Puzzle.error2": "Некалькі блёкаў (%1) зьмешчаныя няправільна.", + "Puzzle.help": "Дапамога", + "Puzzle.country1Language": "ангельская", + "Puzzle.country2City1": "Бэрлін", + "Puzzle.cities": "гарады:", + "Puzzle.country2City2": "Мюнхэн" +} diff --git a/apps/json/bg.json b/apps/json/bg.json new file mode 100644 index 000000000..2650c2174 --- /dev/null +++ b/apps/json/bg.json @@ -0,0 +1,26 @@ +{ + "Puzzle.country3City2": "Шанхай", + "Puzzle.country3HelpUrl": "http://bg.wikipedia.org/wiki/Китай", + "Puzzle.country3Language": "Китайски", + "Puzzle.language": "език:", + "Puzzle.country1HelpUrl": "http://bg.wikipedia.org/wiki/Австралия", + "Puzzle.languageChoose": "избиране...", + "Puzzle.country4City2": "Сао Пауло", + "Puzzle.country4City1": "Рио де Жанейро", + "Puzzle.country4Language": "Португалски", + "Puzzle.flag": "флаг:", + "Puzzle.country4HelpUrl": "http://bg.wikipedia.org/wiki/Бразилия", + "Puzzle.country3City1": "Пекин", + "Puzzle.country1City1": "Мелбърн", + "Puzzle.country1City2": "Сидни", + "Puzzle.country2Language": "Немски", + "Puzzle.country3": "Китай", + "Puzzle.country2": "Германия", + "Puzzle.country1": "Австралия", + "Puzzle.country2HelpUrl": "http://bg.wikipedia.org/wiki/Германия", + "Puzzle.country4": "Бразилия", + "Puzzle.country1Language": "Английски", + "Puzzle.country2City1": "Берлин", + "Puzzle.cities": "градове:", + "Puzzle.country2City2": "Мюнхен" +} diff --git a/apps/json/bn.json b/apps/json/bn.json new file mode 100644 index 000000000..2669bda23 --- /dev/null +++ b/apps/json/bn.json @@ -0,0 +1,25 @@ +{ + "Puzzle.country3City2": "সাংহাই", + "Puzzle.country3City1": "বেইজিং", + "Puzzle.country3Language": "চাইনিজ", + "Puzzle.checkAnswers": "উত্তর যাচাই করুন", + "Puzzle.language": "ভাষা:", + "Apps.dialogOk": "ঠিক আছে", + "Puzzle.languageChoose": "পছন্দ করুন...", + "Puzzle.country4City2": "সাও পাওলো", + "Puzzle.country4City1": "রিউ দি জানেইরু", + "Puzzle.country4Language": "পর্তুগীজ", + "Puzzle.flag": "পতাকা:", + "Puzzle.country1City1": "মেলবোর্ন", + "Puzzle.country1City2": "সিডনি", + "Puzzle.country2Language": "জার্মান", + "Puzzle.country3": "চীন", + "Puzzle.country2": "জার্মানী", + "Puzzle.country1": "অস্ট্রেলিয়া", + "Puzzle.country4": "ব্রাজিল", + "Puzzle.help": "সাহায্য", + "Puzzle.country1Language": "ইংরেজি", + "Puzzle.country2City1": "বার্লিন", + "Puzzle.cities": "শহর:", + "Puzzle.country2City2": "মিউনিখ" +} diff --git a/apps/json/br.json b/apps/json/br.json new file mode 100644 index 000000000..0ca08d357 --- /dev/null +++ b/apps/json/br.json @@ -0,0 +1,153 @@ +{ + "@metadata": { + "authors": [ + "Fohanno", + "Fulup", + "Gwenn-Ael", + "Y-M D" + ] + }, + "Apps.subtitle": "un endro programmi\u00f1 da welet", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Gwelet ar c'hod JavaScript krouet.", + "Apps.linkTooltip": "Enrolla\u00f1 ha liamma\u00f1 d'ar bloc'hado\u00f9.", + "Apps.runTooltip": "La\u00f1sa\u00f1 ar programm termenet gant ar bloc'hado\u00f9 en takad labour.", + "Apps.runProgram": "La\u00f1sa\u00f1 ar programm", + "Apps.resetProgram": "Adderaouekaat", + "Apps.dialogOk": "Mat eo", + "Apps.dialogCancel": "Nulla\u00f1", + "Apps.catLogic": "Poell", + "Apps.catLoops": "Bouklo\u00f9", + "Apps.catMath": "Matematik", + "Apps.catText": "Testenn", + "Apps.catLists": "Rollo\u00f9", + "Apps.catColour": "Liv", + "Apps.catVariables": "Argemmenno\u00f9", + "Apps.catProcedures": "Argerzhadurio\u00f9", + "Apps.httpRequestError": "Ur gudenn zo gant ar reked.", + "Apps.linkAlert": "Ranna\u00f1 ho ploc'ho\u00f9 gant al liamm-ma\u00f1 :\n\n%1", + "Apps.hashError": "Digarezit. \"%1\" ne glot gant programm enrollet ebet.", + "Apps.xmlError": "Ne c'haller ket karga\u00f1 ho restr enrollet. Marteze e oa bet krouet gant ur stumm dishe\u00f1vel eus Blockly ?", + "Apps.listVariable": "roll", + "Apps.textVariable": "testenn", + "Code.badXml": "Fazi dielfenna\u00f1 XML :\n%1\n\nDibabit \"Mat eo\" evit dilezel ar c'hemmo\u00f9-se pe \"Nulla\u00f1\" evit kemma\u00f1 an XML c'hoazh.", + "Code.badCode": "Fazi programm :\n%1", + "Code.timeout": "Tizhet eo bet an niver brasa\u00f1 a iteradurio\u00f9 seveni\u00f1 aotreet.", + "Code.discard": "Diverka\u00f1 an holl vloc'ho\u00f9 %1 ?", + "Code.title": "Kod", + "Code.blocks": "Bloc'ho\u00f9", + "Code.trashTooltip": "Disteurel an holl vloc'ho\u00f9.", + "Graph.title": "Jederez c'hrafek", + "Maze.moveForward": "mont war-raok", + "Maze.turnLeft": "trei\u00f1 a-gleiz", + "Maze.turnRight": "trei\u00f1 a-zehou", + "Maze.doCode": "ober", + "Maze.elseCode": "a-hend-all", + "Maze.helpIfElse": "Seveni\u00f1 a raio ar bloc'ho\u00f9 \"Ma/A-hend-all\" an eil tra pe egile.", + "Maze.pathAhead": "Ma'z eus un hent dirak", + "Maze.pathLeft": "Ma'z eus un hent a-gleiz", + "Maze.pathRight": "Ma'z eus un hent a-zeho\u00f9", + "Maze.repeatUntil": "adober betek", + "Maze.moveForwardTooltip": "Lakait ar c'hoarier da vont war-raok eus un esaouenn.", + "Maze.turnTooltip": "Lakait ar c'hoarier da drei\u00f1 a-gleiz pe a-zeho\u00f9 a 90 derez.", + "Maze.ifTooltip": "Ma'z eus un hent war an tu spisaet, grit an obero\u00f9-se neuze.", + "Maze.ifelseTooltip": "Ma'z eus un hent war an tu spisaet, grit ar c'henta\u00f1 bloc'had obero\u00f9. A-hend-all, grit an eil bloc'had obero\u00f9.", + "Maze.whileTooltip": "Adober ar bloc'ho\u00f9 zo en diabarzh betek tizhout ar pal.", + "Maze.capacity0": "Ne chom bloc'h ebet (%0) ganeoc'h.", + "Maze.capacity1": "Chom a ra %1 bloc'h ganeoc'h.", + "Maze.capacity2": "Chom a ra %2 bloc'h ganeoc'h.", + "Maze.nextLevel": "Gourc'hemenno\u00f9 ! Ha prest oc'h da vont d'al live %1 ?", + "Maze.finalLevel": "Gourc'hemenno\u00f9 ! Diskoulmet eo bet al live diwezha\u00f1 ganeoc'h.", + "Maze.maze": "Milendall", + "Maze.runTooltip": "Lakaat ar c'hoarier d'ober ar pezh a lavar ar bloc'ho\u00f9.", + "Maze.resetTooltip": "Adlakaat an dudenn e dero\u00f9 ar milendall.", + "Maze.helpStack": "Bernia\u00f1 asambles daou vloc'h kemenno\u00f9 \"mont war-raok\" evit sikour ac'hanon da dizhout ar pal.", + "Maze.helpOneTopBlock": "El live-se az peus ezhomm da vernia\u00f1 bloc'ho\u00f9 an eil war egile en un takad labour gwenn.", + "Maze.helpRun": "Sevenit ho programm evit gwelet petra a c'hoarvez.", + "Maze.helpReset": "N'eo ket bet diskoulmet ar milendall gant ho programm. Pouezit war \"Adderaouekaat\" ha klaskit en-dro.", + "Maze.helpRepeat": "N'eus ket nemeur a vemor gant an urzhiataerio\u00f9. Implijit daou vloc'h hepken evit tizhout ar pal. Implijit ar bloc'h \"adober\" evit seveni\u00f1 ur bloc'h meur a wech.", + "Maze.helpCapacity": "Implijet eo bet ganeoc'h holl vloc'ho\u00f9 al live-ma\u00f1. Evit kroui\u00f1 ur bloc'h nevez e rankit dilemel ur bloc'h zo anezha\u00f1 da genta\u00f1.", + "Maze.helpRepeatMany": "Meur a vloc'h a c'haller lakaat en ur bloc'h 'adober'.", + "Maze.helpSkins": "Dibabit ho c'hoarier kareta\u00f1 el la\u00f1ser.", + "Maze.helpIf": "Ne raio ur bloc'h \"ma\" un dra bennak ken nemet ma'z eo gwir an amplegad. Klaskit trei\u00f1 a-gleiz ma'z eus un hent war an tu kleiz.", + "Maze.helpMenu": "Klikit war %1 er bloc'h \"ma\" evit che\u00f1ch e amplegad.", + "Maze.helpWallFollow": "Daoust ha gouest oc'h da ziskoulma\u00f1 ar milendall luziet-ma\u00f1 ? Klaskit mont a-hed ar voger gleiz. Evit ar brogrammerien arroutet-mat hepken !", + "Plane.rows": "Renkennado\u00f9 : %1", + "Plane.getRows": "renkennado\u00f9 (%1)", + "Plane.rows1": "Renkennado\u00f9 kenta\u00f1 klas : %1", + "Plane.getRows1": "Renkennado\u00f9 kenta\u00f1 klas (%1)", + "Plane.rows2": "Renkennado\u00f9 eil klas : %1", + "Plane.getRows2": "Renkennado\u00f9 eil klas (%1)", + "Plane.seats": "Azezenno\u00f9 : %1", + "Plane.placeholder": "?", + "Plane.setSeats": "azezenno\u00f9 =", + "Plane.plane": "Nijerez", + "Plane.description1": "Un nijerez he deus un toullad renkennado\u00f9 azezenno\u00f9 evit ar veajourien. Peder azezenn a zo e pep renkennad.", + "Plane.description2": "En un nijerez ez eus div azezenn el logell levia\u00f1(evit al loman hag an eil loman), hag ur toullad renkennado\u00f9 azezenno\u00f9 evit an dremenidi. Peder azezenn zo e pep renkennad.", + "Plane.description3": "En un nijerez ez eus div azezenn el logell levia\u00f1(evit al loman hag an eil loman), hag un toullad renkennado\u00f9 azezenno\u00f9 tremenidi kenta\u00f1 hag eil klas. Peder azezenn zo e pep renkennad kenta\u00f1 klas. Pemp azezenn zo e pemp renkennad eil klas.", + "Plane.instructions": "Sevel ur formulenn (ama\u00f1 dindan) evit jedi\u00f1 an niver a azezenno\u00f9 en holl en nijerez pa vez kemmet an niver a renkennado\u00f9 (ama\u00f1 a-us).", + "Puzzle.country1": "Aostralia", + "Puzzle.country1Language": "Saozneg", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://br.wikipedia.org/wiki/Aostralia", + "Puzzle.country2": "Alamagn", + "Puzzle.country2Language": "Alamaneg", + "Puzzle.country2City1": "Berlin", + "Puzzle.country2City2": "M\u00fcnchen", + "Puzzle.country2HelpUrl": "http://br.wikipedia.org/wiki/Alamagn", + "Puzzle.country3": "Sina", + "Puzzle.country3Language": "Sinaeg", + "Puzzle.country3City1": "Beijing", + "Puzzle.country3City2": "Shanghai", + "Puzzle.country3HelpUrl": "http://br.wikipedia.org/wiki/Sina", + "Puzzle.country4": "Brazil", + "Puzzle.country4Language": "Portugaleg", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "S\u00e3o Paulo", + "Puzzle.country4HelpUrl": "http://br.wikipedia.org/wiki/Brazil", + "Puzzle.flag": "banniel :", + "Puzzle.language": "yezh :", + "Puzzle.languageChoose": "dibab...", + "Puzzle.cities": "keodedo\u00f9 :", + "Puzzle.error0": "Dispar !\nReizh eo an/ar %1 bloc'h.", + "Puzzle.error1": "Tost ! Chom a ra ur bloc'h direizh.", + "Puzzle.error2": "%1 bloc'h direizh zo.", + "Puzzle.tryAgain": "Direizh eo ar bloc'h usskedet.\nKendalc'hit da bleustri\u00f1.", + "Puzzle.title": "Miltamm", + "Puzzle.help": "Skoazell", + "Puzzle.checkAnswers": "Gwiria\u00f1 ar responto\u00f9", + "Puzzle.helpText": "Evit kement bro (e gwer), staga\u00f1 he banniel, dibab he yezh, ha bernia\u00f1 he c'h\u00eario\u00f9.", + "Turtle.moveTooltip": "Lakaat ar vaot da vont war-raok pe da vont war-gil hervez ar c'hementad merket.", + "Turtle.moveForward": "Mont war-raok eus", + "Turtle.moveBackward": "Mont war-gil eus", + "Turtle.turnTooltip": "Lakaat ar vaot da drei\u00f1 a-gleiz pe a-zeho\u00f9 hervez an niver a zerezio\u00f9 merket.", + "Turtle.turnRight": "trei\u00f1 a-zehou da", + "Turtle.turnLeft": "Trei\u00f1 a-gleiz da", + "Turtle.widthTooltip": "Che\u00f1ch ledander ar stilo.", + "Turtle.setWidth": "lakaat al ledander da", + "Turtle.colourTooltip": "Che\u00f1ch liv ar stilo.", + "Turtle.setColour": "lakaat al liv da", + "Turtle.penTooltip": "Sevel pe diskenn ar stilo, evit paouez pe kregi\u00f1 da dresa\u00f1.", + "Turtle.penUp": "sevel ar stilo", + "Turtle.penDown": "lakaat ar stilo d'an trao\u00f1", + "Turtle.turtleVisibilityTooltip": "Lakaat a ra ar vaot (kelc'h ha biro\u00f9) war pe diwar wel.", + "Turtle.hideTurtle": "kuzhat ar vaot", + "Turtle.showTurtle": "diskouez ar vaot", + "Turtle.printHelpUrl": "http://en.wikipedia.org/wiki/Printing", + "Turtle.printTooltip": "Tresa\u00f1 an destenn war-zu ar vaot el lec'h m'ema\u00f1.", + "Turtle.print": "moulla\u00f1", + "Turtle.fontHelpUrl": "http://en.wikipedia.org/wiki/Font", + "Turtle.fontTooltip": "Termeni\u00f1 a ra ar font implijet gant ar bloc'h skriva\u00f1.", + "Turtle.font": "font", + "Turtle.fontSize": "ment ar font", + "Turtle.fontNormal": "reizh", + "Turtle.fontBold": "tev", + "Turtle.fontItalic": "italek", + "Turtle.unloadWarning": "Mar kuitait ar bajenn-ma\u00f1 e kollot ho labour.", + "Turtle.title": "Baot tresa\u00f1", + "Turtle.runTooltip": "Lakaat ar vaot d'ober ar pezh a lavar ar bloc'ho\u00f9.", + "Turtle.captureTooltip": "Enrolla\u00f1 an dresadenn.", + "Turtle.imgFilename": "tresadenn.png", + "Turtle.catTurtle": "Baot" +} \ No newline at end of file diff --git a/apps/json/ca.json b/apps/json/ca.json new file mode 100644 index 000000000..72873b855 --- /dev/null +++ b/apps/json/ca.json @@ -0,0 +1,145 @@ +{ + "@metadata": { + "authors": [ + "Alvaro Vidal-Abarca" + ] + }, + "Apps.subtitle": "un entorn visual de programaci\u00f3", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Veure el codi JavaScript generat.", + "Apps.linkTooltip": "Desa i enlla\u00e7a als blocs.", + "Apps.runTooltip": "Executa el programa definit pels blocs de l'\u00e0rea de treball.", + "Apps.runProgram": "Executa el programa", + "Apps.resetProgram": "Reinicialitza", + "Apps.dialogOk": "D'acord", + "Apps.dialogCancel": "Cancel\u00b7la", + "Apps.catLogic": "L\u00f2gica", + "Apps.catLoops": "Bucles", + "Apps.catMath": "Matem\u00e0tiques", + "Apps.catText": "Text", + "Apps.catLists": "Llistes", + "Apps.catColour": "Color", + "Apps.catVariables": "Variables", + "Apps.catProcedures": "Procediments", + "Apps.httpRequestError": "Hi ha hagut un problema amb la sol\u00b7licitud.", + "Apps.linkAlert": "Comparteix els teus blocs amb aquest enlla\u00e7: %1", + "Apps.hashError": "Ho sentim, '%1' no es correspon amb cap fitxer desat de Blockly.", + "Apps.xmlError": "No s'ha pogut carregar el teu fitxer desat. Potser va ser creat amb una versi\u00f3 diferent de Blockly?", + "Apps.listVariable": "llista", + "Apps.textVariable": "text", + "Code.badXml": "Error d'an\u00e0lisi XML:\n %1\n\nAbandonar els canvis?", + "Code.badCode": "Error de programa:\n %1", + "Code.timeout": "S'ha superat el nombre m\u00e0xim d'iteracions d'execuci\u00f3.", + "Code.discard": "Esborrar els %1 blocs?", + "Code.title": "Codi", + "Code.blocks": "Blocs", + "Code.trashTooltip": "Descarta tots els blocs.", + "Graph.title": "Calculadora gr\u00e0fica", + "Maze.moveForward": "mou endavant", + "Maze.turnLeft": "gira esquerra", + "Maze.turnRight": "gira dreta", + "Maze.doCode": "fes", + "Maze.elseCode": "si no", + "Maze.helpIfElse": "Les declaracions 'si-si no' faran fer una cosa o una altra.", + "Maze.pathAhead": "al davant", + "Maze.pathLeft": "si cam\u00ed a l'esquerra", + "Maze.pathRight": "si cam\u00ed a la dreta", + "Maze.repeatUntil": "repeteix fins al", + "Maze.moveForwardTooltip": "Mou el Pegman endavant un espai.", + "Maze.turnTooltip": "Gira el Pegman a l'esquerra o a la dreta 90 graus.", + "Maze.ifTooltip": "Si hi ha un cam\u00ed en la direcci\u00f3 especificada, llavors fes algunes accions.", + "Maze.ifelseTooltip": "Si hi ha un cam\u00ed en la direcci\u00f3 especificada, llavors fes el primer bloc d'accions. Si no, fes el segon bloc d'accions.", + "Maze.whileTooltip": "Repeteix les accions de dins del bloc fins arribar al punt final.", + "Maze.capacity0": "Et resten %0 blocs.", + "Maze.capacity1": "Et resten %1 blocs.", + "Maze.capacity2": "Et resten %2 blocs.", + "Maze.nextLevel": "Felicitats! Est\u00e0s preparat per a procedir amb el nivell %1?", + "Maze.finalLevel": "Felicitats! Has resolt el nivell final.", + "Maze.maze": "Laberint", + "Maze.runTooltip": "Fa que el jugador faci el que diuen els blocs.", + "Maze.resetTooltip": "Col\u00b7loca el jugador a l'inici del laberint.", + "Maze.helpStack": "Apila un parell de blocs 'mou endavant' junts per ajudar-me a arribar a la meta.", + "Maze.helpOneTopBlock": "En aquest nivell, has d'apilar junts tots els blocs a l'espai de treball blanc.", + "Maze.helpRepeat": "Els ordinadors tenen una mem\u00f2ria limitada. Arriba al final d'aquest cam\u00ed utilitzant nom\u00e9s dos blocs. Utilitza 'repeteix' per a executar un bloc m\u00e9s d'una vegada.", + "Maze.helpRepeatMany": "Arriba a la meta utilitzant nom\u00e9s cinc blocs.", + "Maze.helpIf": "Una condici\u00f3 'si' far\u00e0 fer alguna cosa nom\u00e9s si la condici\u00f3 \u00e9s certa. Prova de girar a l'esquerra si hi ha un cam\u00ed a l'esquerra.", + "Maze.helpWallFollow": "Pots resoldre aquest complicat laberint? Prova de seguir la paret de l'esquerra. Nom\u00e9s programadors avan\u00e7ats!", + "Plane.rows": "Files: %1", + "Plane.getRows": "files (%1)", + "Plane.rows1": "files de primera classe: %1", + "Plane.getRows1": "files de primera classe (%1)", + "Plane.rows2": "files de segona classe: %1", + "Plane.getRows2": "files de segona classe (%1)", + "Plane.seats": "Seients: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "seients =", + "Plane.plane": "Avi\u00f3", + "Plane.description1": "Un avi\u00f3 t\u00e9 un nombre de files de seients de passatgers. Cada fila cont\u00e9 quatre seients.", + "Plane.description2": "Un avi\u00f3 t\u00e9 dos seients en la cabina de vol (pel pilot i pel copilot) i un nombre de files de seients de passatgers. Cada fila cont\u00e9 quatre seients.", + "Plane.description3": "Un avi\u00f3 t\u00e9 dos seients en la cabina de vol (pel pilot i copilot) i un nombre de files per seients de passatgers de primera classe i de segona classe. Cada fila de primera classe cont\u00e9 quatre seients. Cada fila de segona classe cont\u00e9 cinc seients.", + "Plane.instructions": "Constru\u00efu una f\u00f3rmula (a sota) que calculi el nombre total de seients de l'avi\u00f3 a mida que canvi\u00efn les files (a dalt).", + "Puzzle.country1": "Austr\u00e0lia", + "Puzzle.country1Language": "Angl\u00e8s", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://en.wikipedia.org/wiki/Australia", + "Puzzle.country2": "Alemanya", + "Puzzle.country2Language": "Alemany", + "Puzzle.country2City1": "Berl\u00edn", + "Puzzle.country2City2": "Munic", + "Puzzle.country2HelpUrl": "https://ca.wikipedia.org/wiki/Alemanya", + "Puzzle.country3": "Xina", + "Puzzle.country3Language": "Xin\u00e8s", + "Puzzle.country3City1": "Pequ\u00edn", + "Puzzle.country3City2": "Xangai", + "Puzzle.country3HelpUrl": "https://ca.wikipedia.org/wiki/Xina", + "Puzzle.country4": "Brasil", + "Puzzle.country4Language": "Portugu\u00e8s", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "S\u00e3o Paulo", + "Puzzle.country4HelpUrl": "https://ca.wikipedia.org/wiki/Brasil", + "Puzzle.flag": "Bandera:", + "Puzzle.language": "Llengua:", + "Puzzle.languageChoose": "triar...", + "Puzzle.cities": "Ciutats:", + "Puzzle.error0": "Perfecte!\nTots els blocs de %1 s\u00f3n correctes.", + "Puzzle.error1": "Gaireb\u00e9! Una bloc \u00e9s incorrecte.", + "Puzzle.error2": "%1 blocs s\u00f3n err\u00f2nies.", + "Puzzle.tryAgain": "El bloc de subratllat no \u00e9s correcta.\nContinu\u00ef provant.", + "Puzzle.title": "Trencaclosques", + "Puzzle.help": "Ajuda", + "Puzzle.checkAnswers": "Comprovar les respostes", + "Puzzle.helpText": "Per a cada pa\u00eds (verd), adjuntar la seva bandera, escollir la seva llengua i fer una pila de les seves ciutats.", + "Turtle.moveTooltip": "Mou la tortuga endavant o enrere segons la quantitat especificada.", + "Turtle.moveForward": "moure endavant", + "Turtle.moveBackward": "moure enrere", + "Turtle.turnTooltip": "Gira la tortuga cap a l'esquerra o cap a la dreta el nombre especificat de graus.", + "Turtle.turnRight": "gira cap a la dreta", + "Turtle.turnLeft": "gira cap a l'esquerra", + "Turtle.widthTooltip": "Canvia el gruix de la ploma.", + "Turtle.setWidth": "canvia el gruix a", + "Turtle.colourTooltip": "Canvia el color de la ploma.", + "Turtle.setColour": "canvia el color a", + "Turtle.penTooltip": "Aixeca o abaixa la ploma, per acabar o comen\u00e7ar a dibuixar.", + "Turtle.penUp": "ploma amunt", + "Turtle.penDown": "ploma avall", + "Turtle.turtleVisibilityTooltip": "Fa que la tortuga (cercle i fletxa) sigui visible o invisible.", + "Turtle.hideTurtle": "amaga tortuga", + "Turtle.showTurtle": "mostra tortuga", + "Turtle.printHelpUrl": "https://ca.wikipedia.org/wiki/Impressi\u00f3", + "Turtle.printTooltip": "Dibuixa text en la direcci\u00f3 de la tortuga a partir de la seva posici\u00f3.", + "Turtle.print": "imprimir", + "Turtle.fontHelpUrl": "https://ca.wikipedia.org/wiki/Font_(tipografia)", + "Turtle.fontTooltip": "Canvia la font usada pel bloc d'impressi\u00f3.", + "Turtle.font": "font", + "Turtle.fontSize": "mida de lletra", + "Turtle.fontNormal": "normal", + "Turtle.fontBold": "negreta", + "Turtle.fontItalic": "cursiva", + "Turtle.unloadWarning": "Si abandona aquesta p\u00e0gina, perdr\u00e0 tota la feina.", + "Turtle.title": "Gr\u00e0fiques tortuga", + "Turtle.runTooltip": "Fa que la tortuga faci el que diuen els blocs.", + "Turtle.captureTooltip": "Desa el dibuix.", + "Turtle.imgFilename": "dibuix.png", + "Turtle.catTurtle": "Tortuga" +} \ No newline at end of file diff --git a/apps/json/cdo.json b/apps/json/cdo.json new file mode 100644 index 000000000..afa127b59 --- /dev/null +++ b/apps/json/cdo.json @@ -0,0 +1,35 @@ +{ + "Puzzle.tryAgain": "強調其鎖定𣍐正確。\n保持試蜀試。", + "Puzzle.country3City2": "上海", + "Puzzle.country3HelpUrl": "http://en.wikipedia.org/wiki/China", + "Puzzle.country3Language": "中文", + "Puzzle.checkAnswers": "檢查答案", + "Puzzle.language": "語言:", + "Apps.dialogOk": "確定", + "Puzzle.title": "謎", + "Puzzle.country1HelpUrl": "http://en.wikipedia.org/wiki/Australia", + "Puzzle.languageChoose": "選擇…", + "Puzzle.country4City2": "聖保羅", + "Puzzle.country4City1": "裡約熱內盧", + "Puzzle.country4Language": "葡萄牙語", + "Puzzle.helpText": "每蜀萆國家,連接伊其國旗,選擇伊其語言,再製造伊其城市其堆。", + "Puzzle.flag": "國旗:", + "Puzzle.country4HelpUrl": "http://en.wikipedia.org/wiki/Brazil", + "Puzzle.error1": "基本完成!蜀萆鎖定𣍐正確。", + "Puzzle.country3City1": "北京", + "Puzzle.country1City1": "墨爾本", + "Puzzle.country1City2": "悉尼", + "Puzzle.country2Language": "德語", + "Puzzle.country3": "中國", + "Puzzle.country2": "德國", + "Puzzle.country1": "澳大利亞", + "Puzzle.country2HelpUrl": "http://en.wikipedia.org/wiki/Germany", + "Puzzle.error0": "雅好!\n所有%1其鎖定都正確去了。", + "Puzzle.country4": "巴西", + "Puzzle.error2": "%1其鎖定𣍐正確。", + "Puzzle.help": "幫助", + "Puzzle.country1Language": "英語", + "Puzzle.country2City1": "柏林", + "Puzzle.cities": "城市:", + "Puzzle.country2City2": "慕尼黑" +} diff --git a/apps/json/cs.json b/apps/json/cs.json new file mode 100644 index 000000000..1db96b4b7 --- /dev/null +++ b/apps/json/cs.json @@ -0,0 +1,129 @@ +{ + "@metadata": { + "authors": [ + "Chmee2", + "Michaelbrabec" + ] + }, + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Zobraz generovan\u00fd JavaScriptov\u00fd k\u00f3d.", + "Apps.linkTooltip": "Ulo\u017e a spoj bloky..", + "Apps.runProgram": "Spus\u0165 program", + "Apps.resetProgram": "Reset", + "Apps.dialogOk": "OK", + "Apps.dialogCancel": "Zru\u0161it", + "Apps.catLogic": "Logika", + "Apps.catLoops": "Smy\u010dky", + "Apps.catMath": "Matematika", + "Apps.catText": "Text", + "Apps.catLists": "Seznamy", + "Apps.catColour": "Barva", + "Apps.catVariables": "Prom\u011bnn\u00e9", + "Apps.catProcedures": "Procedury", + "Apps.httpRequestError": "Do\u0161lo k pot\u00ed\u017e\u00edm s po\u017eadavkem.", + "Apps.linkAlert": "Sd\u00edlej bloky t\u00edmto odkazem: %1", + "Apps.hashError": "Omlouv\u00e1me se, '%1' nesouhlas\u00ed s \u017e\u00e1dn\u00fdm z ulo\u017een\u00fdch soubor\u016f.", + "Apps.xmlError": "Nepoda\u0159ilo se ulo\u017eit v\u00e1s soubor. Pravd\u011bpodobn\u011b byl vytvo\u0159en jinou verz\u00ed Blockly?", + "Apps.listVariable": "seznam", + "Apps.textVariable": "text", + "Code.badCode": "Chyba programu:\n%1", + "Code.discard": "Odstranit v\u0161echny bloky %1?", + "Code.title": "K\u00f3d", + "Code.blocks": "Bloky", + "Code.trashTooltip": "Zahodit v\u0161echny bloky.", + "Graph.title": "Grafick\u00e1 kalkula\u010dka", + "Maze.moveForward": "pohyb vp\u0159ed", + "Maze.turnLeft": "oto\u010dit lev\u00e1", + "Maze.turnRight": "oto\u010dit prav\u00e1", + "Maze.doCode": "ud\u011blej", + "Maze.elseCode": "jinak", + "Maze.helpIfElse": "P\u0159\u00edkaz 'pokud-jinak' provede bu\u010f n\u011bco, nebo n\u011bco jin\u00e9ho.", + "Maze.pathAhead": "pokud cesta vp\u0159ed", + "Maze.pathLeft": "pokud cesta doleva", + "Maze.pathRight": "pokud cesta doprava", + "Maze.repeatUntil": "opakuj a\u017e do", + "Maze.moveForwardTooltip": "Pohne Pegmanem vp\u0159ed o jedno pole.", + "Maze.turnTooltip": "Oto\u010d\u00ed Pegmana vlevo nebo vpravo o 90 stup\u0148\u016f.", + "Maze.ifTooltip": "Pokud je v dan\u00e9m sm\u011bru cesta, pak prove\u010f n\u011bjakou akci.", + "Maze.ifelseTooltip": "Pokud je v dann\u00e9m sm\u011bru cesta, pak prove\u010f posloupnost akc\u00ed. V opa\u010dn\u00e9m p\u0159\u00edpad\u011b prove\u010f druhou posloupnost akc\u00ed.", + "Maze.whileTooltip": "Opakuj obsa\u017een\u00e9 akce do t\u00e9 doby, dokud nen\u00ed dosa\u017een c\u00edlov\u00fd bod.", + "Maze.capacity0": "Po\u010det zb\u00fdvaj\u00edc\u00edch blok\u016f %0.", + "Maze.capacity1": "Po\u010det zb\u00fdvaj\u00edc\u00edch blok\u016f %1.", + "Maze.capacity2": "Po\u010det zb\u00fdvaj\u00edc\u00edch blok\u016f %2.", + "Maze.nextLevel": "Blahop\u0159ejeme! Jsi p\u0159ipraven vstoupit do levelu %1?", + "Maze.finalLevel": "Blahop\u0159ejeme! Vy\u0159e\u0161il jsi posledn\u00ed level.", + "Maze.maze": "Bludi\u0161t\u011b", + "Maze.runTooltip": "Hr\u00e1\u010d d\u011bl\u00e1 to, co bloky \u0159\u00edkaj\u00ed.", + "Maze.resetTooltip": "Postav hr\u00e1\u010de zp\u011bt na za\u010d\u00e1tek bludi\u0161t\u011b.", + "Maze.helpStack": "Poskl\u00e1dej n\u011bkolik pohyb\u016f vp\u0159ed dohromady a pomoc mi dos\u00e1hnout c\u00edle.", + "Maze.helpOneTopBlock": "V tomto levelu mus\u00ed\u0161 posb\u00edrat v\u0161echny bloky na b\u00edl\u00e9m pozad\u00ed.", + "Maze.helpRepeat": "Po\u010d\u00edta\u010de maj\u00ed omezenou pam\u011b\u0165. Dos\u00e1hni c\u00edle s pou\u017eit\u00edm pouze dvou blok\u016f. Pou\u017eij p\u0159\u00edkaz 'opakuj' pro zopakov\u00e1n\u00ed p\u0159\u00edkazu.", + "Maze.helpRepeatMany": "Dos\u00e1hni c\u00edle s pou\u017eit\u00edm peti blok\u016f.", + "Maze.helpIf": "Podm\u00ednka 'pokud' ud\u011bl\u00e1 n\u011bco pouze v p\u0159\u00edpad\u011b, \u017ee je spln\u011bna jej\u00ed podm\u00ednka. Zkus se oto\u010dit vlevo, pokud je nalevo cesta.", + "Maze.helpWallFollow": "Dok\u00e1\u017ee\u0161 vy\u0159e\u0161it toto komplikovan\u00e9 bludi\u0161t\u011b? Zkus se p\u0159idr\u017eovat zdi po lev\u00e9 ruce.", + "Plane.rows": "\u0158\u00e1dk\u016f: %1", + "Plane.getRows": "\u0159\u00e1dky (% 1)", + "Plane.rows1": "1. t\u0159\u00edda \u0159\u00e1dk\u016f: %1", + "Plane.getRows1": "1. t\u0159\u00edda \u0159\u00e1dk\u016f (%1)", + "Plane.rows2": "2. t\u0159\u00edda \u0159\u00e1dk\u016f: %1", + "Plane.getRows2": "2. t\u0159\u00edda \u0159\u00e1dk\u016f (%1)", + "Plane.seats": "Sedadla: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "sedadla =", + "Plane.plane": "Letadlo", + "Puzzle.country1": "Austr\u00e1lie", + "Puzzle.country1Language": "Angli\u010dtina", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://cs.wikipedia.org/wiki/Austr\u00e1lie", + "Puzzle.country2": "N\u011bmecko", + "Puzzle.country2Language": "N\u011bm\u010dina", + "Puzzle.country2City1": "Berl\u00edn", + "Puzzle.country2City2": "Mnichov", + "Puzzle.country2HelpUrl": "http://cs.wikipedia.org/wiki/N\u011bmecko", + "Puzzle.country3": "\u010c\u00edna", + "Puzzle.country3Language": "\u010c\u00edn\u0161tina", + "Puzzle.country3City1": "Peking", + "Puzzle.country3City2": "\u0160anghaj", + "Puzzle.country3HelpUrl": "http://cs.wikipedia.org/wiki/\u010c\u00edna", + "Puzzle.country4": "Braz\u00edlie", + "Puzzle.country4Language": "Portugal\u0161tina", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "S\u00e3o Paulo", + "Puzzle.country4HelpUrl": "http://cs.wikipedia.org/wiki/Braz\u00edlie", + "Puzzle.flag": "vlajka:", + "Puzzle.language": "jazyk:", + "Puzzle.languageChoose": "vyber...", + "Puzzle.cities": "m\u011bsta:", + "Puzzle.error0": "V\u00fdborn\u011b!\nV\u0161ech %1 blok\u016f je um\u00edst\u011bno spr\u00e1vn\u011b.", + "Puzzle.error1": "Skoro! Jeden blok je nespr\u00e1vn\u011b.", + "Puzzle.error2": "%1 bloky jsou chybn\u011b.", + "Puzzle.tryAgain": "Zv\u00fdrazn\u011bn\u00fd blok nen\u00ed spr\u00e1vn\u011b.\nZkou\u0161ej to d\u00e1l.", + "Puzzle.title": "Skl\u00e1da\u010dka", + "Puzzle.help": "Pomoc", + "Puzzle.checkAnswers": "Zkontrolovat odpov\u011bdi", + "Puzzle.helpText": "Pro ka\u017ed\u00fd st\u00e1t (zelen\u011b) p\u0159ipoj jeho vlajku, zvol jazyk a p\u0159i\u0159a\u010f m\u011bsta.", + "Turtle.moveForward": "P\u0159esunout vp\u0159ed", + "Turtle.moveBackward": "p\u0159esunout zp\u011bt", + "Turtle.turnRight": "oto\u010dit doprava o", + "Turtle.turnLeft": "oto\u010dit doleva o", + "Turtle.widthTooltip": "Zm\u011bn\u00ed tlou\u0161\u0165ku pera.", + "Turtle.setWidth": "nastavit \u0161\u00ed\u0159ku na", + "Turtle.colourTooltip": "Zm\u011bn\u00ed barvu pera.", + "Turtle.setColour": "nastavit barvu na", + "Turtle.hideTurtle": "skr\u00fdt \u017eelvu", + "Turtle.showTurtle": "zobrazit \u017eelvu", + "Turtle.printHelpUrl": "http://cs.wikipedia.org/wiki/Tiska%C5%99stv%C3%AD", + "Turtle.print": "vytisknout", + "Turtle.fontHelpUrl": "http://cs.wikipedia.org/wiki/Font", + "Turtle.font": "p\u00edsmo", + "Turtle.fontSize": "velikost p\u00edsma", + "Turtle.fontNormal": "norm\u00e1ln\u00ed", + "Turtle.fontBold": "tu\u010dn\u00e9", + "Turtle.fontItalic": "kurz\u00edva", + "Turtle.unloadWarning": "Opu\u0161t\u011bn\u00ed t\u00e9to str\u00e1nky bude m\u00edt za n\u00e1sledek ztr\u00e1tu va\u0161\u00ed pr\u00e1ce.", + "Turtle.title": "\u017delv\u00ed grafika", + "Turtle.captureTooltip": "Ulo\u017ete v\u00fdkres.", + "Turtle.imgFilename": "kresba.png", + "Turtle.catTurtle": "\u017delva" +} \ No newline at end of file diff --git a/apps/json/da.json b/apps/json/da.json new file mode 100644 index 000000000..9393cdbec --- /dev/null +++ b/apps/json/da.json @@ -0,0 +1,153 @@ +{ + "@metadata": { + "authors": [ + "Christian List", + "Hein0170", + "Peter Alberti", + "Simeondahl" + ] + }, + "Apps.subtitle": "et visuelt programmeringsmilj\u00f8", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Se den genererede JavaScript kode.", + "Apps.linkTooltip": "Gem og link til blokke.", + "Apps.runTooltip": "K\u00f8r programmet, der er defineret af blokkene i arbejdsomr\u00e5det.", + "Apps.runProgram": "K\u00f8r program", + "Apps.resetProgram": "Nulstil", + "Apps.dialogOk": "OK", + "Apps.dialogCancel": "Afbryd", + "Apps.catLogic": "Logik", + "Apps.catLoops": "L\u00f8kker", + "Apps.catMath": "Matematik", + "Apps.catText": "Tekst", + "Apps.catLists": "Lister", + "Apps.catColour": "Farve", + "Apps.catVariables": "Variabler", + "Apps.catProcedures": "Procedurer", + "Apps.httpRequestError": "Der var et problem med foresp\u00f8rgslen.", + "Apps.linkAlert": "Del dine blokke med dette link:\n\n%1", + "Apps.hashError": "Beklager, '%1' passer ikke med nogen gemt Blockly fil.", + "Apps.xmlError": "Kunne ikke hente din gemte fil. M\u00e5ske er den lavet med en anden udgave af Blockly?", + "Apps.listVariable": "liste", + "Apps.textVariable": "tekst", + "Code.badXml": "Fejl under fortolkningen af XML:\n%1\n\nV\u00e6lg 'OK' for at opgive dine \u00e6ndringer eller 'Afbryd' for at redigere XML-filen yderligere.", + "Code.badCode": "Programfejl:\n%1", + "Code.timeout": "Maksimale antal udf\u00f8relsesgentagelser overskredet.", + "Code.discard": "Slet alle %1 blokke?", + "Code.title": "Kode", + "Code.blocks": "Blokke", + "Code.trashTooltip": "Kass\u00e9r alle blokke.", + "Graph.title": "Grafisk lommeregner", + "Maze.moveForward": "flyt fremad", + "Maze.turnLeft": "drej til venstre", + "Maze.turnRight": "drej til h\u00f8jre", + "Maze.doCode": "udf\u00f8r", + "Maze.elseCode": "ellers", + "Maze.helpIfElse": "Hvis-ellers blokke vil g\u00f8re den ene eller den anden ting.", + "Maze.pathAhead": "hvis sti fremad", + "Maze.pathLeft": "hvis sti til venstre", + "Maze.pathRight": "hvis sti til h\u00f8jre", + "Maze.repeatUntil": "gentag indtil", + "Maze.moveForwardTooltip": "Flytter spilleren et felt fremad.", + "Maze.turnTooltip": "Drejer spilleren 90 grader til h\u00f8jre eller venstre.", + "Maze.ifTooltip": "Hvis der er en sti i den angivne retning, s\u00e5 udf\u00f8r nogle handlinger.", + "Maze.ifelseTooltip": "Hvis der er en sti i den angivne retning, s\u00e5 udf\u00f8r den f\u00f8rste handlingsblok. Hvis ikke, s\u00e5 udf\u00f8r den anden handlingsblok.", + "Maze.whileTooltip": "Gentag handlingsblok indtil slutpunktet er n\u00e5et.", + "Maze.capacity0": "Du har %0 blokke tilbage.", + "Maze.capacity1": "Du har %1 blok tilbage.", + "Maze.capacity2": "Du har %2 blokke tilbage.", + "Maze.nextLevel": "Tillykke! Er du klar til at forts\u00e6tte til bane %1?", + "Maze.finalLevel": "Tillykke! Du har klaret den sidste bane.", + "Maze.maze": "Labyrint", + "Maze.runTooltip": "F\u00e5r spilleren til at g\u00f8re det blokkene siger.", + "Maze.resetTooltip": "S\u00e6tter spilleren tilbage til starten af labyrinten.", + "Maze.helpStack": "S\u00e6t et par 'flyt fremad' blokke sammen for at hj\u00e6lpe mig til at n\u00e5 m\u00e5let,", + "Maze.helpOneTopBlock": "P\u00e5 denne bane skal du s\u00e6tte alle blokkene sammen i det hvide arbejdsfelt.", + "Maze.helpRun": "K\u00f8r dit program for at se, hvad der sker.", + "Maze.helpReset": "Dit program l\u00f8ste ikke labyrinten. Tryk p\u00e5 'Nulstil', og pr\u00f8v igen.", + "Maze.helpRepeat": "Pr\u00f8v at n\u00e5 enden af denne sti ved kun at bruge to blokke. Brug 'gentag indtil' til at k\u00f8re en blok mere end \u00e9n gang.", + "Maze.helpCapacity": "Du har opbrugt alle blokkene for dette niveau. Hvis du vil oprette en ny blok, skal du f\u00f8rst slette en eksisterende blok.", + "Maze.helpRepeatMany": "Der er plads til mere end \u00e9n blok inde i en 'gentag indtil' blok.", + "Maze.helpSkins": "V\u00e6lg din favoritspiller fra denne menu.", + "Maze.helpIf": "En 'hvis'-blok vil kun g\u00f8re noget hvis betingelsen er sand. Pr\u00f8v at dreje til venstre hvis der er en sti til venstre.", + "Maze.helpMenu": "Klik p\u00e5 %1 i 'hvis' blokken for at \u00e6ndre dens tilstand.", + "Maze.helpWallFollow": "Kan du l\u00f8se denne komplicerede labyrint? Pr\u00f8v at f\u00f8lge v\u00e6ggen p\u00e5 venstre h\u00e5nd. Kun for avancerede programm\u00f8rer!", + "Plane.rows": "R\u00e6kker: %1", + "Plane.getRows": "r\u00e6kker (%1)", + "Plane.rows1": "1. klasse r\u00e6kker: %1", + "Plane.getRows1": "1. klasse r\u00e6kker (%1)", + "Plane.rows2": "2. klasse r\u00e6kker: %1", + "Plane.getRows2": "2. klasse r\u00e6kker (%1)", + "Plane.seats": "S\u00e6der: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "s\u00e6der =", + "Plane.plane": "Fly", + "Plane.description1": "Et fly har et antal r\u00e6kker af passagers\u00e6der. Hver r\u00e6kke indeholder fire s\u00e6der.", + "Plane.description2": "Et fly har to pladser i cockpittet (til pilot og med-pilot), og et antal r\u00e6kker af passagers\u00e6der. Hver r\u00e6kke indeholder fire s\u00e6der.", + "Plane.description3": "Et fly har to pladser i cockpittet (til pilot og med-pilot), og et antal r\u00e6kker af 1. klasses og 2. klasses passagers\u00e6der. Hver 1. klasses r\u00e6kke indeholder fire s\u00e6der. Hver 2. klasses r\u00e6kke indeholder fem s\u00e6der.", + "Plane.instructions": "Opbyg en formel (nedenfor), der beregner det samlede antal pladser p\u00e5 flyet, hvis antal r\u00e6kker \u00e6ndres (ovenfor).", + "Puzzle.country1": "Australien", + "Puzzle.country1Language": "Engelsk", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://da.wikipedia.org/wiki/Australien", + "Puzzle.country2": "Tyskland", + "Puzzle.country2Language": "Tysk", + "Puzzle.country2City1": "Berlin", + "Puzzle.country2City2": "M\u00fcnchen", + "Puzzle.country2HelpUrl": "http://da.wikipedia.org/wiki/Tyskland", + "Puzzle.country3": "Kina", + "Puzzle.country3Language": "Kinesisk", + "Puzzle.country3City1": "Beijing", + "Puzzle.country3City2": "Shanghai", + "Puzzle.country3HelpUrl": "http://da.wikipedia.org/wiki/Kina", + "Puzzle.country4": "Brasilien", + "Puzzle.country4Language": "Portugisisk", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "S\u00e3o Paulo", + "Puzzle.country4HelpUrl": "http://da.wikipedia.org/wiki/Brasilien", + "Puzzle.flag": "flag:", + "Puzzle.language": "sprog:", + "Puzzle.languageChoose": "v\u00e6lg...", + "Puzzle.cities": "byer:", + "Puzzle.error0": "Perfekt!\nAlle %1 blokke er rigtige.", + "Puzzle.error1": "N\u00e6sten! En blok er forkert.", + "Puzzle.error2": "%1 blokke er forkerte.", + "Puzzle.tryAgain": "Den fremh\u00e6vede blok er ikke rigtig.\nBliv ved med at pr\u00f8ve.", + "Puzzle.title": "Puslespil", + "Puzzle.help": "Hj\u00e6lp", + "Puzzle.checkAnswers": "Kontroller svarene", + "Puzzle.helpText": "For hvert land (gr\u00f8n), tilknyt dets flag, v\u00e6lg dets sprog og lav en stabel med dets byer.", + "Turtle.moveTooltip": "Bev\u00e6ger skildpadden frem eller tilbage med den angivne v\u00e6rdi.", + "Turtle.moveForward": "flyt fremad med", + "Turtle.moveBackward": "flyt bagud med", + "Turtle.turnTooltip": "Drejer skildpadden til venstre eller h\u00f8jre med det angivne antal grader.", + "Turtle.turnRight": "drej til h\u00f8jre med", + "Turtle.turnLeft": "drej til venstre med", + "Turtle.widthTooltip": "\u00c6ndrer bredden p\u00e5 pennen.", + "Turtle.setWidth": "s\u00e6t bredden til", + "Turtle.colourTooltip": "\u00c6ndrer farven p\u00e5 pennen.", + "Turtle.setColour": "s\u00e6t farve til", + "Turtle.penTooltip": "L\u00f8fter eller s\u00e6nker pennen, for at stoppe eller starte tegning.", + "Turtle.penUp": "pennen op", + "Turtle.penDown": "pennen ned", + "Turtle.turtleVisibilityTooltip": "G\u00f8r skildpadden (cirkel og pil) synlig eller usynlig.", + "Turtle.hideTurtle": "skjul skildpadde", + "Turtle.showTurtle": "vis skildpadde", + "Turtle.printHelpUrl": "http://da.wikipedia.org/wiki/Bogtryk", + "Turtle.printTooltip": "Skriver tekst i skildpaddens retning p\u00e5 dens placering.", + "Turtle.print": "skriv", + "Turtle.fontHelpUrl": "http://da.wikipedia.org/wiki/Skrifttype", + "Turtle.fontTooltip": "Angiver den skrifttype, der bruges af skriveblokken.", + "Turtle.font": "skrifttype", + "Turtle.fontSize": "skriftst\u00f8rrelse", + "Turtle.fontNormal": "normal", + "Turtle.fontBold": "fed", + "Turtle.fontItalic": "kursiv", + "Turtle.unloadWarning": "Hvis du forlader denne side vil det resultere i tab af dit arbejde.", + "Turtle.title": "Skildpaddegrafik", + "Turtle.runTooltip": "F\u00e5r skildpadden til at g\u00f8re det blokkene siger.", + "Turtle.captureTooltip": "Gem tegningen.", + "Turtle.imgFilename": "tegning.png", + "Turtle.catTurtle": "Skildpadde" +} \ No newline at end of file diff --git a/apps/json/de.json b/apps/json/de.json new file mode 100644 index 000000000..c2a7f94b8 --- /dev/null +++ b/apps/json/de.json @@ -0,0 +1,150 @@ +{ + "@metadata": { + "authors": [ + "Metalhead64" + ] + }, + "Apps.subtitle": "Visuelle Programmierumgebung", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Erzeugten JavaScript-Code ansehen.", + "Apps.linkTooltip": "Speichern und auf Bausteine verlinken.", + "Apps.runTooltip": "Das Programm ausf\u00fchren, das von den Bausteinen im Arbeitsbereich definiert ist.", + "Apps.runProgram": "Programm ausf\u00fchren", + "Apps.resetProgram": "Zur\u00fccksetzen", + "Apps.dialogOk": "Okay", + "Apps.dialogCancel": "Abbrechen", + "Apps.catLogic": "Logik", + "Apps.catLoops": "Schleifen", + "Apps.catMath": "Mathematik", + "Apps.catText": "Text", + "Apps.catLists": "Listen", + "Apps.catColour": "Farbe", + "Apps.catVariables": "Variablen", + "Apps.catProcedures": "Funktionen", + "Apps.httpRequestError": "Mit der Anfrage gab es ein Problem.", + "Apps.linkAlert": "Teile deine Bausteine mit diesem Link:\n\n%1", + "Apps.hashError": "\u201e%1\u201c stimmt leider mit keinem gespeicherten Programm \u00fcberein.", + "Apps.xmlError": "Deine gespeicherte Datei konnte nicht geladen werden. Vielleicht wurde sie mit einer anderen Version von Blockly erstellt.", + "Apps.listVariable": "Liste", + "Apps.textVariable": "Text", + "Code.badXml": "Fehler beim Parsen von XML:\n%1\n\nW\u00e4hle 'OK' zum Verwerfen deiner \u00c4nderungen oder 'Abbrechen' zum weiteren Bearbeiten des XML.", + "Code.badCode": "Programmfehler:\n%1", + "Code.timeout": "Die maximalen Ausf\u00fchrungswiederholungen wurden \u00fcberschritten.", + "Code.discard": "Alle %1 Bausteine l\u00f6schen?", + "Code.title": "Code", + "Code.blocks": "Bausteine", + "Code.trashTooltip": "Alle Bausteine verwerfen.", + "Graph.title": "Grafikrechner", + "Maze.moveForward": "vorw\u00e4rts laufen", + "Maze.turnLeft": "links abbiegen", + "Maze.turnRight": "rechts abbiegen", + "Maze.doCode": "ausf\u00fchren", + "Maze.elseCode": "sonst", + "Maze.helpIfElse": "Wenn-Sonst-Bausteine f\u00fchren das eine oder das andere aus.", + "Maze.pathAhead": "wenn Pfad davor ist", + "Maze.pathLeft": "wenn Pfad nach links ist", + "Maze.pathRight": "wenn Pfad nach rechts ist", + "Maze.repeatUntil": "wiederholen bis", + "Maze.moveForwardTooltip": "Bewegt den Spieler ein Feld vor.", + "Maze.turnTooltip": "Dreht den Spieler um 90 Grad nach links oder rechts.", + "Maze.ifTooltip": "Falls es einen Pfad in der angegebenen Richtung gibt, dann einige Aktionen ausf\u00fchren.", + "Maze.ifelseTooltip": "Falls es einen Pfad in der angegebenen Richtung gibt, dann den ersten Aktionenbaustein ausf\u00fchren, anderenfalls den zweiten.", + "Maze.whileTooltip": "Die beigef\u00fcgten Aktionen wiederholen, bis das Ziel erreicht wurde.", + "Maze.capacity0": "Du hast noch %0 Bausteine.", + "Maze.capacity1": "Du hast noch %1 Baustein.", + "Maze.capacity2": "Du hast noch %2 Bausteine.", + "Maze.nextLevel": "Gratulation! In das Level %1 gehen?", + "Maze.finalLevel": "Gratulation! Du hast das Spiel beendet.", + "Maze.maze": "Labyrinth", + "Maze.runTooltip": "Der Spieler macht das, was die Bausteine sagen.", + "Maze.resetTooltip": "Setzt den Spieler an den Start des Labyrinths zur\u00fcck.", + "Maze.helpStack": "Verbinde einige 'laufe vorw\u00e4rts' Bl\u00f6cke, um mir zu helfen um das Ziel zu erreichen.", + "Maze.helpOneTopBlock": "In diesem Level musst du die ganzen Bausteine in dem wei\u00dfen Arbeitsbereich zusammenstapeln.", + "Maze.helpRun": "F\u00fchre dein Programm aus, um zu sehen, was passiert.", + "Maze.helpReset": "Dein Programm l\u00f6st das Labyrinth nicht. Dr\u00fccke 'Zur\u00fccksetzen' und versuche es erneut.", + "Maze.helpRepeat": "Computer haben begrenzten Speicher. Erreiche das Ende dieses Pfads mit nur zwei Bausteinen. Benutze \u201eWiederholen\u201c, um einen Baustein mehr als einmal auszuf\u00fchren.", + "Maze.helpCapacity": "Du hast f\u00fcr dieses Level alle Bausteine aufgebraucht. Um einen neuen Baustein zu erstellen, musst du zuerst einen vorhandenen Baustein l\u00f6schen.", + "Maze.helpRepeatMany": "Sie k\u00f6nnen mehrere Bl\u00f6cke innerhalb eines Blocks 'repeat' passen.", + "Maze.helpSkins": "W\u00e4hle deinen Lieblingsspieler vom Men\u00fc aus.", + "Maze.helpIf": "Ein \u201eWenn\u201c-Baustein macht etwas, falls die Bedingung wahr ist. Versuche links abzubiegen, falls es einen Pfad nach links gibt.", + "Maze.helpMenu": "Klicke auf %1 im 'Wenn'-Baustein um die Bedingung zu \u00e4ndern.", + "Maze.helpWallFollow": "Kannst du dieses komplizierte Labyrinth l\u00f6sen? Folge der linken Wand. Nur f\u00fcr fortgeschrittene Programmierer!", + "Plane.rows": "Reihen: %1", + "Plane.getRows": "Reihen (%1)", + "Plane.rows1": "Reihen der 1. Klasse: %1", + "Plane.getRows1": "Reihen der 1. Klasse (%1)", + "Plane.rows2": "Reihen der 2. Klasse: %1", + "Plane.getRows2": "Reihen der 2. Klasse (%1)", + "Plane.seats": "Sitze: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "Sitze =", + "Plane.plane": "Flugzeug", + "Plane.description1": "Ein Flugzeug hat eine Anzahl an Reihen mit Passagiersitzen. Jede Reihe enth\u00e4lt vier Sitze.", + "Plane.description2": "Ein Flugzeug hat zwei Sitze im Pilotenstand (f\u00fcr den Piloten und Co-Piloten) und eine Anzahl an Reihen mit Passagiersitzen. Jede Reihe enth\u00e4lt vier Sitze.", + "Plane.description3": "Ein Flugzeug hat zwei Sitze im Pilotenstand (f\u00fcr den Piloten und Co-Piloten) und eine Anzahl an Reihen mit Passagiersitzen der 1. und 2. Klasse. Jede 1.-Klasse-Reihe enth\u00e4lt vier Sitze. Jede 2.-Klasse-Reihe enth\u00e4lt f\u00fcnf Sitze.", + "Plane.instructions": "Erstelle eine Formel (unten), die die gesamte Anzahl an Sitzen im Flugzeug berechnet, wenn die Reihen (oben) ge\u00e4ndert werden.", + "Puzzle.country1": "Australien", + "Puzzle.country1Language": "Englisch", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://de.wikipedia.org/wiki/Australien", + "Puzzle.country2": "Deutschland", + "Puzzle.country2Language": "Deutsch", + "Puzzle.country2City1": "Berlin", + "Puzzle.country2City2": "M\u00fcnchen", + "Puzzle.country2HelpUrl": "http://de.wikipedia.org/wiki/Deutschland", + "Puzzle.country3": "Volksrepublik China", + "Puzzle.country3Language": "Chinesisch", + "Puzzle.country3City1": "Peking", + "Puzzle.country3City2": "Shanghai", + "Puzzle.country3HelpUrl": "http://de.wikipedia.org/wiki/Volksrepublik_China", + "Puzzle.country4": "Brasilien", + "Puzzle.country4Language": "Portugiesisch", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "S\u00e3o Paulo", + "Puzzle.country4HelpUrl": "http://de.wikipedia.org/wiki/Brasilien", + "Puzzle.flag": "Flagge:", + "Puzzle.language": "Sprache:", + "Puzzle.languageChoose": "w\u00e4hle \u2026", + "Puzzle.cities": "St\u00e4dte:", + "Puzzle.error0": "Perfekt! Alle %1 Bausteine sind richtig.", + "Puzzle.error1": "Fast! Ein Baustein ist falsch.", + "Puzzle.error2": "%1 Bausteine sind falsch.", + "Puzzle.tryAgain": "Der hervorgehobene Baustein ist falsch. Versuche es noch einmal.", + "Puzzle.title": "Puzzle", + "Puzzle.help": "Hilfe", + "Puzzle.checkAnswers": "Antworten \u00fcberpr\u00fcfen", + "Puzzle.helpText": "H\u00e4nge f\u00fcr jeden Staat (gr\u00fcn) seine Flagge an, w\u00e4hle seine Sprache aus und mache einen Stapel mit seinen St\u00e4dten.", + "Turtle.moveTooltip": "Bewegt die Schildkr\u00f6te um den angegebenen Wert vorw\u00e4rts oder r\u00fcckw\u00e4rts.", + "Turtle.moveForward": "vorw\u00e4rts bewegen um", + "Turtle.moveBackward": "r\u00fcckw\u00e4rts bewegen um", + "Turtle.turnTooltip": "Dreht die Schildkr\u00f6te nach links oder rechts um die angegebene Gradanzahl.", + "Turtle.turnRight": "nach rechts drehen um", + "Turtle.turnLeft": "nach links drehen um", + "Turtle.widthTooltip": "\u00c4ndert die Breite des Stiftes.", + "Turtle.setWidth": "Breite setzen auf", + "Turtle.colourTooltip": "\u00c4ndert die Farbe des Stiftes.", + "Turtle.setColour": "\u00e4ndert die Farbe in", + "Turtle.penTooltip": "Hebt oder senkt den Stift zum Stoppen oder Starten der Zeichnung.", + "Turtle.penUp": "Stift nach oben", + "Turtle.penDown": "Stift nach unten", + "Turtle.turtleVisibilityTooltip": "Macht die Schildkr\u00f6te (Kreis und Pfeil) sichtbar oder unsichtbar.", + "Turtle.hideTurtle": "Schildkr\u00f6te ausblenden", + "Turtle.showTurtle": "Schildkr\u00f6te anzeigen", + "Turtle.printHelpUrl": "http://de.wikipedia.org/wiki/Buchdruck", + "Turtle.printTooltip": "Zeichnet Text in der Richtung der Schildkr\u00f6te bei ihrem Standort.", + "Turtle.print": "drucken", + "Turtle.fontHelpUrl": "http://de.wikipedia.org/wiki/Schriftschnitt", + "Turtle.fontTooltip": "Legt die Schriftart fest, die vom Druck-Baustein verwendet wird.", + "Turtle.font": "Schriftart", + "Turtle.fontSize": "Schriftgr\u00f6\u00dfe", + "Turtle.fontNormal": "normal", + "Turtle.fontBold": "fett", + "Turtle.fontItalic": "kursiv", + "Turtle.unloadWarning": "Das Verlassen dieser Seite f\u00fchrt zum Verlust deiner Arbeit.", + "Turtle.title": "Turtle-Grafiken", + "Turtle.runTooltip": "Die Schildkr\u00f6te macht das, was die Bausteine sagen.", + "Turtle.captureTooltip": "Zeichnung speichern.", + "Turtle.imgFilename": "zeichnung.png", + "Turtle.catTurtle": "Schildkr\u00f6te" +} \ No newline at end of file diff --git a/apps/json/diq.json b/apps/json/diq.json new file mode 100644 index 000000000..8ae6fea22 --- /dev/null +++ b/apps/json/diq.json @@ -0,0 +1,30 @@ +{ + "Puzzle.country3City2": "Şangay", + "Puzzle.country3HelpUrl": "http://en.wikipedia.org/wiki/China", + "Puzzle.country3Language": "Çinki", + "Puzzle.checkAnswers": "Netican kontrol ke", + "Puzzle.language": "Zıwan:", + "Apps.dialogOk": "TEMAM", + "Puzzle.title": "Puzzle", + "Puzzle.country1HelpUrl": "http://en.wikipedia.org/wiki/Australia", + "Puzzle.languageChoose": "weçine...", + "Puzzle.country4City2": "Sao Paulo", + "Puzzle.country4City1": "Rio de Ceneryo", + "Puzzle.country4Language": "Portekız", + "Puzzle.flag": "desmal", + "Puzzle.country4HelpUrl": "http://en.wikipedia.org/wiki/Brazil", + "Puzzle.country3City1": "Pekin", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sidney", + "Puzzle.country2Language": "Alman", + "Puzzle.country3": "Çin", + "Puzzle.country2": "Almanya", + "Puzzle.country1": "Awıstralya", + "Puzzle.country2HelpUrl": "http://en.wikipedia.org/wiki/Germany", + "Puzzle.country4": "Brezilya", + "Puzzle.help": "Peşti", + "Puzzle.country1Language": "Ingiliz", + "Puzzle.country2City1": "Berlin", + "Puzzle.cities": "suki:", + "Puzzle.country2City2": "Munix" +} diff --git a/apps/json/el.json b/apps/json/el.json new file mode 100644 index 000000000..56245ee02 --- /dev/null +++ b/apps/json/el.json @@ -0,0 +1,153 @@ +{ + "@metadata": { + "authors": [ + "Azountas", + "Evropi", + "Namatreasure", + "Tifa93" + ] + }, + "Apps.subtitle": "\u0388\u03bd\u03b1 \u03bf\u03c0\u03c4\u03b9\u03ba\u03cc \u03c0\u03b5\u03c1\u03b9\u03b2\u03ac\u03bb\u03bb\u03bf\u03bd \u03c0\u03c1\u03bf\u03b3\u03c1\u03b1\u03bc\u03bc\u03b1\u03c4\u03b9\u03c3\u03bc\u03bf\u03cd", + "Apps.blocklyMessage": "Blockly (\u039c\u03c0\u03bb\u03cc\u03ba\u03bb\u03b9)", + "Apps.codeTooltip": "\u0394\u03b5\u03c2 \u03c4\u03bf\u03bd \u03ba\u03ce\u03b4\u03b9\u03ba\u03b1 JavaScript \u03c0\u03bf\u03c5 \u03b4\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03ae\u03b8\u03b7\u03ba\u03b5.", + "Apps.linkTooltip": "\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7 \u03ba\u03b1\u03b9 \u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7 \u03c3\u03c4\u03bf \u03bc\u03c0\u03bb\u03bf\u03ba.", + "Apps.runTooltip": "\u0395\u03ba\u03c4\u03ad\u03bb\u03b5\u03c3\u03b5 \u03c4\u03bf \u03c0\u03c1\u03cc\u03b3\u03c1\u03b1\u03bc\u03bc\u03b1 \u03c0\u03bf\u03c5 \u03bf\u03c1\u03af\u03b6\u03b5\u03c4\u03b1\u03b9 \u03b1\u03c0\u03cc \u03c4\u03b1 \u03bc\u03c0\u03bb\u03bf\u03ba \u03c3\u03c4\u03bf \u03c7\u03ce\u03c1\u03bf \u03b5\u03c1\u03b3\u03b1\u03c3\u03af\u03b1\u03c2.", + "Apps.runProgram": "\u0395\u03ba\u03c4\u03ad\u03bb\u03b5\u03c3\u03b7 \u03a0\u03c1\u03bf\u03b3\u03c1\u03ac\u03bc\u03bc\u03b1\u03c4\u03bf\u03c2", + "Apps.resetProgram": "\u0395\u03c0\u03b1\u03bd\u03b5\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7", + "Apps.dialogOk": "\u039f\u039a", + "Apps.dialogCancel": "\u0391\u03ba\u03cd\u03c1\u03c9\u03c3\u03b7", + "Apps.catLogic": "\u039b\u03bf\u03b3\u03b9\u03ba\u03ae", + "Apps.catLoops": "\u0395\u03c0\u03b1\u03bd\u03b1\u03bb\u03ae\u03c8\u03b5\u03b9\u03c2", + "Apps.catMath": "\u039c\u03b1\u03b8\u03b7\u03bc\u03b1\u03c4\u03b9\u03ba\u03ac", + "Apps.catText": "\u039a\u03b5\u03af\u03bc\u03b5\u03bd\u03bf", + "Apps.catLists": "\u039b\u03af\u03c3\u03c4\u03b5\u03c2", + "Apps.catColour": "\u03a7\u03c1\u03ce\u03bc\u03b1", + "Apps.catVariables": "\u039c\u03b5\u03c4\u03b1\u03b2\u03bb\u03b7\u03c4\u03ad\u03c2", + "Apps.catProcedures": "\u0394\u03b9\u03b1\u03b4\u03b9\u03ba\u03b1\u03c3\u03af\u03b5\u03c2", + "Apps.httpRequestError": "\u03a5\u03c0\u03ae\u03c1\u03be\u03b5 \u03c0\u03c1\u03cc\u03b2\u03bb\u03b7\u03bc\u03b1 \u03bc\u03b5 \u03c4\u03bf \u03b1\u03af\u03c4\u03b7\u03bc\u03b1.", + "Apps.linkAlert": "\u039c\u03bf\u03b9\u03c1\u03ac\u03c3\u03bf\u03c5 \u03c4\u03b1 blocks \u03c3\u03bf\u03c5 \u03bc\u03b5 \u03b1\u03c5\u03c4\u03cc \u03c4\u03bf \u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03bc\u03bf:\n\n%1", + "Apps.hashError": "\u039b\u03c5\u03c0\u03ac\u03bc\u03b1\u03b9, \u03c4\u03bf \u00ab%1\u00bb \u03b4\u03b5\u03bd \u03b1\u03bd\u03c4\u03b9\u03c3\u03c4\u03bf\u03b9\u03c7\u03b5\u03af \u03c3\u03b5 \u03ba\u03b1\u03bd\u03ad\u03bd\u03b1 \u03b1\u03c0\u03bf\u03b8\u03b7\u03ba\u03b5\u03c5\u03bc\u03ad\u03bd\u03bf \u03c0\u03c1\u03cc\u03b3\u03c1\u03b1\u03bc\u03bc\u03b1.", + "Apps.xmlError": "\u0394\u03b5\u03bd \u03bc\u03c0\u03bf\u03c1\u03ce \u03bd\u03b1 \u03c6\u03bf\u03c1\u03c4\u03ce\u03c3\u03c9 \u03c4\u03bf \u03b1\u03c0\u03bf\u03b8\u03b7\u03ba\u03b5\u03c5\u03bc\u03ad\u03bd\u03bf \u03b1\u03c1\u03c7\u03b5\u03af\u03bf \u03c3\u03bf\u03c5. \u039c\u03ae\u03c0\u03c9\u03c2 \u03b4\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03ae\u03b8\u03b7\u03ba\u03b5 \u03b1\u03c0\u03cc \u03bc\u03af\u03b1 \u03c0\u03b1\u03bb\u03b9\u03cc\u03c4\u03b5\u03c1\u03b7 \u03ad\u03ba\u03b4\u03bf\u03c3\u03b7 \u03c4\u03bf\u03c5 \u039c\u03c0\u03bb\u03cc\u03ba\u03bb\u03b9.", + "Apps.listVariable": "\u039b\u03af\u03c3\u03c4\u03b1", + "Apps.textVariable": "\u03ba\u03b5\u03af\u03bc\u03b5\u03bd\u03bf", + "Code.badXml": "\u03a3\u03c6\u03ac\u03bb\u03bc\u03b1 \u03b1\u03bd\u03ac\u03bb\u03c5\u03c3\u03b7\u03c2 XML:\n%1\n\n\u0395\u03c0\u03af\u03bb\u03b5\u03be\u03b5 \u00ab\u039f\u039a\u00bb \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03b5\u03b3\u03ba\u03b1\u03c4\u03b1\u03bb\u03b5\u03af\u03c8\u03b5\u03b9\u03c2 \u03c4\u03b9\u03c2 \u03b1\u03bb\u03bb\u03b1\u03b3\u03ad\u03c2 \u03ae \u00ab\u0391\u03ba\u03cd\u03c1\u03c9\u03c3\u03b7\u00bb \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03b5\u03c0\u03b5\u03be\u03b5\u03c1\u03b3\u03b1\u03c3\u03c4\u03b5\u03af\u03c2 \u03c4\u03bf XML \u03ba\u03b9 \u03ac\u03bb\u03bb\u03bf.", + "Code.badCode": "\u03a3\u03c6\u03ac\u03bb\u03bc\u03b1 \u03c0\u03c1\u03bf\u03b3\u03c1\u03ac\u03bc\u03bc\u03b1\u03c4\u03bf\u03c2:\n%1", + "Code.timeout": "\u03a5\u03c0\u03ad\u03c1\u03b2\u03b1\u03c3\u03b7 \u03bc\u03ad\u03b3\u03b9\u03c3\u03c4\u03bf\u03c5 \u03b1\u03c1\u03b9\u03b8\u03bc\u03bf\u03cd \u03b5\u03c0\u03b1\u03bd\u03b1\u03bb\u03ae\u03c8\u03b5\u03c9\u03bd.", + "Code.discard": "\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae \u03ba\u03b1\u03b9 \u03c4\u03c9\u03bd %1 \u03bc\u03c0\u03bb\u03bf\u03ba?", + "Code.title": "\u039a\u03ce\u03b4\u03b9\u03ba\u03b1\u03c2", + "Code.blocks": "\u039c\u03c0\u03bb\u03bf\u03ba", + "Code.trashTooltip": "\u0391\u03c0\u03cc\u03c1\u03c1\u03b9\u03c8\u03b7 \u03cc\u03bb\u03c9\u03bd \u03c4\u03c9\u03bd \u03bc\u03c0\u03bb\u03bf\u03ba.", + "Graph.title": "\u0397 \u0393\u03c1\u03b1\u03c6\u03b9\u03ba\u03ae \u0391\u03c0\u03b5\u03b9\u03ba\u03cc\u03bd\u03b9\u03c3\u03b7 \u0391\u03c1\u03b9\u03b8\u03bc\u03bf\u03bc\u03b7\u03c7\u03b1\u03bd\u03ae", + "Maze.moveForward": "\u03c0\u03c1\u03bf\u03c7\u03ce\u03c1\u03b7\u03c3\u03b5 \u03b5\u03c5\u03b8\u03b5\u03af\u03b1", + "Maze.turnLeft": "\u03c3\u03c4\u03c1\u03af\u03c8\u03b5 \u03b1\u03c1\u03b9\u03c3\u03c4\u03b5\u03c1\u03ac", + "Maze.turnRight": "\u03c3\u03c4\u03c1\u03af\u03c8\u03b5 \u03b4\u03b5\u03be\u03b9\u03ac", + "Maze.doCode": "\u03ba\u03ac\u03bd\u03b5", + "Maze.elseCode": "\u03b4\u03b9\u03b1\u03c6\u03bf\u03c1\u03b5\u03c4\u03b9\u03ba\u03ac", + "Maze.helpIfElse": "\u03a4\u03b1 \u03bc\u03c0\u03bb\u03bf\u03ba '\u03b5\u03ac\u03bd...\u03b5\u03b9\u03b4\u03ac\u03bb\u03bb\u03c9\u03c2' \u03b8\u03b1 \u03ba\u03ac\u03bd\u03bf\u03c5\u03bd \u03b5\u03af\u03c4\u03b5 \u03c4\u03bf \u03ad\u03bd\u03b1 \u03b5\u03af\u03c4\u03b5 \u03c4\u03bf \u03ac\u03bb\u03bb\u03bf.", + "Maze.pathAhead": "\u03b5\u03b1\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9 \u03bc\u03bf\u03bd\u03bf\u03c0\u03ac\u03c4\u03b9 \u03bc\u03c0\u03c1\u03bf\u03c3\u03c4\u03ac", + "Maze.pathLeft": "\u03b5\u03b1\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9 \u03bc\u03bf\u03bd\u03bf\u03c0\u03ac\u03c4\u03b9 \u03c0\u03c1\u03bf\u03c2 \u03c4\u03b1 \u03b1\u03c1\u03b9\u03c3\u03c4\u03b5\u03c1\u03ac", + "Maze.pathRight": "\u03b5\u03b1\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9 \u03bc\u03bf\u03bd\u03bf\u03c0\u03ac\u03c4\u03b9 \u03c0\u03c1\u03bf\u03c2 \u03c4\u03b1 \u03b4\u03b5\u03be\u03b9\u03ac", + "Maze.repeatUntil": "\u03b5\u03c0\u03b1\u03bd\u03ac\u03bb\u03b1\u03b2\u03b5 \u03bc\u03ad\u03c7\u03c1\u03b9", + "Maze.moveForwardTooltip": "\u039a\u03b9\u03bd\u03b5\u03af \u03c4\u03bf \u03b1\u03bd\u03b8\u03c1\u03c9\u03c0\u03ac\u03ba\u03b9 \u03bc\u03af\u03b1 \u03b8\u03ad\u03c3\u03b7 \u03bc\u03c0\u03c1\u03bf\u03c3\u03c4\u03ac.", + "Maze.turnTooltip": "\u03a4\u03bf \u03b1\u03bd\u03b8\u03c1\u03c9\u03c0\u03ac\u03ba\u03b9 \u03c3\u03c4\u03c1\u03af\u03b2\u03b5\u03b9 \u03b1\u03c1\u03b9\u03c3\u03c4\u03b5\u03c1\u03ac \u03ae \u03b4\u03b5\u03be\u03b9\u03ac \u03ba\u03b1\u03c4\u03ac 90 \u03bc\u03bf\u03af\u03c1\u03b5\u03c2.", + "Maze.ifTooltip": "\u0391\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9 \u03ad\u03bd\u03b1 \u03bc\u03bf\u03bd\u03bf\u03c0\u03ac\u03c4\u03b9 \u03c0\u03c1\u03bf\u03c2 \u03c4\u03b7 \u03c3\u03c5\u03b3\u03ba\u03b5\u03ba\u03c1\u03b9\u03bc\u03ad\u03bd\u03b7 \u03ba\u03b1\u03c4\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7, \u03c4\u03cc\u03c4\u03b5 \u03ba\u03ac\u03bd\u03bf\u03c5\u03bc\u03b5 \u03ba\u03ac\u03c0\u03bf\u03b9\u03b5\u03c2 \u03b5\u03bd\u03ad\u03c1\u03b3\u03b5\u03b9\u03b5\u03c2.", + "Maze.ifelseTooltip": "\u0391\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9 \u03ad\u03bd\u03b1 \u03bc\u03bf\u03bd\u03bf\u03c0\u03ac\u03c4\u03b9 \u03c0\u03c1\u03bf\u03c2 \u03c4\u03b7 \u03c3\u03c5\u03b3\u03ba\u03b5\u03ba\u03c1\u03b9\u03bc\u03ad\u03bd\u03b7 \u03ba\u03b1\u03c4\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7, \u03c4\u03cc\u03c4\u03b5 \u03ba\u03ac\u03bd\u03b5 \u03c4\u03bf \u03c0\u03c1\u03ce\u03c4\u03bf \u03bc\u03c0\u03bb\u03bf\u03ba \u03c4\u03c9\u03bd \u03b4\u03c1\u03ac\u03c3\u03b5\u03c9\u03bd. \u0394\u03b9\u03b1\u03c6\u03bf\u03c1\u03b5\u03c4\u03b9\u03ba\u03ac, \u03ba\u03ac\u03bd\u03b5 \u03c4\u03bf \u03b4\u03b5\u03cd\u03c4\u03b5\u03c1\u03bf \u03bc\u03c0\u03bb\u03bf\u03ba \u03c4\u03c9\u03bd \u03b4\u03c1\u03ac\u03c3\u03b5\u03c9\u03bd.", + "Maze.whileTooltip": "\u0395\u03c0\u03b1\u03bd\u03ad\u03bb\u03b1\u03b2\u03b5 \u03c4\u03b9\u03c2 \u03c0\u03b5\u03c1\u03b9\u03ba\u03bb\u03b5\u03b9\u03cc\u03bc\u03b5\u03bd\u03b5\u03c2 \u03b5\u03bd\u03ad\u03c1\u03b3\u03b5\u03b9\u03b5\u03c2 \u03bc\u03ad\u03c7\u03c1\u03b9 \u03bd\u03b1 \u03c6\u03b8\u03ac\u03c3\u03b5\u03b9 \u03c3\u03c4\u03bf \u03c4\u03ad\u03c1\u03bc\u03b1", + "Maze.capacity0": "\u0388\u03c7\u03b5\u03b9\u03c2 \u03ac\u03bb\u03bb\u03b1 %0 \u03bc\u03c0\u03bb\u03bf\u03ba \u03b1\u03ba\u03cc\u03bc\u03b1.", + "Maze.capacity1": "\u0388\u03c7\u03b5\u03b9\u03c2 \u03ac\u03bb\u03bb\u03b1 %1 \u03bc\u03c0\u03bb\u03bf\u03ba \u03b1\u03ba\u03cc\u03bc\u03b1.", + "Maze.capacity2": "\u0388\u03c7\u03b5\u03b9\u03c2 \u03ac\u03bb\u03bb\u03b1 %2 blocks \u03b1\u03ba\u03cc\u03bc\u03b1.", + "Maze.nextLevel": "\u03a3\u03c5\u03b3\u03c7\u03b1\u03c1\u03b7\u03c4\u03ae\u03c1\u03b9\u03b1! \u0398\u03b1 \u03c0\u03c1\u03bf\u03c7\u03c9\u03c1\u03ae\u03c3\u03b5\u03b9\u03c2 \u03c3\u03c4\u03bf \u03b5\u03c0\u03af\u03c0\u03b5\u03b4\u03bf %1?", + "Maze.finalLevel": "\u03a3\u03c5\u03b3\u03c7\u03b1\u03c1\u03b7\u03c4\u03ae\u03c1\u03b9\u03b1! \u0388\u03bb\u03c5\u03c3\u03b5\u03c2 \u03c4\u03bf \u03c4\u03b5\u03bb\u03b5\u03c5\u03c4\u03b1\u03af\u03bf \u03b5\u03c0\u03af\u03c0\u03b5\u03b4\u03bf.", + "Maze.maze": "\u039b\u03b1\u03b2\u03cd\u03c1\u03b9\u03bd\u03b8\u03bf\u03c2", + "Maze.runTooltip": "\u039a\u03ac\u03bd\u03b5\u03b9 \u03c4\u03bf\u03bd \u03c7\u03b1\u03c1\u03b1\u03ba\u03c4\u03ae\u03c1\u03b1 \u03bd\u03b1 \u03ba\u03ac\u03bd\u03b5\u03b9 \u03b1\u03c5\u03c4\u03cc \u03c0\u03bf\u03c5 \u03bb\u03ad\u03bd\u03b5 \u03c4\u03b1 \u03bc\u03c0\u03bb\u03bf\u03ba.", + "Maze.resetTooltip": "\u0392\u03ac\u03bb\u03c4\u03b5 \u03c4\u03bf \u03c7\u03b1\u03c1\u03b1\u03ba\u03c4\u03ae\u03c1\u03b1 \u03c0\u03af\u03c3\u03c9 \u03c3\u03c4\u03b7\u03bd \u03b1\u03c1\u03c7\u03ae \u03c4\u03bf\u03c5 \u03bb\u03b1\u03b2\u03c5\u03c1\u03af\u03bd\u03b8\u03bf\u03c5.", + "Maze.helpStack": "\u03a3\u03c4\u03bf\u03af\u03b2\u03b1\u03be\u03b5 \u03b4\u03cd\u03bf \u03bc\u03c0\u03bb\u03bf\u03ba '\u03c0\u03c1\u03bf\u03c7\u03ce\u03c1\u03b7\u03c3\u03b5' \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03c6\u03c4\u03ac\u03c3\u03c9 \u03c3\u03c4\u03bf \u03c4\u03ad\u03c1\u03bc\u03b1.", + "Maze.helpOneTopBlock": "\u03a3\u03b5 \u03b1\u03c5\u03c4\u03cc \u03c4\u03bf \u03b5\u03c0\u03af\u03c0\u03b5\u03b4\u03bf, \u03c0\u03c1\u03ad\u03c0\u03b5\u03b9 \u03bd\u03b1 \u03c3\u03c4\u03bf\u03b9\u03b2\u03ac\u03be\u03b5\u03b9\u03c2 \u03cc\u03bb\u03b1 \u03c4\u03b1 blocks \u03c3\u03c4\u03bf \u03bb\u03b5\u03c5\u03ba\u03cc \u03c7\u03ce\u03c1\u03bf \u03b5\u03c1\u03b3\u03b1\u03c3\u03af\u03b1\u03c2.", + "Maze.helpRun": "\u0395\u03ba\u03c4\u03ad\u03bb\u03b5\u03c3\u03b5 \u03c4\u03bf \u03c0\u03c1\u03cc\u03b3\u03c1\u03b1\u03bc\u03bc\u03ac \u03c3\u03bf\u03c5 \u03ba\u03b1\u03b9 \u03b4\u03b5\u03c2 \u03c4\u03b9 \u03c3\u03c5\u03bc\u03b2\u03b1\u03af\u03bd\u03b5\u03b9.", + "Maze.helpReset": "\u03a4\u03bf \u03c0\u03c1\u03cc\u03b3\u03c1\u03b1\u03bc\u03bc\u03b1 \u03c3\u03bf\u03c5 \u03b4\u03b5\u03bd \u03ad\u03bb\u03c5\u03c3\u03b5 \u03c4\u03bf\u03bd \u03bb\u03b1\u03b2\u03cd\u03c1\u03b9\u03bd\u03b8\u03bf. \u03a0\u03ac\u03c4\u03b7\u03c3\u03b5 \u00ab\u0395\u03c0\u03b1\u03bd\u03b1\u03c6\u03bf\u03c1\u03ac\u00bb \u03ba\u03b1\u03b9 \u03b4\u03bf\u03ba\u03af\u03bc\u03b1\u03c3\u03b5 \u03ac\u03bb\u03bb\u03b7 \u03bc\u03b9\u03b1 \u03c6\u03bf\u03c1\u03ac.", + "Maze.helpRepeat": "\u039f\u03b9 \u03c5\u03c0\u03bf\u03bb\u03bf\u03b3\u03b9\u03c3\u03c4\u03ad\u03c2 \u03ad\u03c7\u03bf\u03c5\u03bd \u03c0\u03b5\u03c1\u03b9\u03bf\u03c1\u03b9\u03c3\u03bc\u03ad\u03bd\u03b7 \u03bc\u03bd\u03ae\u03bc\u03b7. \u03a0\u03c1\u03bf\u03c3\u03c0\u03ac\u03b8\u03b7\u03c3\u03b5 \u03bd\u03b1 \u03c6\u03c4\u03ac\u03c3\u03b5\u03b9\u03c2 \u03c3\u03c4\u03bf \u03c4\u03ad\u03bb\u03bf\u03c2 \u03c4\u03bf\u03c5 \u03bc\u03bf\u03bd\u03bf\u03c0\u03b1\u03c4\u03b9\u03bf\u03cd \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ce\u03bd\u03c4\u03b1\u03c2 \u03bc\u03cc\u03bd\u03bf \u03b4\u03cd\u03bf \u03bc\u03c0\u03bb\u03bf\u03ba. \u03a7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b5 \u03c4\u03bf \u03bc\u03c0\u03bb\u03bf\u03ba '\u03b5\u03c0\u03b1\u03bd\u03ad\u03bb\u03b1\u03b2\u03b5' \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03c4\u03c1\u03ad\u03be\u03b5\u03b9\u03c2 \u03c4\u03bf \u03bc\u03c0\u03bb\u03bf\u03ba \u03c0\u03bf\u03c5 \u03b8\u03ad\u03bb\u03b5\u03b9\u03c2 \u03c0\u03b5\u03c1\u03b9\u03c3\u03c3\u03cc\u03c4\u03b5\u03c1\u03b5\u03c2 \u03c6\u03bf\u03c1\u03ad\u03c2.", + "Maze.helpCapacity": "\u0388\u03c7\u03bf\u03c5\u03bd \u03b5\u03be\u03b1\u03bd\u03c4\u03bb\u03b7\u03b8\u03b5\u03af \u03cc\u03bb\u03b1 \u03c4\u03b1 \u03bc\u03c0\u03bb\u03bf\u03ba \u03b3\u03b9\u03b1 \u03b1\u03c5\u03c4\u03cc \u03c4\u03bf \u03b5\u03c0\u03af\u03c0\u03b5\u03b4\u03bf. \u0393\u03b9\u03b1 \u03bd\u03b1 \u03b4\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03ae\u03c3\u03b5\u03b9\u03c2 \u03ad\u03bd\u03b1 \u03bd\u03ad\u03bf \u03bc\u03c0\u03bb\u03bf\u03ba, \u03b8\u03b1 \u03c0\u03c1\u03ad\u03c0\u03b5\u03b9 \u03c0\u03c1\u03ce\u03c4\u03b1 \u03bd\u03b1 \u03b4\u03b9\u03b1\u03b3\u03c1\u03ac\u03c8\u03b5\u03b9\u03c2 \u03ad\u03bd\u03b1 \u03c5\u03c0\u03ac\u03c1\u03c7\u03bf\u03bd \u03bc\u03c0\u03bb\u03bf\u03ba.", + "Maze.helpRepeatMany": "\u039c\u03c0\u03bf\u03c1\u03b5\u03af\u03c4\u03b5 \u03bd\u03b1 \u03b2\u03ac\u03bb\u03b5\u03c4\u03b5 \u03c0\u03b5\u03c1\u03b9\u03c3\u03c3\u03cc\u03c4\u03b5\u03c1\u03b1 \u03b1\u03c0\u03cc \u03ad\u03bd\u03b1 \u03bc\u03c0\u03bb\u03bf\u03ba \u03bc\u03ad\u03c3\u03b1 \u03c3\u03b5 \u03ad\u03bd\u03b1 \u03bc\u03c0\u03bb\u03bf\u03ba \u00ab\u03b5\u03c0\u03b1\u03bd\u03ac\u03bb\u03b7\u03c8\u03b7\u00bb.", + "Maze.helpSkins": "\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c3\u03b1\u03c2 \u03b1\u03b3\u03b1\u03c0\u03b7\u03bc\u03ad\u03bd\u03bf \u03c0\u03b1\u03af\u03ba\u03c4\u03b7 \u03b1\u03c0\u03cc \u03b1\u03c5\u03c4\u03cc \u03c4\u03bf \u03bc\u03b5\u03bd\u03bf\u03cd.", + "Maze.helpIf": "\u039c\u03b9\u03b1 \u03c3\u03c5\u03bd\u03b8\u03ae\u03ba\u03b7 '\u03b5\u03ac\u03bd' \u03b8\u03b1 \u03b5\u03ba\u03c4\u03b5\u03bb\u03ad\u03c3\u03b5\u03b9 \u03ba\u03ac\u03c4\u03b9 \u03bc\u03cc\u03bd\u03bf \u03b1\u03bd \u03b5\u03af\u03bd\u03b1\u03b9 \u03b1\u03bb\u03b7\u03b8\u03ae\u03c2. \u03a0\u03c1\u03bf\u03c3\u03c0\u03ac\u03b8\u03b7\u03c3\u03b5 \u03bd\u03b1 \u03c3\u03c4\u03c1\u03af\u03c8\u03b5\u03b9\u03c2 \u03b1\u03c1\u03b9\u03c3\u03c4\u03b5\u03c1\u03ac, \u03b5\u03ac\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9 \u03bc\u03bf\u03bd\u03bf\u03c0\u03ac\u03c4\u03b9 \u03c0\u03c1\u03bf\u03c2 \u03c4\u03b1 \u03b1\u03c1\u03b9\u03c3\u03c4\u03b5\u03c1\u03ac.", + "Maze.helpMenu": "\u039a\u03ac\u03bd\u03b5 \u03ba\u03bb\u03b9\u03ba \u03c3\u03c4\u03bf %1 \u03bc\u03ad\u03c3\u03b1 \u03c3\u03c4\u03bf \u00ab\u03b5\u03ac\u03bd\u00bb \u03bc\u03c0\u03bb\u03bf\u03ba \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03b1\u03bb\u03bb\u03ac\u03be\u03b5\u03b9\u03c2 \u03c4\u03b7\u03bd \u03ba\u03b1\u03c4\u03ac\u03c3\u03c4\u03b1\u03c3\u03ae \u03c4\u03bf\u03c5.", + "Maze.helpWallFollow": "\u039c\u03c0\u03bf\u03c1\u03b5\u03af\u03c2 \u03bd\u03b1 \u03b5\u03c0\u03b9\u03bb\u03cd\u03c3\u03b5\u03b9\u03c2 \u03b1\u03c5\u03c4\u03cc\u03bd \u03c4\u03bf\u03bd \u03c0\u03b5\u03c1\u03af\u03c0\u03bb\u03bf\u03ba\u03bf \u03bb\u03b1\u03b2\u03cd\u03c1\u03b9\u03bd\u03b8\u03bf; \u03a0\u03c1\u03bf\u03c3\u03c0\u03ac\u03b8\u03b7\u03c3\u03b5 \u03bd\u03b1 \u03b1\u03ba\u03bf\u03bb\u03bf\u03c5\u03b8\u03ae\u03c3\u03b5\u03b9\u03c2 \u03c4\u03bf\u03bd \u03b1\u03c1\u03b9\u03c3\u03c4\u03b5\u03c1\u03cc \u03c4\u03bf\u03af\u03c7\u03bf. \u039c\u03cc\u03bd\u03bf \u03c0\u03c1\u03bf\u03c7\u03c9\u03c1\u03b7\u03bc\u03ad\u03bd\u03bf\u03b9 \u03c0\u03c1\u03bf\u03b3\u03c1\u03b1\u03bc\u03bc\u03b1\u03c4\u03b9\u03c3\u03c4\u03ad\u03c2!", + "Plane.rows": "\u03a3\u03b5\u03b9\u03c1\u03ad\u03c2: %1", + "Plane.getRows": "\u03c3\u03b5\u03b9\u03c1\u03ad\u03c2 (%1)", + "Plane.rows1": "\u03a3\u03b5\u03b9\u03c1\u03ad\u03c2 1\u03b7\u03c2 \u03b8\u03ad\u03c3\u03b7\u03c2: %1", + "Plane.getRows1": "\u03a3\u03b5\u03b9\u03c1\u03ad\u03c2 1\u03b7\u03c2 \u03b8\u03ad\u03c3\u03b7\u03c2 (%1)", + "Plane.rows2": "\u03a3\u03b5\u03b9\u03c1\u03ad\u03c2 2\u03b7\u03c2 \u03b8\u03ad\u03c3\u03b7\u03c2: %1", + "Plane.getRows2": "\u03a3\u03b5\u03b9\u03c1\u03ad\u03c2 2\u03b7\u03c2 \u03b8\u03ad\u03c3\u03b7\u03c2 (%1)", + "Plane.seats": "\u039a\u03b1\u03b8\u03af\u03c3\u03bc\u03b1\u03c4\u03b1: %1", + "Plane.placeholder": ";", + "Plane.setSeats": "\u03ba\u03b1\u03b8\u03af\u03c3\u03bc\u03b1\u03c4\u03b1 =", + "Plane.plane": "\u0391\u03b5\u03c1\u03bf\u03c0\u03bb\u03ac\u03bd\u03bf", + "Plane.description1": "\u0388\u03bd\u03b1 \u03b1\u03b5\u03c1\u03bf\u03c0\u03bb\u03ac\u03bd\u03bf \u03ad\u03c7\u03b5\u03b9 \u03ad\u03bd\u03b1\u03bd \u03b1\u03c1\u03b9\u03b8\u03bc\u03cc \u03c3\u03b5\u03b9\u03c1\u03ce\u03bd \u03ba\u03b1\u03b8\u03b9\u03c3\u03bc\u03ac\u03c4\u03c9\u03bd \u03b5\u03c0\u03b9\u03b2\u03b1\u03c4\u03ce\u03bd. \u039a\u03ac\u03b8\u03b5 \u03c3\u03b5\u03b9\u03c1\u03ac \u03ad\u03c7\u03b5\u03b9 \u03c4\u03ad\u03c3\u03c3\u03b5\u03c1\u03b1 \u03ba\u03b1\u03b8\u03af\u03c3\u03bc\u03b1\u03c4\u03b1.", + "Plane.description2": "\u0388\u03bd\u03b1 \u03b1\u03b5\u03c1\u03bf\u03c0\u03bb\u03ac\u03bd\u03bf \u03ad\u03c7\u03b5\u03b9 \u03b4\u03cd\u03bf \u03ba\u03b1\u03b8\u03af\u03c3\u03bc\u03b1\u03c4\u03b1 \u03c3\u03c4\u03bf \u03b8\u03ac\u03bb\u03b1\u03bc\u03bf \u03b4\u03b9\u03b1\u03ba\u03c5\u03b2\u03ad\u03c1\u03bd\u03b7\u03c3\u03b7\u03c2 (\u03b3\u03b9\u03b1 \u03c4\u03bf\u03bd \u03ba\u03c5\u03b2\u03b5\u03c1\u03bd\u03ae\u03c4\u03b7 \u03ba\u03b1\u03b9 \u03c4\u03bf\u03bd \u03c3\u03c5\u03b3\u03ba\u03c5\u03b2\u03b5\u03c1\u03bd\u03ae\u03c4\u03b7), \u03ba\u03b1\u03b8\u03ce\u03c2 \u03ba\u03b1\u03b9 \u03ad\u03bd\u03b1\u03bd \u03b1\u03c1\u03b9\u03b8\u03bc\u03cc \u03b1\u03c0\u03cc \u03c3\u03b5\u03b9\u03c1\u03ad\u03c2 \u03ba\u03b1\u03b8\u03b9\u03c3\u03bc\u03ac\u03c4\u03c9\u03bd \u03b5\u03c0\u03b9\u03b2\u03b1\u03c4\u03ce\u03bd. \u039a\u03ac\u03b8\u03b5 \u03c3\u03b5\u03b9\u03c1\u03ac \u03ad\u03c7\u03b5\u03b9 \u03c4\u03ad\u03c3\u03c3\u03b5\u03c1\u03b1 \u03ba\u03b1\u03b8\u03af\u03c3\u03bc\u03b1\u03c4\u03b1.", + "Plane.description3": "\u0388\u03bd\u03b1 \u03b1\u03b5\u03c1\u03bf\u03c0\u03bb\u03ac\u03bd\u03bf \u03ad\u03c7\u03b5\u03b9 \u03b4\u03cd\u03bf \u03ba\u03b1\u03b8\u03af\u03c3\u03bc\u03b1\u03c4\u03b1 \u03c3\u03c4\u03bf \u03b8\u03ac\u03bb\u03b1\u03bc\u03bf \u03b4\u03b9\u03b1\u03ba\u03c5\u03b2\u03ad\u03c1\u03bd\u03b7\u03c3\u03b7\u03c2 (\u03b3\u03b9\u03b1 \u03c4\u03bf\u03bd \u03ba\u03c5\u03b2\u03b5\u03c1\u03bd\u03ae\u03c4\u03b7 \u03ba\u03b1\u03b9 \u03c4\u03bf\u03bd \u03c3\u03c5\u03b3\u03ba\u03c5\u03b2\u03b5\u03c1\u03bd\u03ae\u03c4\u03b7), \u03ba\u03b1\u03b8\u03ce\u03c2 \u03ba\u03b1\u03b9 \u03ad\u03bd\u03b1\u03bd \u03b1\u03c1\u03b9\u03b8\u03bc\u03cc \u03c3\u03b5\u03b9\u03c1\u03ce\u03bd \u03ba\u03b1\u03b8\u03b9\u03c3\u03bc\u03ac\u03c4\u03c9\u03bd \u03b3\u03b9\u03b1 \u03c4\u03b7\u03bd 1\u03b7 \u03ba\u03b1\u03b9 2\u03b7 \u03b8\u03ad\u03c3\u03b7. \u039a\u03ac\u03b8\u03b5 \u03c3\u03b5\u03b9\u03c1\u03ac \u03c4\u03b7\u03c2 1\u03b7\u03c2 \u03b8\u03ad\u03c3\u03b7\u03c2 \u03ad\u03c7\u03b5\u03b9 \u03c4\u03ad\u03c3\u03c3\u03b5\u03c1\u03b1 \u03ba\u03b1\u03b8\u03af\u03c3\u03bc\u03b1\u03c4\u03b1 \u03ba\u03b1\u03b9 \u03ba\u03ac\u03b8\u03b5 \u03c3\u03b5\u03b9\u03c1\u03ac \u03c4\u03b7\u03c2 2\u03b7\u03c2 \u03b8\u03ad\u03c3\u03b7\u03c2 \u03ad\u03c7\u03b5\u03b9 \u03c0\u03ad\u03bd\u03c4\u03b5 \u03ba\u03b1\u03b8\u03af\u03c3\u03bc\u03b1\u03c4\u03b1.", + "Plane.instructions": "\u03a6\u03c4\u03b9\u03ac\u03be\u03b5 \u03ad\u03bd\u03b1\u03bd \u03c4\u03cd\u03c0\u03bf (\u03ba\u03ac\u03c4\u03c9) \u03c0\u03bf\u03c5 \u03b8\u03b1 \u03c5\u03c0\u03bf\u03bb\u03bf\u03b3\u03af\u03b6\u03b5\u03b9 \u03c4\u03bf \u03c3\u03c5\u03bd\u03bf\u03bb\u03b9\u03ba\u03cc \u03b1\u03c1\u03b9\u03b8\u03bc\u03cc \u03ba\u03b1\u03b8\u03b9\u03c3\u03bc\u03ac\u03c4\u03c9\u03bd \u03c4\u03bf\u03c5 \u03b1\u03b5\u03c1\u03bf\u03c0\u03bb\u03ac\u03bd\u03bf\u03c5 \u03ba\u03b1\u03b8\u03ce\u03c2 \u03b1\u03bb\u03bb\u03ac\u03b6\u03bf\u03c5\u03bd \u03bf\u03b9 \u03c3\u03b5\u03b9\u03c1\u03ad\u03c2 (\u03c0\u03ac\u03bd\u03c9).", + "Puzzle.country1": "\u0391\u03c5\u03c3\u03c4\u03c1\u03b1\u03bb\u03af\u03b1", + "Puzzle.country1Language": "\u0391\u03b3\u03b3\u03bb\u03b9\u03ba\u03ac", + "Puzzle.country1City1": "\u039c\u03b5\u03bb\u03b2\u03bf\u03cd\u03c1\u03bd\u03b7", + "Puzzle.country1City2": "\u03a3\u03af\u03b4\u03bd\u03b5\u03ca", + "Puzzle.country1HelpUrl": "http://el.wikipedia.org/wiki/\u0391\u03c5\u03c3\u03c4\u03c1\u03b1\u03bb\u03af\u03b1", + "Puzzle.country2": "\u0393\u03b5\u03c1\u03bc\u03b1\u03bd\u03af\u03b1", + "Puzzle.country2Language": "\u0393\u03b5\u03c1\u03bc\u03b1\u03bd\u03b9\u03ba\u03ac", + "Puzzle.country2City1": "\u0392\u03b5\u03c1\u03bf\u03bb\u03af\u03bd\u03bf", + "Puzzle.country2City2": "\u039c\u03cc\u03bd\u03b1\u03c7\u03bf", + "Puzzle.country2HelpUrl": "http://el.wikipedia.org/wiki/\u0393\u03b5\u03c1\u03bc\u03b1\u03bd\u03af\u03b1", + "Puzzle.country3": "\u039a\u03af\u03bd\u03b1", + "Puzzle.country3Language": "\u039a\u03b9\u03bd\u03b5\u03b6\u03b9\u03ba\u03ac", + "Puzzle.country3City1": "\u03a0\u03b5\u03ba\u03af\u03bd\u03bf", + "Puzzle.country3City2": "\u03a3\u03b1\u03b3\u03ba\u03ac\u03b7", + "Puzzle.country3HelpUrl": "http://el.wikipedia.org/wiki/\u039a\u03af\u03bd\u03b1", + "Puzzle.country4": "\u0392\u03c1\u03b1\u03b6\u03b9\u03bb\u03af\u03b1", + "Puzzle.country4Language": "\u03a0\u03bf\u03c1\u03c4\u03bf\u03b3\u03b1\u03bb\u03b9\u03ba\u03ac", + "Puzzle.country4City1": "\u03a1\u03af\u03bf \u03bd\u03c4\u03b5 \u03a4\u03b6\u03b1\u03bd\u03ad\u03b9\u03c1\u03bf", + "Puzzle.country4City2": "\u03a3\u03ac\u03bf \u03a0\u03ac\u03bf\u03bb\u03bf", + "Puzzle.country4HelpUrl": "http://el.wikipedia.org/wiki/\u0392\u03c1\u03b1\u03b6\u03b9\u03bb\u03af\u03b1", + "Puzzle.flag": "\u03c3\u03b7\u03bc\u03b1\u03af\u03b1:", + "Puzzle.language": "\u03b3\u03bb\u03ce\u03c3\u03c3\u03b1:", + "Puzzle.languageChoose": "\u03b4\u03b9\u03ac\u03bb\u03b5\u03be\u03b5...", + "Puzzle.cities": "\u03c0\u03cc\u03bb\u03b5\u03b9\u03c2:", + "Puzzle.error0": "\u03a4\u03ad\u03bb\u03b5\u03b9\u03b1!\n\u039a\u03b1\u03b9 \u03c4\u03b1 %1 \u03bc\u03c0\u03bb\u03bf\u03ba \u03b5\u03af\u03bd\u03b1\u03b9 \u03c3\u03c9\u03c3\u03c4\u03ac.", + "Puzzle.error1": "\u03a3\u03c7\u03b5\u03b4\u03cc\u03bd! \u0388\u03bd\u03b1 \u03bc\u03c0\u03bb\u03bf\u03ba \u03b5\u03af\u03bd\u03b1\u03b9 \u03bb\u03ac\u03b8\u03bf\u03c2.", + "Puzzle.error2": "%1 \u03bc\u03c0\u03bb\u03bf\u03ba \u03b5\u03af\u03bd\u03b1\u03b9 \u03bb\u03ac\u03b8\u03bf\u03c2.", + "Puzzle.tryAgain": "\u03a4\u03bf \u03b5\u03c0\u03b9\u03c3\u03b7\u03bc\u03b1\u03c3\u03bc\u03ad\u03bd\u03bf \u03bc\u03c0\u03bb\u03bf\u03ba \u03b4\u03b5\u03bd \u03b5\u03af\u03bd\u03b1\u03b9 \u03c3\u03c9\u03c3\u03c4\u03cc.\n\u03a3\u03c5\u03bd\u03ad\u03c7\u03b9\u03c3\u03b5 \u03c4\u03b7\u03bd \u03c0\u03c1\u03bf\u03c3\u03c0\u03ac\u03b8\u03b5\u03b9\u03b1.", + "Puzzle.title": "\u03a0\u03b1\u03b6\u03bb", + "Puzzle.help": "\u0392\u03bf\u03ae\u03b8\u03b5\u03b9\u03b1", + "Puzzle.checkAnswers": "\u0388\u03bb\u03b5\u03b3\u03be\u03b5 \u03c4\u03b9\u03c2 \u03b1\u03c0\u03b1\u03bd\u03c4\u03ae\u03c3\u03b5\u03b9\u03c2", + "Puzzle.helpText": "\u0393\u03b9\u03b1 \u03ba\u03ac\u03b8\u03b5 \u03c7\u03ce\u03c1\u03b1 (\u03c0\u03c1\u03ac\u03c3\u03b9\u03bd\u03b1 \u03bc\u03c0\u03bb\u03bf\u03ba), \u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b5 \u03c4\u03b7 \u03c3\u03b7\u03bc\u03b1\u03af\u03b1 \u03c4\u03b7\u03c2, \u03c4\u03b7 \u03b3\u03bb\u03ce\u03c3\u03c3\u03b1 \u03c4\u03b7\u03c2 \u03ba\u03b1\u03b9 \u03ba\u03ac\u03bd\u03b5 \u03bc\u03b9\u03b1 \u03c3\u03c4\u03bf\u03af\u03b2\u03b1 \u03bc\u03b5 \u03c4\u03b9\u03c2 \u03c0\u03cc\u03bb\u03b5\u03b9\u03c2 \u03c4\u03b7\u03c2.", + "Turtle.moveTooltip": "\u039c\u03b5\u03c4\u03b1\u03ba\u03b9\u03bd\u03b5\u03af \u03c4\u03b7 \u03c7\u03b5\u03bb\u03ce\u03bd\u03b1 \u03c0\u03c1\u03bf\u03c2 \u03c4\u03b1 \u03b5\u03bc\u03c0\u03c1\u03cc\u03c2 \u03ae \u03c0\u03c1\u03bf\u03c2 \u03c4\u03b1 \u03c0\u03af\u03c3\u03c9 \u03ba\u03b1\u03c4\u03ac \u03c4\u03bf \u03bf\u03c1\u03b9\u03c3\u03bc\u03ad\u03bd\u03bf \u03c0\u03bf\u03c3\u03cc.", + "Turtle.moveForward": "\u03ba\u03b9\u03bd\u03ae\u03c3\u03bf\u03c5 \u03bc\u03c0\u03c1\u03bf\u03c3\u03c4\u03ac \u03ba\u03b1\u03c4\u03ac", + "Turtle.moveBackward": "\u03ba\u03b9\u03bd\u03ae\u03c3\u03bf\u03c5 \u03c0\u03c1\u03bf\u03c2 \u03c4\u03b1 \u03c0\u03af\u03c3\u03c9 \u03ba\u03b1\u03c4\u03ac", + "Turtle.turnTooltip": "\u0393\u03c5\u03c1\u03af\u03b6\u03b5\u03b9 \u03b7 \u03c7\u03b5\u03bb\u03ce\u03bd\u03b1 \u03b1\u03c1\u03b9\u03c3\u03c4\u03b5\u03c1\u03ac \u03ae \u03b4\u03b5\u03be\u03b9\u03ac \u03ba\u03b1\u03c4\u03ac \u03c4\u03bf\u03bd \u03ba\u03b1\u03b8\u03bf\u03c1\u03b9\u03c3\u03bc\u03ad\u03bd\u03bf \u03b1\u03c1\u03b9\u03b8\u03bc\u03cc \u03c4\u03c9\u03bd \u03bc\u03bf\u03b9\u03c1\u03ce\u03bd.", + "Turtle.turnRight": "\u03c3\u03c4\u03c1\u03af\u03c8\u03b5 \u03b4\u03b5\u03be\u03b9\u03ac \u03ba\u03b1\u03c4\u03ac", + "Turtle.turnLeft": "\u03c3\u03c4\u03c1\u03af\u03c8\u03b5 \u03b1\u03c1\u03b9\u03c3\u03c4\u03b5\u03c1\u03ac \u03ba\u03b1\u03c4\u03ac", + "Turtle.widthTooltip": "\u0391\u03bb\u03bb\u03ac\u03b6\u03b5\u03b9 \u03c4\u03bf \u03c6\u03ac\u03c1\u03b4\u03bf\u03c2 \u03c4\u03bf\u03c5 \u03c3\u03c4\u03b9\u03bb\u03cc.", + "Turtle.setWidth": "\u03bf\u03c1\u03af\u03c3\u03c4\u03b5 \u03c4\u03bf \u03c0\u03bb\u03ac\u03c4\u03bf\u03c2 \u03af\u03c3\u03bf \u03c0\u03c1\u03bf\u03c2", + "Turtle.colourTooltip": "\u0391\u03bb\u03bb\u03ac\u03b6\u03b5\u03b9 \u03c4\u03bf \u03c7\u03c1\u03ce\u03bc\u03b1 \u03c4\u03bf\u03c5 \u03c3\u03c4\u03b9\u03bb\u03cc.", + "Turtle.setColour": "\u03b1\u03bb\u03bb\u03b1\u03b3\u03ae \u03c7\u03c1\u03ce\u03bc\u03b1\u03c4\u03bf\u03c2 \u03c3\u03b5", + "Turtle.penTooltip": "\u0391\u03bd\u03b5\u03b2\u03ac\u03b6\u03b5\u03b9 \u03ae \u03ba\u03b1\u03c4\u03b5\u03b2\u03ac\u03b6\u03b5\u03b9 \u03c4\u03b7\u03bd \u03c0\u03ad\u03bd\u03b1 \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03c3\u03c4\u03b1\u03bc\u03b1\u03c4\u03ae\u03c3\u03b5\u03b9 \u03ae \u03bd\u03b1 \u03be\u03b5\u03ba\u03b9\u03bd\u03ae\u03c3\u03b5\u03b9 \u03bd\u03b1 \u03b6\u03c9\u03b3\u03c1\u03b1\u03c6\u03af\u03b6\u03b5\u03b9.", + "Turtle.penUp": "\u03c3\u03c4\u03b9\u03bb\u03cc \u03c0\u03ac\u03bd\u03c9", + "Turtle.penDown": "\u03c3\u03c4\u03b9\u03bb\u03cc \u03ba\u03ac\u03c4\u03c9", + "Turtle.turtleVisibilityTooltip": "\u039a\u03ac\u03bd\u03b5\u03b9 \u03c4\u03b7 \u03c7\u03b5\u03bb\u03ce\u03bd\u03b1 (\u03c0\u03c1\u03ac\u03c3\u03b9\u03bd\u03bf\u03c2 \u03ba\u03cd\u03ba\u03bb\u03bf\u03c2 \u03ba\u03b1\u03b9 \u03b2\u03ad\u03bb\u03bf\u03c2) \u03bf\u03c1\u03b1\u03c4\u03ae \u03ae \u03b1\u03cc\u03c1\u03b1\u03c4\u03b7.", + "Turtle.hideTurtle": "\u03ba\u03c1\u03cd\u03c8\u03b5 \u03c4\u03b7 \u03c7\u03b5\u03bb\u03ce\u03bd\u03b1", + "Turtle.showTurtle": "\u03b5\u03bc\u03c6\u03ac\u03bd\u03b9\u03c3\u03b5 \u03c4\u03b7 \u03c7\u03b5\u03bb\u03ce\u03bd\u03b1", + "Turtle.printHelpUrl": "http://el.wikipedia.org/wiki/%CE%A4%CF%85%CF%80%CE%BF%CE%B3%CF%81%CE%B1%CF%86%CE%AF%CE%B1", + "Turtle.printTooltip": "\u0393\u03c1\u03ac\u03c6\u03b5\u03b9 \u03c4\u03bf \u03ba\u03b5\u03af\u03bc\u03b5\u03bd\u03bf \u03c3\u03c4\u03b7\u03bd \u03ba\u03b1\u03c4\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7 \u03c4\u03b7\u03c2 \u03c7\u03b5\u03bb\u03ce\u03bd\u03b1\u03c2 \u03be\u03b5\u03ba\u03b9\u03bd\u03ce\u03bd\u03c4\u03b1\u03c2 \u03b1\u03c0\u03cc \u03c4\u03b7\u03bd \u03c4\u03c1\u03ad\u03c7\u03bf\u03c5\u03c3\u03b1 \u03b8\u03ad\u03c3\u03b7 \u03c4\u03b7\u03c2.", + "Turtle.print": "\u03b5\u03ba\u03c4\u03cd\u03c0\u03c9\u03c3\u03b7", + "Turtle.fontHelpUrl": "http://el.wikipedia.org/wiki/%CE%93%CF%81%CE%B1%CE%BC%CE%BC%CE%B1%CF%84%CE%BF%CF%83%CE%B5%CE%B9%CF%81%CE%AC", + "Turtle.fontTooltip": "\u039a\u03b1\u03b8\u03bf\u03c1\u03af\u03b6\u03b5\u03b9 \u03c4\u03b7 \u03b3\u03c1\u03b1\u03bc\u03bc\u03b1\u03c4\u03bf\u03c3\u03b5\u03b9\u03c1\u03ac \u03c0\u03bf\u03c5 \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03b5\u03af\u03c4\u03b1\u03b9 \u03b1\u03c0\u03cc \u03c4\u03bf \u03bc\u03c0\u03bb\u03bf\u03ba \u03c4\u03b7\u03c2 \u03b5\u03ba\u03c4\u03cd\u03c0\u03c9\u03c3\u03b7\u03c2.", + "Turtle.font": "\u03b3\u03c1\u03b1\u03bc\u03bc\u03b1\u03c4\u03bf\u03c3\u03b5\u03b9\u03c1\u03ac", + "Turtle.fontSize": "\u03bc\u03ad\u03b3\u03b5\u03b8\u03bf\u03c2 \u03b3\u03c1\u03b1\u03bc\u03bc\u03b1\u03c4\u03bf\u03c3\u03b5\u03b9\u03c1\u03ac\u03c2", + "Turtle.fontNormal": "\u03ba\u03b1\u03bd\u03bf\u03bd\u03b9\u03ba\u03cc", + "Turtle.fontBold": "\u03ad\u03bd\u03c4\u03bf\u03bd\u03bf", + "Turtle.fontItalic": "\u03c0\u03bb\u03ac\u03b3\u03b9\u03b1 \u03b3\u03c1\u03b1\u03c6\u03ae", + "Turtle.unloadWarning": "\u0391\u03bd \u03c6\u03cd\u03b3\u03b5\u03b9\u03c2 \u03b1\u03c0\u03cc \u03b1\u03c5\u03c4\u03ae \u03c4\u03b7 \u03c3\u03b5\u03bb\u03af\u03b4\u03b1, \u03cc\u03bb\u03b7 \u03b7 \u03b4\u03bf\u03c5\u03bb\u03b5\u03b9\u03ac \u03c0\u03bf\u03c5 \u03ad\u03c7\u03b5\u03b9\u03c2 \u03ba\u03ac\u03bd\u03b5\u03b9 \u03b8\u03b1 \u03c7\u03b1\u03b8\u03b5\u03af.", + "Turtle.title": "\u0393\u03c1\u03b1\u03c6\u03b9\u03ba\u03ac \u03bc\u03b5 \u03c4\u03b7 \u03a7\u03b5\u03bb\u03ce\u03bd\u03b1", + "Turtle.runTooltip": "\u0397 \u03c7\u03b5\u03bb\u03ce\u03bd\u03b1 \u03be\u03b5\u03ba\u03b9\u03bd\u03ac\u03b5\u03b9 \u03bd\u03b1 \u03ba\u03ac\u03bd\u03b5\u03b9 \u03b1\u03c5\u03c4\u03cc \u03c0\u03bf\u03c5 \u03bb\u03ad\u03bd\u03b5 \u03c4\u03b1 \u03bc\u03c0\u03bb\u03bf\u03ba.", + "Turtle.captureTooltip": "\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b5 \u03c4\u03bf \u03c3\u03c7\u03ad\u03b4\u03b9\u03bf.", + "Turtle.imgFilename": "\u03c3\u03c7\u03ad\u03b4\u03b9\u03bf.png", + "Turtle.catTurtle": "\u03a7\u03b5\u03bb\u03ce\u03bd\u03b1" +} \ No newline at end of file diff --git a/apps/json/en.json b/apps/json/en.json new file mode 100644 index 000000000..fbd502e75 --- /dev/null +++ b/apps/json/en.json @@ -0,0 +1,151 @@ +{ + "@metadata": { + "author": "Ellen Spertus ", + "lastupdated": "2013-10-27 13:14:27.036722", + "locale": "en", + "messagedocumentation" : "qqq" + }, + "Apps.subtitle": "a visual programming environment", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "See generated JavaScript code.", + "Apps.linkTooltip": "Save and link to blocks.", + "Apps.runTooltip": "Run the program defined by the blocks in the workspace.", + "Apps.runProgram": "Run Program", + "Apps.resetProgram": "Reset", + "Apps.dialogOk": "OK", + "Apps.dialogCancel": "Cancel", + "Apps.catLogic": "Logic", + "Apps.catLoops": "Loops", + "Apps.catMath": "Math", + "Apps.catText": "Text", + "Apps.catLists": "Lists", + "Apps.catColour": "Colour", + "Apps.catVariables": "Variables", + "Apps.catProcedures": "Procedures", + "Apps.httpRequestError": "There was a problem with the request.", + "Apps.linkAlert": "Share your blocks with this link:\n\n%1", + "Apps.hashError": "Sorry, '%1' doesn't correspond with any saved program.", + "Apps.xmlError": "Could not load your saved file. Perhaps it was created with a different version of Blockly?", + "Apps.listVariable": "list", + "Apps.textVariable": "text", + "Code.badXml": "Error parsing XML:\n%1\n\nSelect 'OK' to abandon your changes or 'Cancel' to further edit the XML.", + "Code.badCode": "Program error:\n%1", + "Code.timeout": "Maximum execution iterations exceeded.", + "Code.discard": "Delete all %1 blocks?", + "Code.title": "Code", + "Code.blocks": "Blocks", + "Code.trashTooltip": "Discard all blocks.", + "Graph.title": "Graphing Calculator", + "Maze.moveForward": "move forward", + "Maze.turnLeft": "turn left", + "Maze.turnRight": "turn right", + "Maze.doCode": "do", + "Maze.elseCode": "else", + "Maze.helpIfElse": "If-else blocks will do one thing or the other.", + "Maze.pathAhead": "if path ahead", + "Maze.pathLeft": "if path to the left", + "Maze.pathRight": "if path to the right", + "Maze.repeatUntil": "repeat until", + "Maze.moveForwardTooltip": "Moves the player forward one space.", + "Maze.turnTooltip": "Turns the player left or right by 90 degrees.", + "Maze.ifTooltip": "If there is a path in the specified direction, then do some actions.", + "Maze.ifelseTooltip": "If there is a path in the specified direction, then do the first block of actions. Otherwise, do the second block of actions.", + "Maze.whileTooltip": "Repeat the enclosed actions until finish point is reached.", + "Maze.capacity0": "You have %0 blocks left.", + "Maze.capacity1": "You have %1 block left.", + "Maze.capacity2": "You have %2 blocks left.", + "Maze.nextLevel": "Congratulations! Are you ready to proceed to level %1?", + "Maze.finalLevel": "Congratulations! You have solved the final level.", + "Maze.maze": "Maze", + "Maze.runTooltip": "Makes the player do what the blocks say.", + "Maze.resetTooltip": "Put the player back at the start of the maze.", + "Maze.helpStack": "Stack a couple of 'move forward' blocks together to help me reach the goal.", + "Maze.helpOneTopBlock": "On this level, you need to stack together all of the blocks in the white workspace.", + "Maze.helpRun": "Run your program to see what happens.", + "Maze.helpReset": "Your program didn't solve the maze. Press 'Reset' and try again.", + "Maze.helpRepeat": "Reach the end of this path using only two blocks. Use 'repeat' to run a block more than once.", + "Maze.helpCapacity": "You have used up all the blocks for this level. To create a new block, you first need to delete an existing block.", + "Maze.helpRepeatMany": "You can fit more than one block inside a 'repeat' block.", + "Maze.helpSkins": "Choose your favourite player from this menu.", + "Maze.helpIf": "An 'if' block will do something only if the condition is true. Try turning left if there is a path to the left.", + "Maze.helpMenu": "Click on %1 in the 'if' block to change its condition.", + "Maze.helpWallFollow": "Can you solve this complicated maze? Try following the left-hand wall. Advanced programmers only!", + "Plane.rows": "Rows: %1", + "Plane.getRows": "rows (%1)", + "Plane.rows1": "1st class rows: %1", + "Plane.getRows1": "1st class rows (%1)", + "Plane.rows2": "2nd class rows: %1", + "Plane.getRows2": "2nd class rows (%1)", + "Plane.seats": "Seats: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "seats =", + "Plane.plane": "Plane", + "Plane.description1": "An airplane has a number of rows of passenger seats. Each row contains four seats.", + "Plane.description2": "An airplane has two seats in the flight deck (for the pilot and co-pilot), and a number of rows of passenger seats. Each row contains four seats.", + "Plane.description3": "An airplane has two seats in the flight deck (for the pilot and co-pilot), and a number of rows of 1st class and 2nd class passenger seats. Each 1st class row contains four seats. Each 2nd class row contains five seats.", + "Plane.instructions": "Build a formula (below) that calculates the total number of seats on the airplane as the rows are changed (above).", + "Puzzle.country1": "Australia", + "Puzzle.country1Language": "English", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://en.wikipedia.org/wiki/Australia", + "Puzzle.country2": "Germany", + "Puzzle.country2Language": "German", + "Puzzle.country2City1": "Berlin", + "Puzzle.country2City2": "Munich", + "Puzzle.country2HelpUrl": "http://en.wikipedia.org/wiki/Germany", + "Puzzle.country3": "China", + "Puzzle.country3Language": "Chinese", + "Puzzle.country3City1": "Beijing", + "Puzzle.country3City2": "Shanghai", + "Puzzle.country3HelpUrl": "http://en.wikipedia.org/wiki/China", + "Puzzle.country4": "Brazil", + "Puzzle.country4Language": "Portuguese", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "São Paulo", + "Puzzle.country4HelpUrl": "http://en.wikipedia.org/wiki/Brazil", + "Puzzle.flag": "flag:", + "Puzzle.language": "language:", + "Puzzle.languageChoose": "choose...", + "Puzzle.cities": "cities:", + "Puzzle.error0": "Perfect!\nAll %1 blocks are correct.", + "Puzzle.error1": "Almost! One block is incorrect.", + "Puzzle.error2": "%1 blocks are incorrect.", + "Puzzle.tryAgain": "The highlighted block is not correct.\nKeep trying.", + "Puzzle.title": "Puzzle", + "Puzzle.help": "Help", + "Puzzle.checkAnswers": "Check Answers", + "Puzzle.helpText": "For each country (green), attach its flag, choose its language, and make a stack of its cities.", + "Turtle.moveTooltip": "Moves the turtle forward or backward by the specified amount.", + "Turtle.moveForward": "move forward by", + "Turtle.moveBackward": "move backward by", + "Turtle.turnTooltip": "Turns the turtle left or right by the specified number of degrees.", + "Turtle.turnRight": "turn right by", + "Turtle.turnLeft": "turn left by", + "Turtle.widthTooltip": "Changes the width of the pen.", + "Turtle.setWidth": "set width to", + "Turtle.colourTooltip": "Changes the colour of the pen.", + "Turtle.setColour": "set colour to", + "Turtle.penTooltip": "Lifts or lowers the pen, to stop or start drawing.", + "Turtle.penUp": "pen up", + "Turtle.penDown": "pen down", + "Turtle.turtleVisibilityTooltip": "Makes the turtle (circle and arrow) visible or invisible.", + "Turtle.hideTurtle": "hide turtle", + "Turtle.showTurtle": "show turtle", + "Turtle.printHelpUrl": "http://en.wikipedia.org/wiki/Printing", + "Turtle.printTooltip": "Draws text in the turtle's direction at its location.", + "Turtle.print": "print", + "Turtle.fontHelpUrl": "http://en.wikipedia.org/wiki/Font", + "Turtle.fontTooltip": "Sets the font used by the print block.", + "Turtle.font": "font", + "Turtle.fontSize": "font size", + "Turtle.fontNormal": "normal", + "Turtle.fontBold": "bold", + "Turtle.fontItalic": "italic", + "Turtle.unloadWarning": "Leaving this page will result in the loss of your work.", + "Turtle.title": "Turtle Graphics", + "Turtle.runTooltip": "Makes the turtle do what the blocks say.", + "Turtle.captureTooltip": "Save the drawing.", + "Turtle.imgFilename": "drawing.png", + "Turtle.catTurtle": "Turtle" +} diff --git a/apps/json/es.json b/apps/json/es.json new file mode 100644 index 000000000..5329d2bfd --- /dev/null +++ b/apps/json/es.json @@ -0,0 +1,153 @@ +{ + "@metadata": { + "authors": [ + "EDGI", + "Fitoschido", + "McDutchie", + "VegaDark" + ] + }, + "Apps.subtitle": "un entorno de programaci\u00f3n visual", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Mira el c\u00f3digo JavaScript generado.", + "Apps.linkTooltip": "Guarda conexi\u00f3n a los bloques.", + "Apps.runTooltip": "Ejecute el programa definido por los bloques en el \u00e1rea de trabajo.", + "Apps.runProgram": "Ejecutar el programa", + "Apps.resetProgram": "Restablecer", + "Apps.dialogOk": "Aceptar", + "Apps.dialogCancel": "Cancelar", + "Apps.catLogic": "L\u00f3gica", + "Apps.catLoops": "Secuencias", + "Apps.catMath": "Matem\u00e1ticas", + "Apps.catText": "Texto", + "Apps.catLists": "Lista", + "Apps.catColour": "Color", + "Apps.catVariables": "Variables", + "Apps.catProcedures": "Procedimientos", + "Apps.httpRequestError": "Hubo un problema con la petici\u00f3n.", + "Apps.linkAlert": "Comparte tus bloques con esta conexi\u00f3n:\n\n%1", + "Apps.hashError": "Lo siento, el '%1' no corresponde con ning\u00fan archivo Blockly guardado.", + "Apps.xmlError": "No se pudo cargar el archivo guardado. \u00bfQuiz\u00e1 fue creado con otra versi\u00f3n de Blockly?", + "Apps.listVariable": "lista", + "Apps.textVariable": "texto", + "Code.badXml": "Error de an\u00e1lisis XML:\n%1\n\nSelecciona OK para abandonar tus cambios o Cancelar para seguir editando el XML.", + "Code.badCode": "Error del programa:\n%1", + "Code.timeout": "Maximo de iteraciones de ejecuci\u00f3n excedidas.", + "Code.discard": "Eliminar todos los bloques 1%?", + "Code.title": "Codigo", + "Code.blocks": "Bloques", + "Code.trashTooltip": "Descartar todos los bloques.", + "Graph.title": "Calculadora gr\u00e1fica", + "Maze.moveForward": "Mover hacia delante", + "Maze.turnLeft": "gira izquierda", + "Maze.turnRight": "gira derecha", + "Maze.doCode": "haz esto", + "Maze.elseCode": "sino", + "Maze.helpIfElse": "Las declaraciones 'si-sino' hacen una cosa u otra.", + "Maze.pathAhead": "si hay camino enfrente", + "Maze.pathLeft": "si hay camino a la izquierda", + "Maze.pathRight": "si hay camino a la derecha", + "Maze.repeatUntil": "repite hasta", + "Maze.moveForwardTooltip": "Mueve a Pegman un cuadro hacia delante.", + "Maze.turnTooltip": "Gira a Pegman a izquierda o derecha 90 grados.", + "Maze.ifTooltip": " Si hay un camino en la direcci\u00f3n especificada, entonces ejecuta unas acciones.", + "Maze.ifelseTooltip": " Si hay un camino en la direcci\u00f3n especificada, entonces ejecuta las primeras acciones. Sino, haz el segundo conjunto de acciones.", + "Maze.whileTooltip": "Repite las acciones encapsuladas hasta terminar.", + "Maze.capacity0": "Te quedan %0 bloques.", + "Maze.capacity1": "Te queda %1 bloque.", + "Maze.capacity2": "Te quedan %2 bloques.", + "Maze.nextLevel": "\u00a1Felicidades! \u00bfEstas listo/a para seguir al siguiente nivel %1?", + "Maze.finalLevel": "\u00a1Felicidades! Haz resuelto el \u00faltimo nivel.", + "Maze.maze": "Laberinto", + "Maze.runTooltip": "Hacer que el personaje haga lo que dicen los bloques.", + "Maze.resetTooltip": "Ponga el personaje de nuevo al comienzo del laberinto.", + "Maze.helpStack": "Une un par de bloques de \u2018avanza\u2019 para ayudarme a llegar a la meta.", + "Maze.helpOneTopBlock": "En este nivel, necesitas apilar los bloques en el espacio en blanco.", + "Maze.helpRun": "Ejecuta tu programa para ver qu\u00e9 pasa.", + "Maze.helpReset": "Tu programa no resolvi\u00f3 el laberinto. Presiona \"reiniciar\" e intenta otra vez.", + "Maze.helpRepeat": "Las computadoras tienen memoria limitada. Llega al final de este camino usando tan s\u00f3lo dos bloques. Utiliza 'repetir' para ejecutar un bloque m\u00e1s de una vez.", + "Maze.helpCapacity": "Has usado todos los bloques para este nivel. Para crear un bloque nuevo, primero debes eliminar un bloque existente.", + "Maze.helpRepeatMany": "Puede encajar m\u00e1s de un bloque dentro de un bloque 'repetir'.", + "Maze.helpSkins": "Elige a tu jugador favorito en este men\u00fa.", + "Maze.helpIf": "Una condici\u00f3n 'si' va hacer algo solamente si la condici\u00f3n es verdadera. Intenta girar a la izquierda si hay camino a la izquierda.", + "Maze.helpMenu": "Haz clic en %1 en el bloque \"if\" para cambiar su condici\u00f3n.", + "Maze.helpWallFollow": "\u00bfPuedes resolver este complicado laberinto? Intenta seguir la pared de la izquierda.", + "Plane.rows": "Filas: %1", + "Plane.getRows": "filas (%1)", + "Plane.rows1": "Filas de primera clase: %1", + "Plane.getRows1": "Filas de primera clase: (%1)", + "Plane.rows2": "Filas de segunda clase: %1", + "Plane.getRows2": "Filas de segunda clase: (%1)", + "Plane.seats": "Asientos: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "asientos =", + "Plane.plane": "Avi\u00f3n", + "Plane.description1": "Un avi\u00f3n\u00a0 tiene un n\u00famero de filas de asientos de pasajeros. Cada fila contiene cuatro asientos.", + "Plane.description2": "Un avi\u00f3n tiene dos asientos en la cabina de vuelo (para el piloto y co-piloto), y un n\u00famero de filas de asientos de pasajeros. Cada fila contiene cuatro asientos.", + "Plane.description3": "Un avi\u00f3n tiene dos asientos en la cabina de vuelo (para el piloto y co-piloto), y un n\u00famero de filas de asientos para pasajeros de primera y segunda clase. Cada fila de la primera clase contiene cuatro asientos. Cada fila de la segunda clase contiene cinco asientos.", + "Plane.instructions": "Construir una f\u00f3rmula (abajo) que calcule el n\u00famero total de asientos en el avi\u00f3n cuando las filas sean cambiadas (arriba).", + "Puzzle.country1": "Australia", + "Puzzle.country1Language": "Ingl\u00e9s", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://es.wikipedia.org/wiki/Australia", + "Puzzle.country2": "Alemania", + "Puzzle.country2Language": "Alem\u00e1n", + "Puzzle.country2City1": "Berl\u00edn", + "Puzzle.country2City2": "M\u00fanich", + "Puzzle.country2HelpUrl": "http://es.wikipedia.org/wiki/Alemania", + "Puzzle.country3": "China", + "Puzzle.country3Language": "Chino", + "Puzzle.country3City1": "Pek\u00edn", + "Puzzle.country3City2": "Shangh\u00e1i", + "Puzzle.country3HelpUrl": "http://es.wikipedia.org/wiki/China", + "Puzzle.country4": "Brasil", + "Puzzle.country4Language": "Portugu\u00e9s", + "Puzzle.country4City1": "R\u00edo de Janeiro", + "Puzzle.country4City2": "S\u00e3o Paulo", + "Puzzle.country4HelpUrl": "http://es.wikipedia.org/wiki/Brasil", + "Puzzle.flag": "bandera:", + "Puzzle.language": "idioma:", + "Puzzle.languageChoose": "elegir...", + "Puzzle.cities": "ciudades:", + "Puzzle.error0": "\u00a1Perfecto!\nLos %1 bloques est\u00e1n bien colocados.", + "Puzzle.error1": "\u00a1Casi! Un bloque est\u00e1 mal colocado.", + "Puzzle.error2": "%1 bloques est\u00e1n mal colocados.", + "Puzzle.tryAgain": "El bloque destacado est\u00e1 mal colocado.\nSigue intent\u00e1ndolo.", + "Puzzle.title": "Puzle", + "Puzzle.help": "Ayuda", + "Puzzle.checkAnswers": "Comprobar las respuestas", + "Puzzle.helpText": "Para cada pa\u00eds (verde), asocia su bandera, elige su idioma y agrupa sus ciudades.", + "Turtle.moveTooltip": "Mueve la tortuga hacia adelante o hacia atr\u00e1s en la cantidad especificada.", + "Turtle.moveForward": "avanzar", + "Turtle.moveBackward": "devolverse", + "Turtle.turnTooltip": "Voltea la tortuga hacia la izquierda o la derecha por el n\u00famero especificado de grados.", + "Turtle.turnRight": "girar a la derecha por", + "Turtle.turnLeft": "girar a la izquierda por", + "Turtle.widthTooltip": "Cambia el ancho del bol\u00edgrafo.", + "Turtle.setWidth": "establecer el ancho de", + "Turtle.colourTooltip": "Cambia el ancho del bol\u00edgrafo.", + "Turtle.setColour": "establecer el color a", + "Turtle.penTooltip": "Levanta o baja el bol\u00edgrafo para detener o empezar a dibujar.", + "Turtle.penUp": "levante el bol\u00edgrafo", + "Turtle.penDown": "baje el bol\u00edgrafo", + "Turtle.turtleVisibilityTooltip": "Hace a la tortuga (c\u00edrculo y flecha) visible o invisible.", + "Turtle.hideTurtle": "ocultar la tortuga", + "Turtle.showTurtle": "mostrar la tortuga", + "Turtle.printHelpUrl": "http://en.wikipedia.org/wiki/Printing", + "Turtle.printTooltip": "Dibuja texto en la direcci\u00f3n de la tortuga en su ubicaci\u00f3n.", + "Turtle.print": "imprimir", + "Turtle.fontHelpUrl": "http://en.wikipedia.org/wiki/Font", + "Turtle.fontTooltip": "Define el tipo de letra utilizado por el bloque de impresi\u00f3n.", + "Turtle.font": "Tipo de letra", + "Turtle.fontSize": "tama\u00f1o de letra", + "Turtle.fontNormal": "normal", + "Turtle.fontBold": "bold", + "Turtle.fontItalic": "italic", + "Turtle.unloadWarning": "Salir de esta p\u00e1gina dar\u00e1 como resultado la p\u00e9rdida de su trabajo.", + "Turtle.title": "Tortuga Grafica", + "Turtle.runTooltip": "Hace que la haga lo que dicen los bloques.", + "Turtle.captureTooltip": "Guardar el dibujo.", + "Turtle.imgFilename": "dibujo.png", + "Turtle.catTurtle": "Tortuga" +} \ No newline at end of file diff --git a/apps/json/eu.json b/apps/json/eu.json new file mode 100644 index 000000000..9568d06e0 --- /dev/null +++ b/apps/json/eu.json @@ -0,0 +1,76 @@ +{ + "@metadata": { + "authors": [ + "Xabier Armendaritz" + ] + }, + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Ikusi sorturiko JavaScript kodea.", + "Apps.linkTooltip": "Gorde eta lotura sortu.", + "Apps.runProgram": "Programa exekutatu", + "Apps.resetProgram": "Berriz hasi", + "Apps.dialogOk": "Ados", + "Apps.httpRequestError": "Eskaerarekin arazo bat egon da.", + "Apps.linkAlert": "Elkarbanatu blokeak lotura honekin:\n\n%1", + "Apps.hashError": "Barkatu, \u00ab%1\u00bb ez dator bat gordetako ezein programarekin.", + "Apps.xmlError": "Ezin izan da zure fitxategia kargatu. Agian Blockly-ren beste bertsio batekin sortua izan zen?", + "Maze.moveForward": "mugi aurrera", + "Maze.turnLeft": "biratu ezker", + "Maze.turnRight": "biratu eskuin", + "Maze.doCode": "egin", + "Maze.elseCode": "bestela", + "Maze.helpIfElse": "If-else blokeek gauza bat edo bestea egingo dute.", + "Maze.pathAhead": "bidea badago aurrera", + "Maze.pathLeft": "bidea badago ezkerrera", + "Maze.pathRight": "bidea badago eskuinera", + "Maze.repeatUntil": "arte errepikatu", + "Maze.moveForwardTooltip": "Pegman aurreruntz tarte bat mugitzen du.", + "Maze.turnTooltip": "Pegman ezkerrerantz edo eskuinerantz 90 gradu biratzen du.", + "Maze.ifTooltip": "Esandako norantzan bidea badago, ekintza batzu burutu.", + "Maze.ifelseTooltip": "Esandako norantzan bidea badago, ekintzen lehenengo blokea burutu. Bestela, ekintzen bigarren blokea burutu.", + "Maze.whileTooltip": "Errepikatu barruko ekintzak bukaera punturaino iritsi arte.", + "Maze.capacity0": "%0 bloke geratzen dira.", + "Maze.capacity1": "Bloke %1 geratzen da.", + "Maze.capacity2": "%2 bloke geratzen dira.", + "Maze.nextLevel": "Zorionak! Prest al zaude %1 mailara pasatzeko?", + "Maze.finalLevel": "Zorionak! Azken maila gainditu duzu.", + "Maze.maze": "Labirintoa", + "Maze.helpStack": "Elkartu 'mugi aurrera' bloke pare bat helmugara iritsi ahal izateko.", + "Maze.helpOneTopBlock": "Maila honetan, bloke guztiak lan-eremu txurian pilatu behar dituzu.", + "Maze.helpRepeat": "Ordenagailuek memoria mugatua daukate. Saiatu zaitez bide honen bukaerara iristen soilik bi bloke erabiliz. Erabili 'errepikatu' bloke bat behin baino gehiagotan to run a block more than once.", + "Maze.helpRepeatMany": "Iritsi helmugara soilik bost bloke erabiliz.", + "Maze.helpIf": "'if' bloke batek zeozer egingo du bakarrik baldintza betetzen bada. Saiatu ezkerrera biratzen ezkerrera bidea baldin badago.", + "Maze.helpWallFollow": "Labirinto zail honi irtenbidea aurkitu diezaiokezu? Saia zaitez ezker-pareta jarraitzen.", + "Puzzle.country1": "Australia", + "Puzzle.country1Language": "Ingelesa", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://eu.wikipedia.org/wiki/Australia", + "Puzzle.country2": "Alemania", + "Puzzle.country2Language": "alemaniera", + "Puzzle.country2City1": "Berlin", + "Puzzle.country2City2": "Munich", + "Puzzle.country2HelpUrl": "http://eu.wikipedia.org/wiki/Alemania", + "Puzzle.country3": "Txina", + "Puzzle.country3Language": "txinera", + "Puzzle.country3City1": "Beijing", + "Puzzle.country3City2": "Shanghai", + "Puzzle.country3HelpUrl": "http://eu.wikipedia.org/wiki/Txina", + "Puzzle.country4": "Brasil", + "Puzzle.country4Language": "portugesa", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "Sao Paulo", + "Puzzle.country4HelpUrl": "http://eu.wikipedia.org/wiki/Brasil", + "Puzzle.flag": "ikurri\u00f1a:", + "Puzzle.language": "hizkuntza:", + "Puzzle.languageChoose": "aukeratu...", + "Puzzle.cities": "hiriak:", + "Puzzle.error0": "Bikain!\n%1 blokeak zuzen daude.", + "Puzzle.error1": "Ia-ia! Bloke bat ez dago ondo.", + "Puzzle.error2": "%1 bloke ez dira zuzenak.", + "Puzzle.tryAgain": "Markatuta agertzen den blokea ez da zuzena.\nSaiatu berriro.", + "Puzzle.title": "Puzzle", + "Puzzle.help": "Laguntza", + "Puzzle.checkAnswers": "Erantzunak egiaztatu", + "Puzzle.helpText": "Herrialde bakoitzari (berdea), bandera jarri, bere hizkuntza aukeratu, eta hiriak jarri." +} \ No newline at end of file diff --git a/apps/json/fa.json b/apps/json/fa.json new file mode 100644 index 000000000..24cfce172 --- /dev/null +++ b/apps/json/fa.json @@ -0,0 +1,150 @@ +{ + "@metadata": { + "authors": [ + "Ebraminio" + ] + }, + "Apps.subtitle": "\u06cc\u06a9 \u0645\u062d\u06cc\u0637 \u0628\u0631\u0646\u0627\u0645\u0647\u200c\u0646\u0648\u06cc\u0633\u06cc \u0628\u0635\u0631\u06cc", + "Apps.blocklyMessage": "\u0628\u0644\u0648\u06a9\u06cc", + "Apps.codeTooltip": "\u062f\u06cc\u062f\u0646 \u06a9\u062f \u062c\u0627\u0648\u0627\u0627\u0633\u06a9\u0631\u06cc\u067e\u062a \u0627\u06cc\u062c\u0627\u062f\u0634\u062f\u0647.", + "Apps.linkTooltip": "\u0630\u062e\u06cc\u0631\u0647 \u0648 \u067e\u06cc\u0648\u0646\u062f \u0628\u0647 \u0628\u0644\u0648\u06a9\u200c\u0647\u0627.", + "Apps.runTooltip": "\u0627\u062c\u0631\u0627\u06cc \u0628\u0631\u0646\u0627\u0645\u0647\u0654 \u062a\u0639\u0631\u06cc\u0641\u200c\u0634\u062f\u0647 \u062a\u0648\u0633\u0637 \u0628\u0644\u0648\u06a9\u200c\u0647\u0627 \u062f\u0631 \u0641\u0636\u0627\u06cc \u06a9\u0627\u0631.", + "Apps.runProgram": "\u0627\u062c\u0631\u0627\u06cc \u0628\u0631\u0646\u0627\u0645\u0647", + "Apps.resetProgram": "\u0627\u0632 \u0646\u0648", + "Apps.dialogOk": "\u062a\u0623\u06cc\u06cc\u062f", + "Apps.dialogCancel": "\u0644\u063a\u0648", + "Apps.catLogic": "\u0645\u0646\u0637\u0642", + "Apps.catLoops": "\u062d\u0644\u0642\u0647\u200c\u0647\u0627", + "Apps.catMath": "\u0631\u06cc\u0627\u0636\u06cc", + "Apps.catText": "\u0645\u062a\u0646", + "Apps.catLists": "\u0641\u0647\u0631\u0633\u062a\u200c\u0647\u0627", + "Apps.catColour": "\u0631\u0646\u06af", + "Apps.catVariables": "\u0645\u062a\u063a\u06cc\u06cc\u0631\u0647\u0627", + "Apps.catProcedures": "\u0631\u0648\u0646\u062f\u0647\u0627", + "Apps.httpRequestError": "\u0645\u0634\u06a9\u0644\u06cc \u0628\u0627 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u0648\u062c\u0648\u062f \u062f\u0627\u0634\u062a.", + "Apps.linkAlert": "\u0627\u0634\u062a\u0631\u0627\u06a9\u200c\u06af\u0630\u0627\u0631\u06cc \u0628\u0644\u0627\u06a9\u200c\u0647\u0627\u06cc\u062a\u0627\u0646 \u0628\u0627 \u0627\u06cc\u0646 \u067e\u06cc\u0648\u0646\u062f:\n\n%1", + "Apps.hashError": "\u0634\u0631\u0645\u0646\u062f\u0647\u060c \u00ab%1\u00bb \u0628\u0627 \u0647\u06cc\u0686 \u0628\u0631\u0646\u0627\u0645\u0647\u0654 \u0630\u062e\u06cc\u0631\u0647\u200c\u0634\u062f\u0647\u200c\u0627\u06cc \u062a\u0637\u0628\u06cc\u0642 \u067e\u06cc\u062f\u0627 \u0646\u06a9\u0631\u062f.", + "Apps.xmlError": "\u0646\u062a\u0648\u0627\u0646\u0633\u062a \u067e\u0631\u0648\u0646\u062f\u0647\u0654 \u0630\u062e\u06cc\u0631\u0647\u0654 \u0634\u0645\u0627 \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0634\u0648\u062f. \u0627\u062d\u062a\u0645\u0627\u0644\u0627\u064b \u0628\u0627 \u0646\u0633\u062e\u0647\u0654 \u0645\u062a\u0641\u0627\u0648\u062a\u06cc \u0627\u0632 \u0628\u0644\u0648\u06a9\u06cc \u062f\u0631\u0633\u062a \u0634\u062f\u0647\u200c\u0627\u0633\u062a\u061f", + "Apps.listVariable": "\u0641\u0647\u0631\u0633\u062a", + "Apps.textVariable": "\u0645\u062a\u0646", + "Code.badXml": "\u062e\u0637\u0627\u06cc \u062a\u062c\u0632\u06cc\u0647\u0654 \u0627\u06a9\u0633\u200c\u0627\u0645\u200c\u0627\u0644:\n%1\n\n\u00ab\u0628\u0627\u0634\u062f\u00bb \u0631\u0627 \u0628\u0631\u0627\u06cc \u0630\u062e\u06cc\u0631\u0647 \u0648 \u00ab\u0641\u0633\u062e\u00bb \u0631\u0627 \u0628\u0631\u0627\u06cc \u0648\u06cc\u0631\u0627\u06cc\u0634 \u0628\u06cc\u0634\u062a\u0631 \u0627\u06a9\u0633\u200c\u0627\u0645\u200c\u0627\u0644 \u0627\u0646\u062a\u062e\u0627\u0628 \u06a9\u0646\u06cc\u062f.", + "Code.badCode": "\u062e\u0637\u0627\u06cc \u0628\u0631\u0646\u0627\u0645\u0647:\n%1", + "Code.timeout": "\u062d\u062f\u0627\u06a9\u062b\u0631 \u062a\u06a9\u0631\u0627\u0631\u0647\u0627\u06cc \u0627\u062c\u0631\u0627 \u0631\u062f \u0634\u062f\u0647\u200c\u0627\u0633\u062a.", + "Code.discard": "\u062d\u0630\u0641 \u0647\u0645\u0647\u0654 \u0628\u0644\u0627\u06a9\u200c\u0647\u0627\u06cc %1\u061f", + "Code.title": "\u06a9\u062f", + "Code.blocks": "\u0628\u0644\u0648\u06a9\u200c\u0647\u0627", + "Code.trashTooltip": "\u062f\u0648\u0631\u0631\u06cc\u062e\u062a\u0646 \u0647\u0645\u0647\u0654 \u0628\u0644\u0648\u06a9\u200c\u0647\u0627.", + "Graph.title": "\u0645\u0627\u0634\u06cc\u0646\u200c\u062d\u0633\u0627\u0628 \u06af\u0631\u0627\u0641", + "Maze.moveForward": "\u062d\u0631\u06a9\u062a \u0631\u0648 \u0628\u0647 \u062c\u0644\u0648", + "Maze.turnLeft": "\u0628\u067e\u06cc\u0686 \u0628\u0647 \u0686\u067e", + "Maze.turnRight": "\u0628\u067e\u06cc\u0686 \u0628\u0647 \u0631\u0627\u0633\u062a", + "Maze.doCode": "\u0627\u0646\u062c\u0627\u0645", + "Maze.elseCode": "\u0622\u0646\u06af\u0627\u0647", + "Maze.helpIfElse": "\u0628\u0644\u0648\u06a9\u200c\u0647\u0627 \u0627\u06af\u0631-\u0622\u0646\u06af\u0627\u0647 \u06cc\u06a9 \u06a9\u0627\u0631 \u0631\u0627 \u0627\u0646\u062c\u0627\u0645 \u0645\u06cc\u200c\u062f\u0647\u0646\u062f \u06cc\u0627 \u06cc\u06a9 \u06a9\u0627\u0631 \u062f\u06cc\u06af\u0631.", + "Maze.pathAhead": "\u0627\u06af\u0631 \u0645\u0633\u06cc\u0631 \u067e\u06cc\u0634 \u0631\u0648", + "Maze.pathLeft": "\u0627\u06af\u0631 \u0645\u0633\u06cc\u0631 \u0628\u0647 \u0633\u0645\u062a \u0686\u067e", + "Maze.pathRight": "\u0627\u06af\u0631 \u0645\u0633\u06cc\u0631 \u0628\u0647 \u0633\u0645\u062a \u0631\u0627\u0633\u062a", + "Maze.repeatUntil": "\u062a\u06a9\u0631\u0627\u0631 \u062a\u0627", + "Maze.moveForwardTooltip": "\u0628\u0627\u0632\u06cc\u06a9\u0646 \u0631\u0627 \u06cc\u06a9 \u062e\u0627\u0646\u0647 \u062c\u0644\u0648 \u0645\u06cc\u200c\u0628\u0631\u062f.", + "Maze.turnTooltip": "\u0628\u0627\u0632\u06cc\u06a9\u0646 \u06f9\u06f0 \u062f\u0631\u062c\u0647 \u0686\u067e \u06cc\u0627 \u0631\u0627\u0633\u062a \u0645\u06cc\u200c\u0686\u0631\u062e\u0627\u0646\u062f.", + "Maze.ifTooltip": "\u0627\u06af\u0631 \u0645\u0633\u06cc\u0631\u06cc \u062f\u0631 \u06cc\u06a9 \u062c\u0647\u062a \u0648\u062c\u0648\u062f \u062f\u0627\u0631\u062f\u060c \u067e\u0633 \u06a9\u0627\u0631\u0647\u0627\u06cc\u06cc \u0627\u0646\u062c\u0627\u0645 \u0628\u062f\u0647.", + "Maze.ifelseTooltip": "\u0627\u06af\u0631 \u0645\u0633\u06cc\u0631\u06cc \u062f\u0631 \u062c\u0647\u062a \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647 \u0648\u062c\u0648\u062f \u062f\u0627\u0631\u062f\u060c \u0627\u0648\u0644 \u0627\u0648\u0644\u06cc\u0646 \u0628\u0644\u0648\u06a9 \u06a9\u0627\u0631\u0647\u0627 \u0631\u0627 \u0627\u0646\u062c\u0627\u0645 \u0628\u062f\u0647. \u062f\u0631 \u063a\u06cc\u0631 \u0627\u06cc\u0646\u0635\u0648\u0631\u062a \u0628\u0644\u0648\u06a9 \u062f\u0648\u0645 \u06a9\u0627\u0631\u0647\u0627 \u0631\u0627 \u0627\u0646\u062c\u0627\u0645 \u0628\u062f\u0647.", + "Maze.whileTooltip": "\u06a9\u0627\u0631\u0647\u0627\u06cc \u0645\u062d\u0635\u0648\u0631 \u0631\u0627 \u062a\u0627 \u0631\u0633\u06cc\u062f\u0646 \u0628\u0647 \u0646\u0642\u0637\u0647\u0654 \u067e\u0627\u06cc\u0627\u0646 \u062a\u06a9\u0631\u0627\u0631 \u06a9\u0646.", + "Maze.capacity0": "\u0634\u0645\u0627 %0 \u0628\u0644\u0648\u06a9 \u0628\u0627\u0642\u06cc\u200c\u0645\u0627\u0646\u062f\u0647 \u062f\u0627\u0631\u06cc\u062f.", + "Maze.capacity1": "\u0634\u0645\u0627 %1 \u0628\u0644\u0648\u06a9 \u0645\u0627\u0646\u062f\u0647 \u062f\u0627\u0631\u06cc\u062f.", + "Maze.capacity2": "\u0634\u0645\u0627 %2 \u0628\u0644\u0648\u06a9 \u0628\u0627\u0642\u06cc\u200c\u0645\u0627\u0646\u062f\u0647 \u062f\u0627\u0631\u06cc\u062f.", + "Maze.nextLevel": "\u062a\u0634\u0648\u06cc\u0642! \u0634\u0645\u0627 \u0628\u0631\u0627\u06cc \u0627\u062f\u0627\u0645\u0647 \u0628\u0647 \u0645\u0631\u062d\u0644\u0647 %1 \u0622\u0645\u0627\u062f\u0647 \u0647\u0633\u062a\u06cc\u062f\u061f", + "Maze.finalLevel": "\u062a\u0634\u0648\u06cc\u0642! \u0634\u0645\u0627 \u0622\u062e\u0631\u06cc\u0646 \u0645\u0631\u062d\u0644\u0647 \u0631\u0627 \u062d\u0644 \u06a9\u0631\u062f\u0647\u200c\u0627\u06cc\u062f.", + "Maze.maze": "\u067e\u06cc\u0686\u200c\u062f\u0631\u067e\u06cc\u0686", + "Maze.runTooltip": "\u0645\u06cc\u200c\u06af\u0630\u0627\u0631\u062f \u06a9\u0627\u0631\u0628\u0631 \u0622\u0646\u0686\u0647 \u06a9\u0647 \u0628\u0644\u0648\u06a9\u200c\u0647\u0627 \u0645\u06cc\u200c\u06af\u0648\u06cc\u062f \u0631\u0627 \u0627\u0646\u062c\u0627\u0645 \u062f\u0647\u062f.", + "Maze.resetTooltip": "\u0628\u0627\u0632\u06cc\u06a9\u0646 \u0631\u0627 \u062f\u0631 \u0627\u0648\u0644 \u0634\u0631\u0648\u0639 \u067e\u06cc\u0686\u200c\u062f\u0631\u067e\u06cc\u0686 \u0642\u0631\u0627\u0631 \u0628\u062f\u0647.", + "Maze.helpStack": "\u062a\u0639\u062f\u0627\u062f\u06cc \u0627\u0632 \u0628\u0644\u0648\u06a9\u200c\u0647\u0627\u06cc \u00ab\u062d\u0631\u06a9\u062a \u0628\u0647 \u062c\u0644\u0648\u00bb \u0631\u0627 \u0628\u0627 \u0647\u0645 \u062f\u0631 \u067e\u0634\u062a\u0647 \u0642\u0631\u0627\u0631 \u0628\u062f\u0647 \u06a9\u0647 \u0628\u0647 \u0631\u0633\u06cc\u062f\u0646 \u0645\u0646 \u0628\u0647 \u0647\u062f\u0641 \u06a9\u0645\u06a9 \u06a9\u0646\u062f.", + "Maze.helpOneTopBlock": "\u062f\u0631 \u0627\u06cc\u0646 \u0645\u0631\u062c\u0644\u0647\u060c \u0634\u0645\u0627 \u0646\u06cc\u0627\u0632\u0645\u0646\u062f \u0642\u0631\u0627\u0631 \u062f\u0627\u062f\u0646 \u0647\u0645\u0647\u0654 \u0628\u0644\u0648\u06a9\u200c\u0647\u0627 \u062f\u0631 \u0641\u0636\u0627\u06cc \u06a9\u0627\u0631 \u0633\u0641\u06cc\u062f \u0647\u0633\u062a\u06cc\u062f.", + "Maze.helpRun": "\u0627\u062c\u0631\u0627\u06cc \u0628\u0631\u0646\u0627\u0645\u0647\u0654 \u0634\u0645\u0627 \u0628\u0631\u0627\u06cc \u062f\u06cc\u062f\u0646 \u0627\u06cc\u0646\u06a9\u0647 \u0686\u0647 \u0631\u062e \u0645\u06cc\u200c\u062f\u0647\u062f.", + "Maze.helpReset": "\u0628\u0631\u0646\u0627\u0645\u0647\u0654 \u0634\u0645\u0627 \u067e\u06cc\u0686\u200c\u062f\u0631\u067e\u06cc\u0686 \u0631\u0627 \u062d\u0644 \u0646\u06a9\u0631\u062f. \u00ab\u0627\u0632 \u0646\u0648\u00bb \u0631\u0627 \u0641\u0634\u0627\u0631 \u062f\u0647\u06cc\u062f \u0648 \u062f\u0648\u0628\u0627\u0631\u0647 \u062a\u0644\u0627\u0634 \u06a9\u0646\u06cc\u062f.", + "Maze.helpRepeat": "\u0631\u0633\u06cc\u062f\u0646 \u0628\u0647 \u0627\u0646\u062a\u0647\u0627\u06cc \u0645\u0633\u06cc\u0631 \u0628\u0627 \u0641\u0642\u0637 \u062f\u0648 \u0628\u0644\u0648\u06a9. \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 \u00ab\u062f\u0648\u0628\u0627\u0631\u0647\u00bb \u0628\u0631\u0627\u06cc \u0627\u062c\u0631\u0627\u06cc \u06cc\u06a9 \u0628\u0644\u0648\u06a9 \u0628\u06cc\u0634\u062a\u0631 \u0627\u0632 \u06cc\u06a9\u06cc.", + "Maze.helpCapacity": "\u0634\u0645\u0627 \u0647\u0645\u0647\u0654 \u0628\u0644\u0648\u06a9\u200c\u0647\u0627\u06cc \u0627\u06cc\u0646 \u0645\u0631\u062d\u0644\u0647 \u0631\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u06a9\u0631\u062f\u0647\u200c\u0627\u06cc\u062f. \u0628\u0631\u0627\u06cc \u0627\u06cc\u062c\u0627\u062f \u06cc\u06a9 \u0628\u0644\u0648\u06a9 \u062c\u062f\u06cc\u062f\u060c \u0634\u0645\u0627 \u0627\u0628\u062a\u062f\u0627 \u0646\u06cc\u0627\u0632\u0645\u0646\u062f \u062d\u0630\u0641 \u06cc\u06a9 \u0628\u0644\u0648\u06a9 \u0645\u0648\u062c\u0648\u062f \u0647\u0633\u062a\u06cc\u062f.", + "Maze.helpRepeatMany": "\u0634\u0645\u0627 \u0645\u06cc\u200c\u062a\u0648\u0627\u0646\u06cc\u062f \u0628\u06cc\u0634\u062a\u0631 \u0627\u0632 \u0628\u0644\u0648\u06a9 \u0631\u0627 \u062f\u0631 \u0628\u0644\u0648\u06a9 \u00ab\u062a\u06a9\u0631\u0627\u0631\u00bb \u062c\u0627\u06cc \u062f\u0647\u06cc\u062f.", + "Maze.helpSkins": "\u0627\u0646\u062a\u062e\u0627\u0628 \u0628\u0627\u0632\u06cc\u06a9\u0646 \u0645\u062c\u0628\u0648\u0628 \u0634\u0645\u0627 \u0627\u0632 \u0627\u06cc\u0646 \u0645\u0646\u0648.", + "Maze.helpIf": "\u06cc\u06a9 \u0628\u0644\u0648\u06a9 \u00ab\u0627\u06af\u0631\u00bb \u06a9\u0627\u0631\u06cc \u0627\u0646\u062c\u0627\u0645 \u0645\u06cc\u200c\u062f\u0647\u062f \u0627\u06af\u0631 \u0634\u0631\u0627\u06cc\u0637 \u0635\u0627\u062f\u0642 \u0628\u0648\u062f. \u0686\u0631\u062e\u0634 \u0628\u0647 \u0686\u067e \u0631\u0627 \u0622\u0632\u0645\u0627\u06cc\u0634 \u06a9\u0646\u06cc\u062f \u0627\u06af\u0631 \u06cc\u06a9 \u0645\u0633\u06cc\u0631 \u0628\u0647 \u0686\u067e \u0627\u0633\u062a.", + "Maze.helpMenu": "\u0628\u0631 %1 \u062f\u0631 \u0628\u0644\u0648\u06a9 \u00ab\u0627\u06af\u0631\u00bb \u06a9\u0644\u06cc\u06a9 \u06a9\u0646\u06cc\u062f \u06a9\u0647 \u0634\u0631\u0627\u06cc\u0637 \u0631\u0627 \u062a\u063a\u06cc\u06cc\u0631 \u062f\u0647\u06cc\u062f.", + "Maze.helpWallFollow": "\u0645\u06cc\u200c\u062a\u0648\u0627\u0646\u06cc\u062f \u06cc\u06a9 \u067e\u06cc\u0686\u200c\u062f\u0631\u067e\u06cc\u0686 \u067e\u06cc\u0686\u06cc\u062f\u0647 \u0631\u0627 \u062c\u0644 \u06a9\u0646\u06cc\u062f\u061f \u0627\u0632 \u062f\u06cc\u0648\u0627\u0631 \u062f\u0633\u062a \u0686\u067e \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u06a9\u0646\u06cc\u062f. \u0628\u0631\u0646\u0627\u0645\u0647\u200c\u0646\u0648\u06cc\u0633\u0627\u0646 \u062d\u0631\u0641\u0647\u200c\u0627\u06cc \u0641\u0642\u0637!", + "Plane.rows": "\u0631\u062f\u06cc\u0641: %1", + "Plane.getRows": "\u0631\u062f\u06cc\u0641\u200c\u0647\u0627 (%1)", + "Plane.rows1": "\u0627\u0648\u0644\u06cc\u0646 \u0631\u062f\u06cc\u0641 \u06a9\u0644\u0627\u0633: %1", + "Plane.getRows1": "\u0627\u0648\u0644\u06cc\u0646 \u06a9\u0644\u0627\u0633 \u0631\u062f\u06cc\u0641\u200c\u0647\u0627 (%1)", + "Plane.rows2": "\u062f\u0648\u0645\u06cc\u0646 \u06a9\u0644\u0627\u0633 \u0631\u062f\u06cc\u0641: %1", + "Plane.getRows2": "\u062f\u0648\u0645\u06cc\u0646 \u06a9\u0644\u0627\u0633 \u0631\u062f\u06cc\u0641\u200c\u0647\u0627 (%1)", + "Plane.seats": "\u0635\u0646\u062f\u0644\u06cc\u200c\u0647\u0627: %1", + "Plane.placeholder": "\u061f", + "Plane.setSeats": "\u0635\u0646\u062f\u0644\u06cc\u200c\u0647\u0627 =", + "Plane.plane": "\u0637\u0631\u062d\u200c\u0647\u0627", + "Plane.description1": "\u06cc\u06a9 \u0647\u0648\u0627\u067e\u06cc\u0645\u0627 \u062a\u0639\u062f\u0627\u062f \u0627\u0632 \u0635\u0646\u062f\u0644\u06cc\u200c\u0647\u0627\u06cc \u0645\u0633\u0627\u0641\u0631\u06cc\u0646 \u0631\u0627 \u062f\u0627\u0631\u062f. \u0647\u0631 \u0631\u062f\u06cc\u0641 \u0634\u0645\u0627\u0644 \u0686\u0647\u0627\u0631 \u0635\u0646\u062f\u0644\u06cc \u0627\u0633\u062a.", + "Plane.description2": "\u06cc\u06a9 \u0647\u0648\u0627\u067e\u06cc\u0645\u0627 \u062f\u0648 \u0635\u0646\u062f\u0644\u06cc \u062f\u0631 \u0639\u0631\u0634\u0647\u0654 \u067e\u0631\u0648\u0627\u0632 \u062f\u0627\u0631\u062f (\u0628\u0631\u0627\u06cc \u062e\u0644\u0628\u0627\u0646 \u0648 \u06a9\u0645\u06a9 \u062e\u0644\u0628\u0627\u0646) \u0648 \u062a\u0639\u062f\u0627\u062f\u06cc \u0635\u0646\u062f\u0644\u06cc \u0645\u0633\u0627\u0641\u0631\u06cc\u0646. \u0647\u0631 \u0631\u062f\u06cc\u0641 \u0634\u0627\u0645\u0644 \u0686\u0647\u0627\u0631 \u0635\u0646\u062f\u0644\u06cc \u0627\u0633\u062a.", + "Plane.description3": "\u06cc\u06a9 \u0647\u0648\u0627\u067e\u06cc\u0645\u0627 \u062f\u0648 \u0635\u0646\u062f\u0644\u06cc \u062f\u0631 \u06a9\u0627\u0628\u06cc\u0646 \u062e\u0644\u0628\u0627\u0646 \u062f\u0627\u0631\u062f (\u0628\u0631\u0627\u06cc \u062e\u0644\u0628\u0627\u0646 \u0648 \u06a9\u0645\u06a9 \u062e\u0644\u0628\u0627\u0646) \u0648 \u062a\u0647\u062f\u0627\u062f \u0627\u0632 \u0635\u0646\u062f\u0644\u06cc\u200c\u0647\u0627 \u0645\u0633\u0627\u0641\u0631\u06cc\u0646 \u062f\u0631\u062c\u0647 \u06cc\u06a9 \u0648 \u062f\u0631\u062c\u0647 \u062f\u0648. \u0647\u0631 \u0631\u062f\u06cc\u0641 \u062f\u0631\u062c\u0647 \u06cc\u06a9 \u0634\u0627\u0645\u0644 \u0686\u0647\u0627\u0631 \u0635\u0646\u062f\u0644\u06cc \u0627\u0633\u062a. \u0647\u0631 \u0631\u062f\u06cc\u0641 \u062f\u0631\u062c\u0647 \u062f\u0648 \u0634\u0627\u0645\u0644 \u067e\u0646\u062c \u0635\u0646\u062f\u0644\u06cc \u0627\u0633\u062a.", + "Plane.instructions": "\u06cc\u06a9 \u0641\u0631\u0645\u0648\u0644 \u0628\u0633\u0627\u0632\u06cc\u062f (\u067e\u0627\u06cc\u06cc\u0646) \u06a9\u0647 \u062a\u0639\u062f\u0627\u062f \u06a9\u0644 \u0635\u0646\u062f\u0644\u06cc\u200c\u0647\u0627\u06cc \u0647\u0648\u0627\u067e\u06cc\u0645\u0627 \u0628\u0627 \u062a\u063a\u06cc\u06cc\u0631 \u0631\u062f\u06cc\u0641 \u0631\u0627 \u062d\u0633\u0627\u0628 \u06a9\u0646\u062f (\u0628\u0627\u0644\u0627).", + "Puzzle.country1": "\u0627\u0633\u062a\u0631\u0627\u0644\u06cc\u0627", + "Puzzle.country1Language": "\u0627\u0646\u06af\u0644\u06cc\u0633\u06cc", + "Puzzle.country1City1": "\u0645\u0644\u0628\u0648\u0631\u0646", + "Puzzle.country1City2": "\u0633\u06cc\u062f\u0646\u06cc", + "Puzzle.country1HelpUrl": "http://en.wikipedia.org/wiki/Australia", + "Puzzle.country2": "\u0622\u0644\u0645\u0627\u0646", + "Puzzle.country2Language": "\u0622\u0644\u0645\u0627\u0646\u06cc", + "Puzzle.country2City1": "\u0628\u0631\u0644\u06cc\u0646", + "Puzzle.country2City2": "\u0645\u0648\u0646\u06cc\u062e", + "Puzzle.country2HelpUrl": "http://en.wikipedia.org/wiki/Germany", + "Puzzle.country3": "\u0686\u06cc\u0646", + "Puzzle.country3Language": "\u0686\u06cc\u0646\u06cc", + "Puzzle.country3City1": "\u067e\u06a9\u0646", + "Puzzle.country3City2": "\u0634\u0627\u0646\u06af\u0647\u0627\u06cc", + "Puzzle.country3HelpUrl": "http://en.wikipedia.org/wiki/China", + "Puzzle.country4": "\u0628\u0631\u0632\u06cc\u0644", + "Puzzle.country4Language": "\u067e\u0631\u062a\u063a\u0627\u0644\u06cc", + "Puzzle.country4City1": "\u0631\u06cc\u0648 \u062f\u0648 \u0698\u0627\u0646\u06cc\u0631\u0648", + "Puzzle.country4City2": "\u0633\u0627\u0626\u0648 \u067e\u0627\u0626\u0648\u0644\u0648", + "Puzzle.country4HelpUrl": "http://en.wikipedia.org/wiki/Brazil", + "Puzzle.flag": "\u067e\u0631\u0686\u0645:", + "Puzzle.language": "\u0632\u0628\u0627\u0646:", + "Puzzle.languageChoose": "\u0627\u0646\u062a\u062e\u0627\u0628 \u06a9\u0646\u06cc\u062f...", + "Puzzle.cities": "\u0634\u0647\u0631\u0647\u0627:", + "Puzzle.error0": "\u0639\u0627\u0644\u06cc!\n\u0647\u0631 %1 \u0628\u0644\u0648\u06a9 \u062f\u0631\u0633\u062a \u0627\u0633\u062a.", + "Puzzle.error1": "\u062a\u0642\u0631\u06cc\u0628\u0627! \u06cc\u06a9 \u0628\u0644\u0648\u06a9 \u0646\u0627\u062f\u0631\u0633\u062a \u0627\u0633\u062a.", + "Puzzle.error2": "%1 \u0628\u0644\u0648\u06a9 \u0646\u0627\u062f\u0631\u0633\u062a \u0627\u0633\u062a.", + "Puzzle.tryAgain": "\u0628\u0644\u0648\u06a9 \u067e\u0631\u0631\u0646\u06af \u0634\u062f\u0647 \u062f\u0631\u0633\u062a \u0646\u06cc\u0633\u062a.\n\u0645\u062c\u062f\u062f\u0627 \u062a\u0644\u0627\u0634 \u06a9\u0646\u06cc\u062f.", + "Puzzle.title": "\u067e\u0627\u0632\u0644", + "Puzzle.help": "\u0631\u0627\u0647\u0646\u0645\u0627", + "Puzzle.checkAnswers": "\u0628\u0631\u0631\u0633\u06cc \u067e\u0627\u0633\u062e", + "Puzzle.helpText": "\u0628\u0631\u0627\u06cc \u0647\u0631 \u06a9\u0634\u0648\u0631 (\u0633\u0628\u0632)\u060c \u062f\u0631 \u06a9\u0646\u0627\u0631 \u067e\u0631\u0686\u0645\u200c\u0634\u0627\u0646\u060c \u0632\u0628\u0627\u0646\u0634\u0627\u0646 \u0631\u0627 \u0627\u0646\u062a\u062e\u0627\u0628 \u06a9\u0646\u06cc\u062f \u0648 \u0641\u0647\u0631\u0633\u062a \u0634\u0647\u0631\u0647\u0627\u06cc\u0634 \u0631\u0627 \u0645\u0634\u062e\u0635 \u0646\u0645\u0627\u0626\u06cc\u062f", + "Turtle.moveTooltip": "\u0644\u0627\u06a9 \u067e\u0634\u062a \u0631\u0627 \u0628\u0647 \u0645\u0642\u062f\u0627\u0631 \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647 \u062c\u0644\u0648 \u06cc\u0627 \u0639\u0642\u0628 \u0645\u0646\u062a\u0642\u0644 \u0645\u06cc\u200c\u06a9\u0646\u062f.", + "Turtle.moveForward": "\u0627\u0646\u062a\u0642\u0627\u0644 \u0628\u0647 \u062c\u0644\u0648 \u062a\u0627", + "Turtle.moveBackward": "\u0627\u0646\u062a\u0642\u0627\u0644 \u0628\u0647 \u067e\u0634\u062a \u062a\u0627", + "Turtle.turnTooltip": "\u0686\u0631\u062e\u0627\u0646\u062f\u0646 \u0644\u0627\u06a9 \u067e\u0634\u062a \u0628\u0647 \u0686\u067e \u06cc\u0627 \u0631\u0627\u0633\u062a \u0628\u0627 \u0639\u062f\u062f \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647\u0654 \u062f\u0631\u062c\u0647.", + "Turtle.turnRight": "\u0686\u0631\u062e\u0634 \u0628\u0647 \u0631\u0627\u0633\u062a \u0628\u0647 \u0645\u0642\u062f\u0627\u0631", + "Turtle.turnLeft": "\u0686\u0631\u062e\u0634 \u0628\u0647 \u0686\u067e \u0628\u0647 \u0645\u0642\u062f\u0627\u0631", + "Turtle.widthTooltip": "\u067e\u0647\u0646\u0627\u06cc \u0642\u0644\u0645 \u0631\u0627 \u062a\u063a\u06cc\u06cc\u0631 \u0645\u06cc\u200c\u062f\u0647\u062f.", + "Turtle.setWidth": "\u062a\u0646\u0638\u06cc\u0645 \u067e\u0647\u0646\u0627 \u0628\u0647", + "Turtle.colourTooltip": "\u0631\u0646\u06af \u0642\u0644\u0645 \u0631\u0627 \u062a\u063a\u06cc\u06cc\u0631 \u0645\u06cc\u200c\u062f\u0647\u062f.", + "Turtle.setColour": "\u062a\u0646\u0638\u06cc\u0645 \u0631\u0646\u06af \u0628\u0647", + "Turtle.penTooltip": "\u067e\u0627\u0644\u0627 \u06cc\u0627 \u067e\u0627\u06cc\u06cc\u0646\u200c\u0628\u0631\u062f\u0646 \u0642\u0644\u0645\u060c \u0628\u0631\u0627\u06cc \u0634\u0631\u0648\u0639 \u06cc\u0627 \u067e\u0627\u06cc\u0627\u0646 \u0646\u0642\u0627\u0634\u06cc.", + "Turtle.penUp": "\u0642\u0644\u0645 \u062a\u0627", + "Turtle.penDown": "\u0642\u0644\u0645 \u067e\u0627\u06cc\u06cc\u0646", + "Turtle.turtleVisibilityTooltip": "(\u062f\u0627\u06cc\u0631\u0647 \u0648 \u0641\u0644\u0634) \u0644\u0627\u06a9\u200c\u06a9\u067e\u0634\u062a \u0631\u0627 \u0638\u0627\u0647\u0631 \u06cc\u0627 \u067e\u0646\u0647\u0627\u0646 \u0645\u06cc\u200c\u06a9\u0646\u062f.", + "Turtle.hideTurtle": "\u067e\u0646\u0647\u0627\u0646\u200c\u06a9\u0631\u062f\u0646 \u0644\u0627\u06a9\u200c\u067e\u0634\u062a", + "Turtle.showTurtle": "\u0646\u0645\u0627\u06cc\u0634 \u0644\u0627\u06a9\u200c\u067e\u0634\u062a", + "Turtle.printHelpUrl": "http://fa.wikipedia.org/wiki/%DA%86%D8%A7%D9%BE_%28%D8%B5%D9%86%D8%B9%D8%AA%29", + "Turtle.printTooltip": "\u06a9\u0634\u06cc\u062f\u0646 \u0645\u062a\u0646 \u062f\u0631 \u062c\u0647\u062a \u0644\u0627\u06a9\u200c\u067e\u0634\u062a \u0648 \u0645\u0648\u0642\u0639\u06cc\u062a\u0634.", + "Turtle.print": "\u0686\u0627\u067e", + "Turtle.fontHelpUrl": "http://fa.wikipedia.org/wiki/%D9%82%D9%84%D9%85_%28%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29", + "Turtle.fontTooltip": "\u0627\u0646\u062f\u0627\u0632\u0647\u0654 \u0642\u0644\u0645 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0634\u062f\u0647 \u062a\u0648\u0633\u0637 \u0686\u0627\u067e \u0628\u0644\u0648\u06a9 \u0631\u0627 \u0645\u0634\u062e\u0635 \u0645\u06cc\u200c\u06a9\u0646\u062f.", + "Turtle.font": "\u0642\u0644\u0645", + "Turtle.fontSize": "\u0627\u0646\u062f\u0627\u0632\u0647\u0654 \u0642\u0644\u0645", + "Turtle.fontNormal": "\u0639\u0627\u062f\u06cc", + "Turtle.fontBold": "\u067e\u0631\u0631\u0646\u06af", + "Turtle.fontItalic": "\u06a9\u062c", + "Turtle.unloadWarning": "\u0631\u0647\u0627\u06a9\u0631\u062f\u0646 \u0627\u06cc\u0646 \u0635\u0641\u062d\u0647 \u0628\u0627\u0639\u062b \u067e\u0627\u06a9\u200c\u0634\u062f\u0646 \u06a9\u0627\u0631 \u0634\u0645\u0627 \u062e\u0648\u0627\u0647\u062f \u0634\u062f.", + "Turtle.title": "\u06af\u0631\u0627\u0641\u06cc\u06a9 \u0644\u0627\u06a9\u200c\u067e\u0634\u062a", + "Turtle.runTooltip": "\u0627\u062c\u0627\u0632\u0647 \u0645\u06cc\u200c\u062f\u0647\u062f \u0644\u0627\u06a9\u200c\u067e\u0634\u062a \u0647\u0631 \u0686\u0647 \u0628\u0644\u0648\u06a9 \u0645\u06cc\u200c\u06af\u0648\u06cc\u062f \u0631\u0627 \u0627\u0646\u062c\u0627\u0645 \u062f\u0647\u062f.", + "Turtle.captureTooltip": "\u0630\u062e\u06cc\u0631\u0647\u0654 \u0646\u0642\u0627\u0634\u06cc.", + "Turtle.imgFilename": "drawing.png", + "Turtle.catTurtle": "\u0644\u0627\u06a9\u200c\u067e\u0634\u062a" +} \ No newline at end of file diff --git a/apps/json/fi.json b/apps/json/fi.json new file mode 100644 index 000000000..2a46a4856 --- /dev/null +++ b/apps/json/fi.json @@ -0,0 +1,35 @@ +{ + "Puzzle.tryAgain": "Korostettu lohko ei ole oikein.\nYritä uudelleen.", + "Puzzle.country3City2": "Shanghai", + "Puzzle.country3HelpUrl": "http://fi.wikipedia.org/wiki/Kiina", + "Puzzle.country3Language": "kiina", + "Puzzle.checkAnswers": "Tarkista vastaukset", + "Puzzle.language": "kieli:", + "Apps.dialogOk": "OK", + "Puzzle.title": "Palapeli", + "Puzzle.country1HelpUrl": "http://fi.wikipedia.org/wiki/Australia", + "Puzzle.languageChoose": "valitse...", + "Puzzle.country4City2": "São Paulo", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4Language": "portugali", + "Puzzle.helpText": "Kullekin maalle (vihreä), liitä oikea lippu, valitse kieli ja tee pino kaupungeista.", + "Puzzle.flag": "lippu:", + "Puzzle.country4HelpUrl": "http://fi.wikipedia.org/wiki/Brasilia", + "Puzzle.error1": "Lähes oikein! Vain yksi lohko on väärin.", + "Puzzle.country3City1": "Beijing", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country2Language": "saksa", + "Puzzle.country3": "Kiina", + "Puzzle.country2": "Saksa", + "Puzzle.country1": "Australia", + "Puzzle.country2HelpUrl": "http://fi.wikipedia.org/wiki/Saksa", + "Puzzle.error0": "Hienoa!\nKaikki %1 lohkoa ovat oikein.", + "Puzzle.country4": "Brasilia", + "Puzzle.error2": "%1 lohkoa ovat virheellisiä.", + "Puzzle.help": "Ohje", + "Puzzle.country1Language": "englanti", + "Puzzle.country2City1": "Berliini", + "Puzzle.cities": "kaupungit:", + "Puzzle.country2City2": "München" +} diff --git a/apps/json/fo.json b/apps/json/fo.json new file mode 100644 index 000000000..17e3ec22b --- /dev/null +++ b/apps/json/fo.json @@ -0,0 +1,35 @@ +{ + "Puzzle.tryAgain": "Tann upplýsti blokkurin er ikki rættur.\nRoyn aftur.", + "Puzzle.country3City2": "Shanghai", + "Puzzle.country3HelpUrl": "http://fo.wikipedia.org/wiki/Kina", + "Puzzle.country3Language": "Kinesiskt", + "Puzzle.checkAnswers": "Hygg eftir svarunum", + "Puzzle.language": "mál:", + "Apps.dialogOk": "OK", + "Puzzle.title": "Putlispæl", + "Puzzle.country1HelpUrl": "http://fo.wikipedia.org/wiki/Avstralia", + "Puzzle.languageChoose": "vel...", + "Puzzle.country4City2": "São Paulo", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4Language": "Portugisiskt", + "Puzzle.helpText": "Fyri hvørt land (grønt), skal tú seta tað flaggið ið hoyrir til, vel mál hjá landinum, og bólka býirnir til tað land, ið teir hoyra til.", + "Puzzle.flag": "flagg:", + "Puzzle.country4HelpUrl": "http://fo.wikipedia.org/wiki/Brasil", + "Puzzle.error1": "Næstan! Ein blokkur er ikki rættur.", + "Puzzle.country3City1": "Beijing", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country2Language": "Týskt", + "Puzzle.country3": "Kina", + "Puzzle.country2": "Týskland", + "Puzzle.country1": "Avstralia", + "Puzzle.country2HelpUrl": "http://fo.wikipedia.org/wiki/Týskland", + "Puzzle.error0": "Einastandandi!\nAllir %1 blokkar eru rættir.", + "Puzzle.country4": "Brasil", + "Puzzle.error2": "%1 blokkar eru ikki rættir.", + "Puzzle.help": "Hjálp", + "Puzzle.country1Language": "Enskt", + "Puzzle.country2City1": "Berlin", + "Puzzle.cities": "býir:", + "Puzzle.country2City2": "München" +} diff --git a/apps/json/fr.json b/apps/json/fr.json new file mode 100644 index 000000000..488756753 --- /dev/null +++ b/apps/json/fr.json @@ -0,0 +1,150 @@ +{ + "@metadata": { + "authors": [ + "Gomoko" + ] + }, + "Apps.subtitle": "un environnement de programmation visuel", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Voir le code JavaScript g\u00e9n\u00e9r\u00e9'.", + "Apps.linkTooltip": "Sauvegarde et lies aux blocs.", + "Apps.runTooltip": "Lancer le programme d\u00e9fini par les blocs dans l\u2019espace de travail.", + "Apps.runProgram": "Execute le programme", + "Apps.resetProgram": "Reset", + "Apps.dialogOk": "OK", + "Apps.dialogCancel": "Annuler", + "Apps.catLogic": "Logique", + "Apps.catLoops": "Boucles", + "Apps.catMath": "Math", + "Apps.catText": "Texte", + "Apps.catLists": "Listes", + "Apps.catColour": "Couleur", + "Apps.catVariables": "Variables", + "Apps.catProcedures": "Proc\u00e9dures", + "Apps.httpRequestError": "Il y a eu un probl\u00e8me avec la demande.", + "Apps.linkAlert": "Partagez vos blocs gr\u00e2ce \u00e0 ce lien:\n\n%1", + "Apps.hashError": "D\u00e9sol\u00e9, '%1' ne correspond pas \u00e0 un fichier Blockly sauvegarde.", + "Apps.xmlError": "Impossible de charger le fichier de sauvegarde. Peut \u00eatre a t-il ete cr\u00e9\u00e9 avec une autre version de Blockly?", + "Apps.listVariable": "liste", + "Apps.textVariable": "texte", + "Code.badXml": "Erreur d\u2019analyse du XML :\n%1\n\nS\u00e9lectionner 'OK' pour abandonner vos modifications ou 'Annuler' pour modifier encore le XML.", + "Code.badCode": "Erreur du programme :\n%1", + "Code.timeout": "Nombre maximum d\u2019it\u00e9rations d\u2019ex\u00e9cution d\u00e9pass\u00e9.", + "Code.discard": "Supprimer tous les %1 blocs\u202f?", + "Code.title": "Code", + "Code.blocks": "Blocs", + "Code.trashTooltip": "Jeter tous les blocs.", + "Graph.title": "Calculatrice graphique", + "Maze.moveForward": "avance", + "Maze.turnLeft": "tourne \u00e0 gauche", + "Maze.turnRight": "tourne \u00e0 droite", + "Maze.doCode": "faire", + "Maze.elseCode": "sinon", + "Maze.helpIfElse": "Un bloc 'Si-Sinon' ex\u00e9cute une chose ou une autre.", + "Maze.pathAhead": "si chemin devant", + "Maze.pathLeft": "si chemin vers la gauche", + "Maze.pathRight": "si chem vers la droite", + "Maze.repeatUntil": "r\u00e9p\u00e8te jusqu'a", + "Maze.moveForwardTooltip": "Fais avancer monsieur Pegman en avant d'un espace.", + "Maze.turnTooltip": "Fais tourner monsieur Pegman \u00e0 gauche ou \u00e0 droite de 90 degr\u00e9s.", + "Maze.ifTooltip": "Si il y'a un chemin dans la direction specifi\u00e9e, alors effectue ces actions.", + "Maze.ifelseTooltip": "Si il y'a un chemin dans la direction specifi\u00e9e, alors fais le premier bloc d'actions. Sinon fais le second bloc d'actions.", + "Maze.whileTooltip": "R\u00e9p\u00e8te les blocs qui sont \u00e0 l'int\u00e9rieur jusqu'\u00e0 atteindre le but.", + "Maze.capacity0": "Il te reste %0 blocs.", + "Maze.capacity1": "Il te reste %1 bloc.", + "Maze.capacity2": "Il te reste %2 blocs.", + "Maze.nextLevel": "Bravo ! Est tu pr\u00eat pour le niveau %1?", + "Maze.finalLevel": "Bravo ! Tu as fini le dernier niveau.", + "Maze.maze": "Labyrinthe", + "Maze.runTooltip": "Faire faire au joueur ce que disent les blocs.", + "Maze.resetTooltip": "Replacer le joueur au d\u00e9but du labyrinthe.", + "Maze.helpStack": "Empiler ensemble deux blocs d\u2019instructions 'avance' pour m\u2019aider \u00e0 atteindre le but.", + "Maze.helpOneTopBlock": "Dans ce niveau, tu as besoin d'empiler les blocs les uns au dessus des autres dans la zone de travail blanche.", + "Maze.helpRun": "Ex\u00e9cuter votre programme pour voir ce qui arrive.", + "Maze.helpReset": "Votre programme n\u2019a pas r\u00e9solu le labyrinthe. Appuyez sur 'R\u00e9initialiser' et r\u00e9essayez.", + "Maze.helpRepeat": "Les ordinateurs n'ont pas beaucoup de m\u00e9moire. Utilise seulement deux blocs pour atteindre le but. Utilise le bloc 'rep\u00e8te' pour ex\u00e9cuter un bloc plus d'une fois.", + "Maze.helpCapacity": "Vous avez utilis\u00e9 tous les blocs pour ce niveau. Pour cr\u00e9er un nouveau bloc, vous devez d\u2019abord supprimer un bloc existant.", + "Maze.helpRepeatMany": "Vous pouvez mettre plus d\u2019un bloc dans un bloc \u00ab\u202fr\u00e9p\u00e9ter\u202f\u00bb.", + "Maze.helpSkins": "Choisissez votre joueur favori dans ce menu.", + "Maze.helpIf": "Un bloc 'si' va ex\u00e9cuter ce qu'il y a dedans seulement si la condition est vraie. Essaie de tourner \u00e0 gauche si il y a un chemin sur la gauche.", + "Maze.helpMenu": "Cliquez sur %1 dans le bloc 'si' pour modifier sa condition.", + "Maze.helpWallFollow": "Peux tu r\u00e9soudre ce labyrinthe plus difficile? Essaie de suivre le mur du c\u00f4t\u00e9 de ta main gauche.", + "Plane.rows": "Rang\u00e9es : %1", + "Plane.getRows": "rang\u00e9es (%1)", + "Plane.rows1": "rang\u00e9es de premi\u00e8re classe : %1", + "Plane.getRows1": "rang\u00e9es de premi\u00e8re classe (%1)", + "Plane.rows2": "rang\u00e9es de seconde classe : %1", + "Plane.getRows2": "rang\u00e9es de seconde classe (%1)", + "Plane.seats": "Si\u00e8ges : %1", + "Plane.placeholder": "?", + "Plane.setSeats": "si\u00e8ges =", + "Plane.plane": "Avion", + "Plane.description1": "Un avion a un nombre de rang\u00e9es de si\u00e8ges passager. Chaque rang\u00e9e contient quatre si\u00e8ges.", + "Plane.description2": "Un avion a deux si\u00e8ges dans le poste de pilotage (pour le pilote et le copilote), et un certain nombre de rang\u00e9es de si\u00e8ges passager. Chaque rang\u00e9e contient quatre si\u00e8ges.", + "Plane.description3": "Un avion a deux si\u00e8ges dans la cabine de pilotage (pour le pilote et le copilote), et un certain nombre de rang\u00e9es de si\u00e8ges passager de premi\u00e8re et seconde classes. Chaque rang\u00e9e de premi\u00e8re classe contient quatre si\u00e8ges. Chaque rang\u00e9e de seconde classe contient cinq si\u00e8ges.", + "Plane.instructions": "Construire une formule (ci-dessous) qui calcule le nombre total de si\u00e8ges dans l\u2019avion quand le nombre de rang\u00e9es est modifi\u00e9 (ci-dessus).", + "Puzzle.country1": "Australie", + "Puzzle.country1Language": "Anglais", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://fr.wikipedia.org/wiki/Australie", + "Puzzle.country2": "Allemagne", + "Puzzle.country2Language": "Allemand", + "Puzzle.country2City1": "Berlin", + "Puzzle.country2City2": "Munich", + "Puzzle.country2HelpUrl": "http://fr.wikipedia.org/wiki/Allemagne", + "Puzzle.country3": "Chine", + "Puzzle.country3Language": "Chinois", + "Puzzle.country3City1": "P\u00e9kin", + "Puzzle.country3City2": "Shanghai", + "Puzzle.country3HelpUrl": "http://fr.wikipedia.org/wiki/Chine", + "Puzzle.country4": "Br\u00e9sil", + "Puzzle.country4Language": "Portugais", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "S\u00e3o Paulo", + "Puzzle.country4HelpUrl": "http://fr.wikipedia.org/wiki/Br%C3%A9sil", + "Puzzle.flag": "drapeau:", + "Puzzle.language": "langue:", + "Puzzle.languageChoose": "choisis...", + "Puzzle.cities": "villes:", + "Puzzle.error0": "Parfait! Tous les %1 blocs sont corrects.", + "Puzzle.error1": "Presque! Un block est incorrect.", + "Puzzle.error2": "%1 blocks sont incorrects.", + "Puzzle.tryAgain": "Le bloc en surbrillance est incorrect. Ressaie.", + "Puzzle.title": "Puzzle", + "Puzzle.help": "Aider", + "Puzzle.checkAnswers": "V\u00e9rifiez les r\u00e9ponses", + "Puzzle.helpText": "Pour chaque pays (en vert), attache son drapeau, choisis sa langue, et fais un empilage de ses villes.", + "Turtle.moveTooltip": "D\u00e9place la tortue en avant ou en arri\u00e8re de la quantit\u00e9 indiqu\u00e9e.", + "Turtle.moveForward": "avancer de", + "Turtle.moveBackward": "reculer de", + "Turtle.turnTooltip": "Faire tourner la tortue \u00e0 gauche ou \u00e0 droite du nombre de degr\u00e9s indiqu\u00e9.", + "Turtle.turnRight": "tourner \u00e0 droite de", + "Turtle.turnLeft": "tourner \u00e0 gauche de", + "Turtle.widthTooltip": "Modifier la grosseur du stylo.", + "Turtle.setWidth": "mettre la grosseur \u00e0", + "Turtle.colourTooltip": "Modifier la couleur du stylo.", + "Turtle.setColour": "mettre la couleur \u00e0", + "Turtle.penTooltip": "Lever ou poser le stylo, pour arr\u00eater ou commencer de dessiner.", + "Turtle.penUp": "lever le stylo", + "Turtle.penDown": "poser le style", + "Turtle.turtleVisibilityTooltip": "Rend la tortue (cercle et fl\u00e8che) visible ou non.", + "Turtle.hideTurtle": "cacher la tortue", + "Turtle.showTurtle": "afficher la tortue", + "Turtle.printHelpUrl": "http://en.wikipedia.org/wiki/Printing", + "Turtle.printTooltip": "Dessine le texte dans la direction de la tortue \u00e0 son emplacement.", + "Turtle.print": "\u00e9crire", + "Turtle.fontHelpUrl": "http://en.wikipedia.org/wiki/Font", + "Turtle.fontTooltip": "D\u00e9finit la police utilis\u00e9e par le bloc d\u2019\u00e9criture.", + "Turtle.font": "police", + "Turtle.fontSize": "taille de la police", + "Turtle.fontNormal": "normal", + "Turtle.fontBold": "gras", + "Turtle.fontItalic": "italique", + "Turtle.unloadWarning": "Quitter cette page provoquera la perte de votre travail.", + "Turtle.title": "Tortue dessinatrice", + "Turtle.runTooltip": "Faire faire \u00e0 la tortue ce que disent les blocs.", + "Turtle.captureTooltip": "Enregistrer le dessin.", + "Turtle.imgFilename": "drawing.png", + "Turtle.catTurtle": "Tortue" +} \ No newline at end of file diff --git a/apps/json/frr.json b/apps/json/frr.json new file mode 100644 index 000000000..e474384c2 --- /dev/null +++ b/apps/json/frr.json @@ -0,0 +1,35 @@ +{ + "Puzzle.tryAgain": "Di kääntiakent baustian as ferkiard. Ferschük det noch ans.", + "Puzzle.country3City2": "Schanghai", + "Puzzle.country3HelpUrl": "http://frr.wikipedia.org/wiki/Sjiina", + "Puzzle.country3Language": "Sjineesk", + "Puzzle.checkAnswers": "Oonswaaren efterluke", + "Puzzle.language": "Spriak:", + "Apps.dialogOk": "OK", + "Puzzle.title": "Puzzle", + "Puzzle.country1HelpUrl": "http://frr.wikipedia.org/wiki/Austraalien", + "Puzzle.languageChoose": "Schük ütj ...", + "Puzzle.country4City2": "São Paulo", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4Language": "Portugiisk", + "Puzzle.helpText": "Hinge för arke lun (green) sin flag bi, schük det spriak ütj an maage en staapel mä stääden.", + "Puzzle.flag": "Flag", + "Puzzle.country4HelpUrl": "http://frr.wikipedia.org/wiki/Brasiilien", + "Puzzle.error1": "Binai! Ian baustian as ferkiard.", + "Puzzle.country3City1": "Peking", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country2Language": "Sjiisk", + "Puzzle.country3": "Sjiina", + "Puzzle.country2": "Sjiisklun", + "Puzzle.country1": "Austraalien", + "Puzzle.country2HelpUrl": "http://frr.wikipedia.org/wiki/Sjiisklun", + "Puzzle.error0": "Klaar! Aal a %1 baustianer san rocht.", + "Puzzle.country4": "Brasiilien", + "Puzzle.error2": "%1 baustianer san ferkiard.", + "Puzzle.help": "Halep", + "Puzzle.country1Language": "Ingelsk", + "Puzzle.country2City1": "Berlin", + "Puzzle.cities": "Stääden:", + "Puzzle.country2City2": "München" +} diff --git a/apps/json/gl.json b/apps/json/gl.json new file mode 100644 index 000000000..c01084de0 --- /dev/null +++ b/apps/json/gl.json @@ -0,0 +1,150 @@ +{ + "@metadata": { + "authors": [ + "Toli\u00f1o" + ] + }, + "Apps.subtitle": "un contorno de programaci\u00f3n visual", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Ver o c\u00f3digo JavaScript xerado.", + "Apps.linkTooltip": "Gardar e crear unha ligaz\u00f3n aos bloques.", + "Apps.runTooltip": "Executar o programa definido polos bloques no espazo de traballo.", + "Apps.runProgram": "Executar o programa", + "Apps.resetProgram": "Restablecer", + "Apps.dialogOk": "Aceptar", + "Apps.dialogCancel": "Cancelar", + "Apps.catLogic": "L\u00f3xica", + "Apps.catLoops": "Bucles", + "Apps.catMath": "Matem\u00e1ticas", + "Apps.catText": "Texto", + "Apps.catLists": "Listas", + "Apps.catColour": "Cor", + "Apps.catVariables": "Variables", + "Apps.catProcedures": "Procedementos", + "Apps.httpRequestError": "Houbo un problema coa solicitude.", + "Apps.linkAlert": "Comparte os teus bloques con esta ligaz\u00f3n:\n\n%1", + "Apps.hashError": "Sent\u00edmolo, \"%1\" non se corresponde con ning\u00fan programa gardado.", + "Apps.xmlError": "Non se puido cargar o ficheiro gardado. Se cadra, foi creado cunha versi\u00f3n diferente de Blockly.", + "Apps.listVariable": "lista", + "Apps.textVariable": "texto", + "Code.badXml": "Erro de an\u00e1lise do XML:\n%1\n\nSelecciona \"Aceptar\" se queres anular os cambios ou \"Cancelar\" para seguir editando o XML.", + "Code.badCode": "Erro do programa:\n%1", + "Code.timeout": "Superouse o n\u00famero m\u00e1ximo de iteraci\u00f3ns durante a execuci\u00f3n.", + "Code.discard": "Queres borrar os %1 bloques?", + "Code.title": "C\u00f3digo", + "Code.blocks": "Bloques", + "Code.trashTooltip": "Descartar todos os bloques.", + "Graph.title": "Calculadora gr\u00e1fica", + "Maze.moveForward": "avanzar", + "Maze.turnLeft": "xirar \u00e1 esquerda", + "Maze.turnRight": "xirar \u00e1 dereita", + "Maze.doCode": "facer", + "Maze.elseCode": "se non", + "Maze.helpIfElse": "Os bloques \"se/se non\" fan unha cousa ou a outra.", + "Maze.pathAhead": "se hai cami\u00f1o diante", + "Maze.pathLeft": "se hai cami\u00f1o \u00e1 esquerda", + "Maze.pathRight": "se hai cami\u00f1o \u00e1 dereita", + "Maze.repeatUntil": "repetir ata", + "Maze.moveForwardTooltip": "Fai que a figura avance un espazo.", + "Maze.turnTooltip": "Fai que a figura xire \u00e1 esquerda ou \u00e1 dereita 90 graos.", + "Maze.ifTooltip": "Se hai un cami\u00f1o na direcci\u00f3n especificada, ent\u00f3n fanse algunhas acci\u00f3ns.", + "Maze.ifelseTooltip": "Se hai un cami\u00f1o na direcci\u00f3n especificada, ent\u00f3n faise o primeiro bloque de acci\u00f3ns. En caso contrario, faise o segundo bloque de acci\u00f3ns.", + "Maze.whileTooltip": "Repetir as acci\u00f3ns do bloque ata chegar \u00e1 meta.", + "Maze.capacity0": "Restan %0 bloques.", + "Maze.capacity1": "Resta %1 bloque.", + "Maze.capacity2": "Restan %2 bloques.", + "Maze.nextLevel": "Parab\u00e9ns! Queres continuar no nivel %1?", + "Maze.finalLevel": "Parab\u00e9ns! Resolviches o nivel final.", + "Maze.maze": "Labirinto", + "Maze.runTooltip": "Fai que a figura realice o que din os bloques.", + "Maze.resetTooltip": "Coloca a figura ao inicio do labirinto.", + "Maze.helpStack": "Apila un par de bloques \"avanzar\" para axudarme a chegar \u00e1 meta.", + "Maze.helpOneTopBlock": "Neste nivel, tes que apilar xuntos todos os bloques no espazo de traballo.", + "Maze.helpRun": "Executa o teu programa para comprobar o que acontece.", + "Maze.helpReset": "O teu programa non resolveu o labirinto. Preme en \"Restablecer\" e int\u00e9ntao de novo.", + "Maze.helpRepeat": "Chega ao final deste cami\u00f1o usando s\u00f3 dous bloques. Utiliza \"repetir\" para executar un bloque m\u00e1is dunha vez.", + "Maze.helpCapacity": "Xa usaches todos os bloques dispo\u00f1ibles para este nivel. Para crear un novo bloque, primeiro debes borrar un dos existentes.", + "Maze.helpRepeatMany": "Podes apilar m\u00e1is dun bloque dentro dos bloques \"repetir\".", + "Maze.helpSkins": "Escolle o teu xogador favorito neste men\u00fa.", + "Maze.helpIf": "Un bloque \"se\" far\u00e1 algo unicamente se a condici\u00f3n \u00e9 certa. Intenta xirar \u00e1 esquerda se hai cami\u00f1o \u00e1 esquerda.", + "Maze.helpMenu": "Preme en %1 no bloque \"se\" para cambiar a s\u00faa condici\u00f3n.", + "Maze.helpWallFollow": "Podes resolver este labirinto m\u00e1is complicado? Intenta seguir a parede da esquerda. S\u00f3 para programadores avanzados!", + "Plane.rows": "Filas: %1", + "Plane.getRows": "filas (%1)", + "Plane.rows1": "Filas de primeira clase: %1", + "Plane.getRows1": "Filas de primeira clase (%1)", + "Plane.rows2": "Filas de segunda clase: %1", + "Plane.getRows2": "Filas de segunda clase (%1)", + "Plane.seats": "Asentos: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "asentos =", + "Plane.plane": "Avi\u00f3n", + "Plane.description1": "Un avi\u00f3n ten un n\u00famero de filas de asentos para os pasaxeiros. Cada fila cont\u00e9n catro asentos.", + "Plane.description2": "Un avi\u00f3n ten dous asentos na cabina (para o piloto e mais o copiloto) e un n\u00famero de filas de asentos para os pasaxeiros. Cada fila cont\u00e9n catro asentos.", + "Plane.description3": "Un avi\u00f3n ten dous asentos na cabina (para o piloto e mais o copiloto) e un n\u00famero de filas de asentos de primeira e segunda clase para os pasaxeiros. Cada fila de primeira clase cont\u00e9n catro asentos. Cada fila de segunda clase cont\u00e9n cinco asentos.", + "Plane.instructions": "Elabora unha f\u00f3rmula (embaixo) que calcule o n\u00famero total de asentos do avi\u00f3n a medida que var\u00ede o n\u00famero de filas (enriba).", + "Puzzle.country1": "Australia", + "Puzzle.country1Language": "ingl\u00e9s", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sidney", + "Puzzle.country1HelpUrl": "http://gl.wikipedia.org/wiki/Australia", + "Puzzle.country2": "Alema\u00f1a", + "Puzzle.country2Language": "alem\u00e1n", + "Puzzle.country2City1": "Berl\u00edn", + "Puzzle.country2City2": "M\u00fanic", + "Puzzle.country2HelpUrl": "http://gl.wikipedia.org/wiki/Alema%C3%B1a", + "Puzzle.country3": "China", + "Puzzle.country3Language": "chin\u00e9s", + "Puzzle.country3City1": "Pequ\u00edn", + "Puzzle.country3City2": "Shanghai", + "Puzzle.country3HelpUrl": "http://gl.wikipedia.org/wiki/Rep%C3%BAblica_Popular_da_China", + "Puzzle.country4": "Brasil", + "Puzzle.country4Language": "portugu\u00e9s", + "Puzzle.country4City1": "R\u00edo de Xaneiro", + "Puzzle.country4City2": "San Paulo", + "Puzzle.country4HelpUrl": "http://gl.wikipedia.org/wiki/Brasil", + "Puzzle.flag": "bandeira:", + "Puzzle.language": "lingua:", + "Puzzle.languageChoose": "escolle...", + "Puzzle.cities": "cidades:", + "Puzzle.error0": "Perfecto!\nOs %1 bloques son correctos.", + "Puzzle.error1": "Por pouco! Un bloque \u00e9 incorrecto.", + "Puzzle.error2": "%1 bloques son incorrectos.", + "Puzzle.tryAgain": "O bloque destacado non \u00e9 correcto.\nSigue intent\u00e1ndoo.", + "Puzzle.title": "Crebacabezas", + "Puzzle.help": "Axuda", + "Puzzle.checkAnswers": "Comprobar as respostas", + "Puzzle.helpText": "A cada pa\u00eds (en verde) faille corresponder a s\u00faa bandeira, sinala a s\u00faa lingua e api\u00f1a as s\u00faas cidades.", + "Turtle.moveTooltip": "Move a tartaruga adiante ou atr\u00e1s a cantidade indicada.", + "Turtle.moveForward": "mover adiante", + "Turtle.moveBackward": "mover atr\u00e1s", + "Turtle.turnTooltip": "Xira a tartaruga \u00e1 esquerda ou \u00e1 dereita o n\u00famero especificado de graos.", + "Turtle.turnRight": "xirar \u00e1 dereita", + "Turtle.turnLeft": "xirar \u00e1 esquerda", + "Turtle.widthTooltip": "Cambia o grosor do bol\u00edgrafo.", + "Turtle.setWidth": "establecer o grosor en", + "Turtle.colourTooltip": "Cambia a cor do bol\u00edgrafo.", + "Turtle.setColour": "establecer a cor en", + "Turtle.penTooltip": "Eleva ou baixa o bol\u00edgrafo, para deixar de debuxar ou empezar a debuxar.", + "Turtle.penUp": "elevar o bol\u00edgrafo", + "Turtle.penDown": "baixar o bol\u00edgrafo", + "Turtle.turtleVisibilityTooltip": "Fai que a tartaruga (o c\u00edrculo e a frecha) sexa visible ou invisible.", + "Turtle.hideTurtle": "agochar a tartaruga", + "Turtle.showTurtle": "mostrar a tartaruga", + "Turtle.printHelpUrl": "http://gl.wikipedia.org/wiki/Impresi%C3%B3n", + "Turtle.printTooltip": "Escribe un texto na direcci\u00f3n da tartaruga e desde a s\u00faa posici\u00f3n.", + "Turtle.print": "escribir", + "Turtle.fontHelpUrl": "http://en.wikipedia.org/wiki/Font", + "Turtle.fontTooltip": "Define o tipo de letra usado polo bloque de escritura.", + "Turtle.font": "tipo de letra", + "Turtle.fontSize": "tama\u00f1o da letra", + "Turtle.fontNormal": "normal", + "Turtle.fontBold": "negra", + "Turtle.fontItalic": "cursiva", + "Turtle.unloadWarning": "Se deixas esta p\u00e1xina perder\u00e1s o teu traballo.", + "Turtle.title": "Gr\u00e1ficas tartaruga", + "Turtle.runTooltip": "Fai que a tartaruga realice o que din os bloques.", + "Turtle.captureTooltip": "Gardar o debuxo.", + "Turtle.imgFilename": "debuxo.png", + "Turtle.catTurtle": "Tartaruga" +} \ No newline at end of file diff --git a/apps/json/gn.json b/apps/json/gn.json new file mode 100644 index 000000000..6b40dcd48 --- /dev/null +++ b/apps/json/gn.json @@ -0,0 +1,70 @@ +{ + "@metadata": { + "authors": [ + "P. S. F. Freitas" + ] + }, + "Apps.subtitle": "pete\u0129 techa myatyr\u00f5 hekoha", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Ehecha JavaScript mba'e apopyre.", + "Apps.linkTooltip": "O\u00f1ongatu ha ombojoaju voreku\u00e9ra.", + "Apps.runTooltip": "Pejapo pe jejapor\u00e3 voreku\u00e9ra ohechauka akue tembiapo rend\u00e1pe.", + "Apps.runProgram": "Pejapo pe Jejapor\u00e3", + "Apps.resetProgram": "\u00d1epyr\u0169 jey", + "Apps.catLogic": "Kuaarape", + "Apps.catLoops": "Tapykuegua", + "Apps.catMath": "Papapykuaa", + "Apps.catText": "Jehaipy", + "Apps.catLists": "Tys\u00fdi", + "Apps.catColour": "Sa'y", + "Apps.catVariables": "\u00d1emoambu\u00e9va", + "Apps.catProcedures": "Aporeko", + "Apps.httpRequestError": "Pete\u0129 tekojepe'y ohechauka.", + "Apps.linkAlert": "Temboja'o nde voreku\u00e9ra ko joaju ndie:\n\n%1", + "Apps.listVariable": "tys\u00fdi", + "Apps.textVariable": "jehaipy", + "Maze.doCode": "pejapo", + "Maze.elseCode": "t\u00e9r\u00e3", + "Plane.placeholder": "?", + "Puzzle.country1Language": "Ingyaterra\u00f1e'\u1ebd", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://gn.wikipedia.org/wiki/Auteralia", + "Puzzle.country2": "Alema\u00f1a", + "Puzzle.country2Language": "Alema\u00f1a\u00f1e'\u1ebd", + "Puzzle.country2City1": "Berlin", + "Puzzle.country2City2": "M\u00fanich", + "Puzzle.country2HelpUrl": "http://gn.wikipedia.org/wiki/Alema\u00f1a", + "Puzzle.country3": "China", + "Puzzle.country3Language": "China\u00f1e'\u1ebd", + "Puzzle.country3City1": "Mbejingo", + "Puzzle.country3City2": "Chang\u00e1i", + "Puzzle.country3HelpUrl": "http://gn.wikipedia.org/wiki/China", + "Puzzle.country4": "Pindorama", + "Puzzle.country4Language": "Poytuga\u00f1e'\u1ebd", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "S\u00e3o Paulo", + "Puzzle.country4HelpUrl": "http://gn.wikipedia.org/wiki/Brasil", + "Puzzle.flag": "poyvi:", + "Puzzle.language": "\u00f1e'\u1ebd:", + "Puzzle.languageChoose": "jeporavo...", + "Puzzle.cities": "t\u00e1va:", + "Puzzle.error0": "Ipor\u00e3ite!\nOpa %1 voreku\u00e9ra o\u0129 por\u00e3.", + "Puzzle.error1": "Haimete por\u00e3! Pete\u0129 vore o\u0129 vai.", + "Puzzle.error2": "%1 voreku\u00e9ra o\u0129 vai.", + "Turtle.penUp": "ejupi haiha", + "Turtle.penDown": "eguejy haiha", + "Turtle.printHelpUrl": "http://en.wikipedia.org/wiki/Printing", + "Turtle.fontHelpUrl": "http://en.wikipedia.org/wiki/Font", + "Turtle.font": "tai ysaja", + "Turtle.fontSize": "tai tuichakue", + "Turtle.fontNormal": "tai tee", + "Turtle.fontBold": "bold", + "Turtle.fontItalic": "italic", + "Turtle.unloadWarning": "Res\u1ebdvo nde reka\u00f1yta opa nde rembiapo.", + "Turtle.title": "Karumbe Ha'angava", + "Turtle.runTooltip": "Ejapouka karumbe vore he'iva.", + "Turtle.captureTooltip": "\u00d1ongatu ta'anga.", + "Turtle.imgFilename": "ta'anga.png", + "Turtle.catTurtle": "Karumbe" +} \ No newline at end of file diff --git a/apps/json/hak.json b/apps/json/hak.json new file mode 100644 index 000000000..2b8834e6f --- /dev/null +++ b/apps/json/hak.json @@ -0,0 +1,35 @@ +{ + "Puzzle.tryAgain": "加光个格仔毋著。\n繼續努力。", + "Puzzle.country3City2": "上海", + "Puzzle.country3HelpUrl": "http://en.wikipedia.org/wiki/China", + "Puzzle.country3Language": "中文", + "Puzzle.checkAnswers": "核對答案", + "Puzzle.language": "語言", + "Apps.dialogOk": "確定", + "Puzzle.title": "迷局", + "Puzzle.country1HelpUrl": "http://en.wikipedia.org/wiki/Australia", + "Puzzle.languageChoose": "選擇", + "Puzzle.country4City2": "聖保羅", + "Puzzle.country4City1": "里約熱内盧", + "Puzzle.country4Language": "葡萄牙語", + "Puzzle.helpText": "每隻國家(青色),選擇其對應个旗幟,語言,與城市。", + "Puzzle.flag": "旗幟", + "Puzzle.country4HelpUrl": "http://en.wikipedia.org/wiki/Brazil", + "Puzzle.error1": "差滴!有 1 格毋著。", + "Puzzle.country3City1": "北京", + "Puzzle.country1City1": "墨爾本", + "Puzzle.country1City2": "悉尼", + "Puzzle.country2Language": "德語", + "Puzzle.country3": "中國", + "Puzzle.country2": "德國", + "Puzzle.country1": "澳大利亞", + "Puzzle.country2HelpUrl": "http://en.wikipedia.org/wiki/Germany", + "Puzzle.error0": "讚!\n%1 格仔全部正確。", + "Puzzle.country4": "巴西", + "Puzzle.error2": "%1 格毋著。", + "Puzzle.help": "幫助", + "Puzzle.country1Language": "英語", + "Puzzle.country2City1": "柏林", + "Puzzle.cities": "城市", + "Puzzle.country2City2": "慕尼黑" +} diff --git a/apps/json/he.json b/apps/json/he.json new file mode 100644 index 000000000..a98e6f70a --- /dev/null +++ b/apps/json/he.json @@ -0,0 +1,77 @@ +{ + "@metadata": { + "authors": [ + "Orsa", + "YaronSh" + ] + }, + "Apps.subtitle": "\u05e1\u05d1\u05d9\u05d1\u05ea \u05ea\u05d9\u05db\u05e0\u05d5\u05ea \u05d7\u05d6\u05d5\u05ea\u05d9", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "\u05d4\u05e6\u05d2\u05ea \u05e7\u05d5\u05d3 \u05d4\u05beJavaScript \u05e9\u05e0\u05d5\u05e6\u05e8.", + "Apps.linkTooltip": "\u05e9\u05de\u05d9\u05e8\u05d4 \u05d5\u05e7\u05d9\u05e9\u05d5\u05e8 \u05dc\u05d1\u05dc\u05d5\u05e7\u05d9\u05dd.", + "Apps.runTooltip": "\u05d4\u05e8\u05e6\u05ea \u05d4\u05ea\u05db\u05e0\u05d9\u05ea \u05e9\u05d4\u05d5\u05d2\u05d3\u05e8\u05d4 \u05e2\u05dc \u05d9\u05d3\u05d9 \u05d4\u05d1\u05dc\u05d5\u05e7\u05d9\u05dd \u05e9\u05d1\u05de\u05e8\u05d7\u05d1 \u05d4\u05e2\u05d1\u05d5\u05d3\u05d4.", + "Apps.runProgram": "\u05d4\u05e8\u05e6\u05ea \u05ea\u05db\u05e0\u05d9\u05ea", + "Apps.resetProgram": "\u05d0\u05d9\u05e4\u05d5\u05e1", + "Apps.dialogOk": "\u05d0\u05d9\u05e9\u05d5\u05e8", + "Apps.dialogCancel": "\u05d1\u05d9\u05d8\u05d5\u05dc", + "Apps.catLogic": "\u05dc\u05d5\u05d2\u05d9\u05e7\u05d4", + "Apps.catLoops": "\u05dc\u05d5\u05dc\u05d0\u05d5\u05ea", + "Apps.catMath": "\u05de\u05ea\u05de\u05d8\u05d9\u05e7\u05d4", + "Apps.catText": "\u05d8\u05e7\u05e1\u05d8", + "Apps.catLists": "\u05e8\u05e9\u05d9\u05de\u05d5\u05ea", + "Apps.catColour": "\u05e6\u05d1\u05e2", + "Apps.catVariables": "\u05de\u05e9\u05ea\u05e0\u05d9\u05dd", + "Apps.catProcedures": "\u05e4\u05e8\u05d5\u05e6\u05d3\u05d5\u05e8\u05d5\u05ea", + "Apps.httpRequestError": "\u05d4\u05d1\u05e7\u05e9\u05d4 \u05e0\u05db\u05e9\u05dc\u05d4.", + "Apps.linkAlert": "\u05e0\u05d9\u05ea\u05df \u05dc\u05e9\u05ea\u05e3 \u05d0\u05ea \u05d4\u05d1\u05dc\u05d5\u05e7\u05d9\u05dd \u05e9\u05dc\u05da \u05d1\u05d0\u05de\u05e6\u05e2\u05d5\u05ea \u05e7\u05d9\u05e9\u05d5\u05e8 \u05d6\u05d4:\n\n%1", + "Apps.listVariable": "\u05e8\u05e9\u05d9\u05de\u05d4", + "Apps.textVariable": "\u05d8\u05e7\u05e1\u05d8", + "Code.badCode": "\u05e9\u05d2\u05d9\u05d0\u05d4 \u05d1\u05ea\u05db\u05e0\u05d9\u05ea: %1", + "Code.discard": "\u05d4\u05d0\u05dd \u05dc\u05de\u05d7\u05d5\u05e7 \u05d0\u05ea \u05db\u05dc %1 \u05d4\u05d1\u05dc\u05d5\u05e7\u05d9\u05dd?", + "Code.title": "\u05e7\u05d5\u05d3", + "Code.trashTooltip": "\u05d4\u05ea\u05e2\u05dc\u05de\u05d5\u05ea \u05de\u05db\u05dc \u05d4\u05d1\u05dc\u05d5\u05e7\u05d9\u05dd.", + "Maze.maze": "\u05de\u05d1\u05d5\u05da", + "Plane.rows": "\u05e9\u05d5\u05e8\u05d5\u05ea: %1", + "Puzzle.country1": "\u05d0\u05d5\u05e1\u05d8\u05e8\u05dc\u05d9\u05d4", + "Puzzle.country1Language": "\u05d0\u05e0\u05d2\u05dc\u05d9\u05ea", + "Puzzle.country1City1": "\u05de\u05dc\u05d1\u05d5\u05e8\u05df", + "Puzzle.country1City2": "\u05e1\u05d9\u05d3\u05e0\u05d9", + "Puzzle.country1HelpUrl": "https://he.wikipedia.org/wiki/\u05d0\u05d5\u05e1\u05d8\u05e8\u05dc\u05d9\u05d4", + "Puzzle.country2": "\u05d2\u05e8\u05de\u05e0\u05d9\u05d4", + "Puzzle.country2Language": "\u05d2\u05e8\u05de\u05e0\u05d9\u05ea", + "Puzzle.country2City1": "\u05d1\u05e8\u05dc\u05d9\u05df", + "Puzzle.country2City2": "\u05de\u05d9\u05e0\u05db\u05df", + "Puzzle.country2HelpUrl": "https://he.wikipedia.org/wiki/\u05d2\u05e8\u05de\u05e0\u05d9\u05d4", + "Puzzle.country3": "\u05e1\u05d9\u05df", + "Puzzle.country3Language": "\u05e1\u05d9\u05e0\u05d9\u05ea", + "Puzzle.country3City1": "\u05d1\u05d9\u05d9\u05d2\u05f3\u05d9\u05e0\u05d2", + "Puzzle.country3City2": "\u05e9\u05d0\u05e0\u05d2\u05d7\u05d0\u05d9", + "Puzzle.country3HelpUrl": "https://he.wikipedia.org/wiki/\u05d4\u05e8\u05e4\u05d5\u05d1\u05dc\u05d9\u05e7\u05d4_\u05d4\u05e2\u05de\u05de\u05d9\u05ea_\u05e9\u05dc_\u05e1\u05d9\u05df", + "Puzzle.country4": "\u05d1\u05e8\u05d6\u05d9\u05dc", + "Puzzle.country4Language": "\u05e4\u05d5\u05e8\u05d8\u05d5\u05d2\u05dc\u05d9\u05ea", + "Puzzle.country4City1": "\u05e8\u05d9\u05d5 \u05d3\u05d4 \u05d6'\u05e0\u05d9\u05d9\u05e8\u05d5", + "Puzzle.country4City2": "\u05e1\u05d0\u05d5 \u05e4\u05d0\u05d5\u05dc\u05d5", + "Puzzle.country4HelpUrl": "https://he.wikipedia.org/wiki/\u05d1\u05e8\u05d6\u05d9\u05dc", + "Puzzle.flag": "\u05d3\u05d2\u05dc:", + "Puzzle.language": "\u05e9\u05e4\u05d4:", + "Puzzle.languageChoose": "\u05d1\u05d7\u05d9\u05e8\u05d4\u2026", + "Puzzle.cities": "\u05e2\u05e8\u05d9\u05dd:", + "Puzzle.error0": "\u05de\u05d5\u05e9\u05dc\u05dd!\n\u05db\u05dc %1 \u05d4\u05d1\u05dc\u05d5\u05e7\u05d9\u05dd \u05e0\u05db\u05d5\u05e0\u05d9\u05dd.", + "Puzzle.error1": "\u05db\u05de\u05e2\u05d8! \u05d1\u05dc\u05d5\u05e7 \u05d0\u05d7\u05d3 \u05dc\u05d0 \u05e0\u05db\u05d5\u05df.", + "Puzzle.error2": "%1 \u05d1\u05dc\u05d5\u05e7\u05d9\u05dd \u05d0\u05d9\u05e0\u05dd \u05e0\u05db\u05d5\u05e0\u05d9\u05dd.", + "Puzzle.tryAgain": "\u05d4\u05d1\u05dc\u05d5\u05e7 \u05d4\u05de\u05d5\u05d3\u05d2\u05e9 \u05d0\u05d9\u05e0\u05d5 \u05e0\u05db\u05d5\u05df.\n\u05e0\u05e1\u05d5 \u05e9\u05d5\u05d1.", + "Puzzle.title": "\u05e4\u05d0\u05d6\u05dc", + "Puzzle.help": "\u05e2\u05d6\u05e8\u05d4", + "Puzzle.checkAnswers": "\u05d1\u05d3\u05d9\u05e7\u05ea \u05d4\u05ea\u05e9\u05d5\u05d1\u05d5\u05ea", + "Puzzle.helpText": "\u05d1\u05e9\u05d1\u05d9\u05dc \u05db\u05dc \u05de\u05d3\u05d9\u05e0\u05d4 (\u05d1\u05d9\u05e8\u05d5\u05e7), \u05e6\u05e8\u05e4\u05d5 \u05d0\u05ea \u05d4\u05d3\u05d2\u05dc, \u05d1\u05d7\u05e8\u05d5 \u05d0\u05ea \u05d4\u05e9\u05e4\u05d4, \u05d5\u05e2\u05e9\u05d5 \u05e2\u05e8\u05d9\u05de\u05d4 \u05e9\u05dc \u05d4\u05e2\u05e8\u05d9\u05dd \u05e9\u05dc\u05d4.", + "Turtle.widthTooltip": "\u05e9\u05d9\u05e0\u05d5\u05d9 \u05d4\u05e8\u05d5\u05d7\u05d1 \u05e9\u05dc \u05d4\u05e2\u05d8.", + "Turtle.hideTurtle": "\u05d4\u05e1\u05ea\u05e8\u05ea \u05d4\u05e6\u05d1", + "Turtle.showTurtle": "\u05d4\u05e6\u05d2\u05ea \u05d4\u05e6\u05d1", + "Turtle.font": "\u05d2\u05d5\u05e4\u05df", + "Turtle.fontSize": "\u05d2\u05d5\u05d3\u05dc \u05d4\u05d2\u05d5\u05e4\u05df", + "Turtle.fontNormal": "\u05e8\u05d2\u05d9\u05dc", + "Turtle.fontBold": "\u05de\u05d5\u05d3\u05d2\u05e9", + "Turtle.fontItalic": "\u05e0\u05d8\u05d5\u05d9", + "Turtle.captureTooltip": "\u05dc\u05e9\u05de\u05d5\u05e8 \u05d0\u05ea \u05d4\u05e6\u05d9\u05d5\u05e8.", + "Turtle.catTurtle": "\u05e6\u05d1" +} \ No newline at end of file diff --git a/apps/json/hu.json b/apps/json/hu.json new file mode 100644 index 000000000..037fa7c14 --- /dev/null +++ b/apps/json/hu.json @@ -0,0 +1,128 @@ +{ + "@metadata": { + "authors": [ + "\uc544\ub77c" + ] + }, + "Apps.subtitle": "vizu\u00e1lis programoz\u00e1si k\u00f6rnyezet", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "A JavaScript forr\u00e1sk\u00f3d megtekint\u00e9se.", + "Apps.runTooltip": "Program futtat\u00e1sa.", + "Apps.runProgram": "Program futtat\u00e1sa", + "Apps.resetProgram": "Alaphelyzet", + "Apps.dialogOk": "Elolvastam", + "Apps.catLogic": "Logikai m\u0171veletek", + "Apps.catLoops": "Ciklusok", + "Apps.catMath": "Matematikai m\u0171veletek", + "Apps.catText": "Sztring m\u0171veletek", + "Apps.catLists": "Listakezel\u00e9s", + "Apps.catColour": "Sz\u00ednek", + "Apps.catVariables": "V\u00e1ltoz\u00f3k", + "Apps.catProcedures": "Elj\u00e1r\u00e1sok", + "Apps.httpRequestError": "A k\u00e9r\u00e9ssel kapcsolatban probl\u00e9ma mer\u00fclt fel.", + "Apps.linkAlert": "Ezzel a hivatkoz\u00e1ssal tudod megosztani a programodat:\n\n%1", + "Apps.hashError": "Eln\u00e9z\u00e9st, a '%1' hivatkoz\u00e1snem tartozik egyetlen programhoz sem.", + "Apps.xmlError": "A programodat nem lehet bet\u00f6lteni. Elk\u00e9pzelhet\u0151, hogy a Blockly egy m\u00e1sik verzi\u00f3j\u00e1ban k\u00e9sz\u00fclt?", + "Apps.listVariable": "list", + "Code.badXml": "Hiba az XML feldolgoz\u00e1sakor:\n%1\n\nV\u00e1ltoz\u00e1sok elvet\u00e9se?", + "Code.badCode": "Program hiba:\n%1", + "Code.timeout": "A program el\u00e9rte a maxim\u00e1lis v\u00e9grehajt\u00e1si id\u0151t.", + "Code.discard": "Az \u00f6sszes %1 blokk t\u00f6rl\u00e9se?", + "Code.title": "K\u00f3dszerkeszt\u0151", + "Code.blocks": "Blokkok", + "Code.trashTooltip": "\u00d6sszes blokk t\u00f6rl\u00e9se.", + "Graph.title": "F\u00fcggv\u00e9nyrajzol\u00f3", + "Maze.moveForward": "Menj el\u0151re", + "Maze.turnLeft": "Fordulj balra", + "Maze.turnRight": "Fordulj jobbra", + "Maze.doCode": "akkor", + "Maze.elseCode": "egy\u00e9bk\u00e9nt", + "Maze.helpIfElse": "A Ha-egy\u00e9bk\u00e9nt felt\u00e9tel eset\u00e9n vagy az egyik, vagy a m\u00e1sik utas\u00edt\u00e1s-csoport ker\u00fcl v\u00e9grehajt\u00e1sra.", + "Maze.pathAhead": "Ha szabad az \u00fat el\u0151tted", + "Maze.pathLeft": "Ha szabad az \u00fat balra", + "Maze.pathRight": "Ha szabad az \u00fat jobbra", + "Maze.repeatUntil": "Ism\u00e9teld a", + "Maze.moveForwardTooltip": "Pegman el\u0151re l\u00e9p egy mez\u0151t.", + "Maze.turnTooltip": "Pegman 90 fokot fordul balra, vagy jobbra.", + "Maze.ifTooltip": "Ha szabad az \u00fat a megadott ir\u00e1nyban, akkor v\u00e9grehajtja az utas\u00edt\u00e1sokat.", + "Maze.ifelseTooltip": "Ha szabad az \u00fat a megadott ir\u00e1nyban, akkor v\u00e9grehajtja az els\u0151 blokkban megadott utas\u00edt\u00e1sokat. Egy\u00e9bk\u00e9nt a m\u00e1sodik blokkban szerepl\u0151 utas\u00edt\u00e1sokat hajtja v\u00e9gre.", + "Maze.whileTooltip": "A be\u00e1gyazott utas\u00edt\u00e1sokat hajtja v\u00e9gre a c\u00e9l el\u00e9r\u00e9s\u00e9ig.", + "Maze.capacity0": "Nem haszn\u00e1lhatsz fel t\u00f6bb blokkot.", + "Maze.capacity1": "M\u00e9g %1 blokkot haszn\u00e1lhatsz fel.", + "Maze.capacity2": "M\u00e9g %2 blokkot haszn\u00e1lhatsz fel.", + "Maze.nextLevel": "Gratul\u00e1lok! K\u00e9sz vagy megoldani a(z) %1. szintet?", + "Maze.finalLevel": "Gratul\u00e1lok! Sikeresen megoldottad az utols\u00f3 szintet.", + "Maze.maze": "Labirintus", + "Maze.helpStack": "Seg\u00edts eljutatni Pegmant a c\u00e9lig, kapcsolj \u00f6ssze n\u00e9h\u00e1ny 'Menj el\u0151re' blokkot!", + "Maze.helpOneTopBlock": "Ezen a szinten \u00f6ssze kell kapcsolnod minden blokkot a munkater\u00fcleten.", + "Maze.helpRepeat": "A sz\u00e1m\u00edt\u00f3g\u00e9peknek v\u00e9ges a mem\u00f3ri\u00e1juk. Juttasd el Pegmant a c\u00e9lig mind\u00f6ssze 2 blokk felhaszn\u00e1l\u00e1s\u00e1val. Haszn\u00e1ld az 'Ism\u00e9teld a c\u00e9lba\u00e9r\u00e9sig' blokkot egy m\u00e1sik blokk ism\u00e9telt v\u00e9grehajt\u00e1s\u00e1hoz.", + "Maze.helpRepeatMany": "Juttasd el Pegmant a c\u00e9lig mind\u00f6ssze 5 blokk felhaszn\u00e1l\u00e1s\u00e1val.", + "Maze.helpIf": "Egy 'Ha' eset\u00e9n az utas\u00edt\u00e1sok csak akkor ker\u00fclnek v\u00e9grehajt\u00e1sra, ha a felt\u00e9tel igaz. Pr\u00f3b\u00e1ld Pegmant balra ford\u00edtani, ha van \u00fat balra.", + "Maze.helpWallFollow": "V\u00e9gig tudod vezetni Pegmant ezen a bonyolult labirintuson? Pr\u00f3b\u00e1ld a bal oldali falat k\u00f6vetni. Halad\u00f3 programoz\u00f3knak!", + "Plane.rows": "Sorok sz\u00e1ma: %1", + "Plane.getRows": "Sorok sz\u00e1ma (%1)", + "Plane.rows1": "1. oszt\u00e1ly: %1 sor", + "Plane.getRows1": "1. oszt\u00e1ly sorai (%1)", + "Plane.rows2": "2. oszt\u00e1ly: %1 sor", + "Plane.getRows2": "2. oszt\u00e1ly sorai (%1)", + "Plane.seats": "\u00dcl\u00e9sek sz\u00e1ma \u00f6sszesen: %1", + "Plane.setSeats": "\u00dcl\u00e9sek sz\u00e1ma =", + "Plane.plane": "Rep\u00fcl\u0151g\u00e9p", + "Plane.description1": "Egy rep\u00fcl\u0151g\u00e9pnek az utasok t\u00f6bb sorban \u00fclnek az utast\u00e9rben. Az utast\u00e9r minden sor\u00e1ban n\u00e9gy sz\u00e9k van.", + "Plane.description2": "Egy rep\u00fcl\u0151g\u00e9pnek 2 \u00fcl\u00e9se van a pil\u00f3taf\u00fclk\u00e9ben (a pli\u00f3t\u00e1nak \u00e9s a m\u00e1sodpil\u00f3t\u00e1nak), az utasok t\u00f6bb sorban \u00fclnek az utast\u00e9rben. Az utast\u00e9r minden sor\u00e1ban n\u00e9gy sz\u00e9k van.", + "Plane.description3": "Egy rep\u00fcl\u0151g\u00e9pnek 2 \u00fcl\u00e9se van a pil\u00f3taf\u00fclk\u00e9ben (a pli\u00f3t\u00e1nak \u00e9s a m\u00e1sodpil\u00f3t\u00e1nak), az utasok 1. \u00e9s 2. oszt\u00e1lyon utazhatnak. Az 1. oszt\u00e1lyon n\u00e9gy sz\u00e9k van egy sorban. A 2. oszt\u00e1lyon \u00f6t sz\u00e9k van egy sorban.", + "Plane.instructions": "K\u00e9sz\u00edtsd el a k\u00e9pletet (lent) amivel kisz\u00e1molhat\u00f3, hogy h\u00e1ny \u00fcl\u00e9s van \u00f6sszesen a rep\u00fcl\u0151g\u00e9pen annak f\u00fcggv\u00e9ny\u00e9ben, ahogy (fent) \u00e1ll\u00edtod a sorok sz\u00e1m\u00e1t.", + "Puzzle.country1": "Ausztr\u00e1lia", + "Puzzle.country1Language": "Angol", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://hu.wikipedia.org/wiki/Ausztr\u00e1lia", + "Puzzle.country2": "N\u00e9metorsz\u00e1g", + "Puzzle.country2Language": "N\u00e9met", + "Puzzle.country2City1": "Berlin", + "Puzzle.country2City2": "M\u00fcnchen", + "Puzzle.country2HelpUrl": "http://hu.wikipedia.org/wiki/N\u00e9metorsz\u00e1g", + "Puzzle.country3": "K\u00edna", + "Puzzle.country3Language": "K\u00ednai", + "Puzzle.country3City1": "Peking", + "Puzzle.country3City2": "Sanghaj", + "Puzzle.country3HelpUrl": "http://hu.wikipedia.org/wiki/K\u00edna", + "Puzzle.country4": "Braz\u00edlia", + "Puzzle.country4Language": "Portug\u00e1l", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "S\u00e3o Paulo", + "Puzzle.country4HelpUrl": "http://hu.wikipedia.org/wiki/Braz\u00edlia", + "Puzzle.flag": "z\u00e1szl\u00f3", + "Puzzle.language": "nyelv:", + "Puzzle.languageChoose": "v\u00e1lassz\u2026", + "Puzzle.cities": "v\u00e1rosok:", + "Puzzle.error0": "T\u00f6k\u00e9letes!\nMind a %1 blokk a hely\u00e9n van.", + "Puzzle.error1": "Majdnem siker\u00fclt! 1 blokk rossz helyre ker\u00fclt.", + "Puzzle.error2": "\u03251 blokk rossz helyre ker\u00fclt.", + "Puzzle.tryAgain": "A kiemelt blokk nincs a hely\u00e9n.\nPr\u00f3b\u00e1ld \u00fajra", + "Puzzle.title": "Kirak\u00f3s", + "Puzzle.help": "Sug\u00f3", + "Puzzle.checkAnswers": "V\u00e1laszok ellen\u0151rz\u00e9se", + "Puzzle.helpText": "Minden orsz\u00e1got jelk\u00e9pez\u0151 blokkhoz (z\u00f6ld), kapcsold hozz\u00e1 a z\u00e1szl\u00f3j\u00e1t, v\u00e1laszd ki a nyelvet amit besz\u00e9lnek \u00e9s h\u00fazg\u00e1ld bele a v\u00e1rosait.", + "Turtle.moveTooltip": "A tekn\u0151c\u00f6t mozgatja el\u0151re, vagy h\u00e1tra a pixelben megadott \u00e9rt\u00e9kkel.", + "Turtle.moveForward": "Menj el\u0151re (pixel)", + "Turtle.moveBackward": "Menj vissza (pixel)", + "Turtle.turnTooltip": "A tekn\u0151c\u00f6t jobbra, vagy balra ford\u00edtja a fokban megadott \u00e9rt\u00e9kkel.", + "Turtle.turnRight": "Fordulj jobbra (fok)", + "Turtle.turnLeft": "Fordulj balra (fok)", + "Turtle.widthTooltip": "Vonalvastags\u00e1g be\u00e1ll\u00edt\u00e1sa.", + "Turtle.setWidth": "Vonalvastags\u00e1g", + "Turtle.colourTooltip": "A rajzol\u00e1s sz\u00edn\u00e9nek v\u00e1ltoztat\u00e1sa.", + "Turtle.setColour": "Rajzol\u00e1s sz\u00edne", + "Turtle.penTooltip": "Toll felemel\u00e9se letev\u00e9se, att\u00f3l f\u00fcgg\u0151en, hogy elkezdj\u00fck vagy befejezz\u00fck a rajzol\u00e1st.", + "Turtle.penUp": "Tollat fel", + "Turtle.penDown": "Tollat le", + "Turtle.turtleVisibilityTooltip": "a tekn\u0151c (k\u00f6r \u00e9s ny\u00edl) l\u00e1that\u00f3v\u00e1 t\u00e9tele, vagy elrejt\u00e9se.", + "Turtle.hideTurtle": "Tekn\u0151c elrejt\u00e9se", + "Turtle.showTurtle": "Tekn\u0151c felfed\u00e9se", + "Turtle.printHelpUrl": "http://en.wikipedia.org/wiki/Printing", + "Turtle.fontHelpUrl": "http://en.wikipedia.org/wiki/Font", + "Turtle.unloadWarning": "Az oldal elhagy\u00e1sa a munk\u00e1d elveszt\u00e9s\u00e9t eredm\u00e9nyezi.", + "Turtle.title": "Tekn\u0151c Grafika", + "Turtle.catTurtle": "Tekn\u0151c" +} \ No newline at end of file diff --git a/apps/json/ia.json b/apps/json/ia.json new file mode 100644 index 000000000..24a2bcd41 --- /dev/null +++ b/apps/json/ia.json @@ -0,0 +1,150 @@ +{ + "@metadata": { + "authors": [ + "McDutchie" + ] + }, + "Apps.subtitle": "un ambiente de programmation visual", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Vider le codice JavaScript generate.", + "Apps.linkTooltip": "Salveguardar e ligar a blocos.", + "Apps.runTooltip": "Executar le programma definite per le blocos in le spatio de travalio.", + "Apps.runProgram": "Executar programma", + "Apps.resetProgram": "Reinitialisar", + "Apps.dialogOk": "OK", + "Apps.dialogCancel": "Cancellar", + "Apps.catLogic": "Logica", + "Apps.catLoops": "Buclas", + "Apps.catMath": "Mathematica", + "Apps.catText": "Texto", + "Apps.catLists": "Listas", + "Apps.catColour": "Color", + "Apps.catVariables": "Variabiles", + "Apps.catProcedures": "Proceduras", + "Apps.httpRequestError": "Il habeva un problema con le requesta.", + "Apps.linkAlert": "Divide tu blocos con iste ligamine:\n\n%1", + "Apps.hashError": "Infelicemente, '%1' non corresponde a alcun programma salveguardate.", + "Apps.xmlError": "Impossibile cargar le file salveguardate. Pote esser que illo ha essite create con un altere version de Blockly?", + "Apps.listVariable": "lista", + "Apps.textVariable": "texto", + "Code.badXml": "Error de analyse del XML:\n%1\n\nSelige 'OK' pro abandonar le modificationes o 'Cancellar' pro continuar a modificar le codice XML.", + "Code.badCode": "Error del programma:\n%1", + "Code.timeout": "Le numero de iterationes executate ha excedite le maximo.", + "Code.discard": "Deler tote le %1 blocos?", + "Code.title": "Codice", + "Code.blocks": "Blocos", + "Code.trashTooltip": "Abandonar tote le blocos.", + "Graph.title": "Calculator graphic", + "Maze.moveForward": "avantiar", + "Maze.turnLeft": "girar a sinistra", + "Maze.turnRight": "girar a dextra", + "Maze.doCode": "face", + "Maze.elseCode": "si non", + "Maze.helpIfElse": "Un bloco \"si/si non\" face o le prime cosa o le altere.", + "Maze.pathAhead": "si cammino avante", + "Maze.pathLeft": "si cammino a sinistra", + "Maze.pathRight": "si cammino a dextra", + "Maze.repeatUntil": "repeter usque a", + "Maze.moveForwardTooltip": "Face le jocator avantiar un spatio.", + "Maze.turnTooltip": "Gira le jocator a sinistra o a dextra de 90 grados.", + "Maze.ifTooltip": "Si existe un cammino in le direction specificate, alora face certe actiones.", + "Maze.ifelseTooltip": "Si existe un cammino in le direction specificate, alora face le prime bloco de actiones. Si non, face le secunde bloco de actiones.", + "Maze.whileTooltip": "Repeter le actiones continite usque al puncto de fin.", + "Maze.capacity0": "Te resta %0 blocos.", + "Maze.capacity1": "Te resta %1 bloco.", + "Maze.capacity2": "Te resta %2 blocos.", + "Maze.nextLevel": "Felicitationes! Es tu preste pro le nivello %1?", + "Maze.finalLevel": "Felicitationes! Tu ha resolvite le nivello final.", + "Maze.maze": "Labyrintho", + "Maze.runTooltip": "Face le jocator facer lo que le blocos dice.", + "Maze.resetTooltip": "Remitter le jocator al initio del labyrintho.", + "Maze.helpStack": "Impila un par de blocos 'avantiar' pro adjutar me a attinger le fin.", + "Maze.helpOneTopBlock": "In iste nivello, tu debe impilar tote le blocos in le spatio de travalio blanc.", + "Maze.helpRun": "Executa tu programma pro vider lo que eveni.", + "Maze.helpReset": "Tu programma non ha solvite le labyrintho. Preme 'Reinitialisar' e proba de novo.", + "Maze.helpRepeat": "Le memoria de computatores es limitate. Attinge le fin de iste cammino con solmente duo blocos. Usa 'repeter' pro executar un bloco plus de un vice.", + "Maze.helpCapacity": "Tu ha usate tote le blocos pro iste nivello. Pro crear un nove bloco, tu debe primo deler un bloco existente.", + "Maze.helpRepeatMany": "Tu pote mitter plus de un bloco intra un bloco 'repeter'.", + "Maze.helpSkins": "Selige tu jocator favorite de iste menu.", + "Maze.helpIf": "Un bloco 'si' face qualcosa solmente si le condition es satisfacite. Essaya girar a sinistra si existe un cammino a sinistra.", + "Maze.helpMenu": "Clicca sur %1 in le bloco 'si' pro cambiar su condition.", + "Maze.helpWallFollow": "Pote tu solver iste labyrintho complexe? Essaya a sequer le muro sinistre. Programmatores experte solmente!", + "Plane.rows": "Filas: %1", + "Plane.getRows": "filas (%1)", + "Plane.rows1": "Filas de prime classe: %1", + "Plane.getRows1": "filas de prime classe (%1)", + "Plane.rows2": "Filas de secunde classe: %1", + "Plane.getRows2": "filas de secunde classe (%1)", + "Plane.seats": "Sedes: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "sedes =", + "Plane.plane": "Avion", + "Plane.description1": "Un avion ha un numero de filas de sedes pro passageros. Cata fila contine quatro sedes.", + "Plane.description2": "Un avion ha duo sedes in le cabina (pro le pilota e le copilota) e un numero de filas de sedes pro passageros. Cata fila contine quatro sedes.", + "Plane.description3": "Un avion ha duo sedes in le cabina (pro le pilota e le copilota) e un numero de filas de sedes pro passageros del prime classe e del secunde classes. Cata fila del prime classe contine quatro sedes. Cata fila del secunde classe contine cinque sedes.", + "Plane.instructions": "Construe un formula (ci infra) que calcula le numero total de sedes in le avion quando le numero de filas es cambiate (ci supra).", + "Puzzle.country1": "Australia", + "Puzzle.country1Language": "Anglese", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://ia.wikipedia.org/wiki/Australia", + "Puzzle.country2": "Germania", + "Puzzle.country2Language": "Germano", + "Puzzle.country2City1": "Berlin", + "Puzzle.country2City2": "Munich", + "Puzzle.country2HelpUrl": "http://ia.wikipedia.org/wiki/Germania", + "Puzzle.country3": "China", + "Puzzle.country3Language": "Chinese", + "Puzzle.country3City1": "Peking", + "Puzzle.country3City2": "Shanghai", + "Puzzle.country3HelpUrl": "http://ia.wikipedia.org/wiki/China", + "Puzzle.country4": "Brasil", + "Puzzle.country4Language": "Portugese", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "S\u00e3o Paulo", + "Puzzle.country4HelpUrl": "http://ia.wikipedia.org/wiki/Brasil", + "Puzzle.flag": "bandiera:", + "Puzzle.language": "lingua:", + "Puzzle.languageChoose": "selige...", + "Puzzle.cities": "citates:", + "Puzzle.error0": "Perfecte!\nTote le %1 blocos es correcte.", + "Puzzle.error1": "Quasi! Un bloco es incorrecte.", + "Puzzle.error2": "%1 blocos es incorrecte.", + "Puzzle.tryAgain": "Le bloco marcate non es correcte.\nFace un altere essayo.", + "Puzzle.title": "Puzzle", + "Puzzle.help": "Adjuta", + "Puzzle.checkAnswers": "Verificar responsas", + "Puzzle.helpText": "Pro cata pais (in verde), attacha su bandiera, selige su lingua, e face un pila de su citates.", + "Turtle.moveTooltip": "Displacia le tortuca in avante o a retro in le quantitate specificate.", + "Turtle.moveForward": "avantiar", + "Turtle.moveBackward": "recular", + "Turtle.turnTooltip": "Gira le tortuca a sinistra o a dextra del numero de grados specificate.", + "Turtle.turnRight": "girar a dextra de", + "Turtle.turnLeft": "girar a sinistra de", + "Turtle.widthTooltip": "Cambia le latitude del stilo.", + "Turtle.setWidth": "mitter latitude a", + "Turtle.colourTooltip": "Cambia le color del stilo.", + "Turtle.setColour": "mitter color a", + "Turtle.penTooltip": "Leva o pone le stilo pro cessar o comenciar a designar.", + "Turtle.penUp": "levar stilo", + "Turtle.penDown": "poner stilo", + "Turtle.turtleVisibilityTooltip": "Rende le tortuca (circulo e flecha) visibile o invisibile.", + "Turtle.hideTurtle": "celar tortuca", + "Turtle.showTurtle": "revelar tortuca", + "Turtle.printHelpUrl": "http://ia.wikipedia.org/wiki/Impression", + "Turtle.printTooltip": "Designa texto in le direction del tortuca in su loco.", + "Turtle.print": "scriber", + "Turtle.fontHelpUrl": "http://ia.wikipedia.org/wiki/Typo_de_litteras", + "Turtle.fontTooltip": "Selige le typo de litteras usate per le bloco 'scriber'.", + "Turtle.font": "typo de litteras", + "Turtle.fontSize": "dimension de litteras", + "Turtle.fontNormal": "normal", + "Turtle.fontBold": "grasse", + "Turtle.fontItalic": "italic", + "Turtle.unloadWarning": "Si tu quita iste pagina, tu perdera le travalio que tu ha facite.", + "Turtle.title": "Graphicos de tortuca", + "Turtle.runTooltip": "Face le tortuca facer lo que le blocos dice.", + "Turtle.captureTooltip": "Salveguardar le designo.", + "Turtle.imgFilename": "designo.png", + "Turtle.catTurtle": "Tortuca" +} \ No newline at end of file diff --git a/apps/json/it.json b/apps/json/it.json new file mode 100644 index 000000000..1b3372b83 --- /dev/null +++ b/apps/json/it.json @@ -0,0 +1,152 @@ +{ + "@metadata": { + "authors": [ + "Beta16", + "Isiond", + "Nerimic" + ] + }, + "Apps.subtitle": "un ambiente di programmazione grafico", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Vedi il codice JavaScript generato.", + "Apps.linkTooltip": "Salva e collega ai blocchi.", + "Apps.runTooltip": "Esegui il programma definito dai blocchi nell'area di lavoro.", + "Apps.runProgram": "Esegui programma", + "Apps.resetProgram": "Reimposta", + "Apps.dialogOk": "OK", + "Apps.dialogCancel": "Annulla", + "Apps.catLogic": "Logica", + "Apps.catLoops": "Cicli", + "Apps.catMath": "Matematica", + "Apps.catText": "Testo", + "Apps.catLists": "Elenchi", + "Apps.catColour": "Colore", + "Apps.catVariables": "Variabili", + "Apps.catProcedures": "Procedure", + "Apps.httpRequestError": "La richiesta non \u00e8 stata soddisfatta.", + "Apps.linkAlert": "Condividi i tuoi blocchi con questo collegamento:\n\n%1", + "Apps.hashError": "Mi spiace, '%1' non corrisponde ad alcun programma salvato.", + "Apps.xmlError": "Non \u00e8 stato possibile caricare il documento. Forse \u00e8 stato creato con una versione diversa di Blockly?", + "Apps.listVariable": "elenco", + "Apps.textVariable": "testo", + "Code.badXml": "Errore durante l'analisi XML:\n%1\n\nSeleziona 'OK' per abbandonare le modifiche o 'Annulla' per continuare a modificare l'XML.", + "Code.badCode": "Errore programma:\n%1", + "Code.timeout": "\u00c8 stato superato il numero massimo consentito di interazioni eseguite.", + "Code.discard": "Cancellare tutti i %1 blocchi?", + "Code.title": "Codice", + "Code.blocks": "Blocchi", + "Code.trashTooltip": "Elimina tutti i blocchi.", + "Graph.title": "Calcolatrice grafica", + "Maze.moveForward": "sposta in avanti", + "Maze.turnLeft": "svolta a sinistra", + "Maze.turnRight": "svolta a destra", + "Maze.doCode": "fa'", + "Maze.elseCode": "altrimenti", + "Maze.helpIfElse": "Le istruzioni if-else cercheranno di compiere la prima azione o la seconda.", + "Maze.pathAhead": "se c'\u00e8 strada avanti", + "Maze.pathLeft": "se c'\u00e8 strada a sinistra", + "Maze.pathRight": "se c'\u00e8 strada a destra", + "Maze.repeatUntil": "ripeti sino alla", + "Maze.moveForwardTooltip": "Avanza la pedina di una casella.", + "Maze.turnTooltip": "Gira la pedina verso destra o sinistra di 90 gradi.", + "Maze.ifTooltip": "Se c'\u00e8 strada nella direzione indicata, allora fa' qualcosa.", + "Maze.ifelseTooltip": "Se c'\u00e8 strada nella direzione indicata, Allora esegui la prima serie di azioni. Altrimenti esegui la seconda serie di azioni.", + "Maze.whileTooltip": "Ripeti l'azione scelta sino al punto di arrivo.", + "Maze.capacity0": "Puoi usare altri %0 blocchi.", + "Maze.capacity1": "Puoi usare %1 altro blocco.", + "Maze.capacity2": "Puoi usare altri %2 blocchi.", + "Maze.nextLevel": "Gaudio! Sei pronto a passare al livello %1?", + "Maze.finalLevel": "Tripudio! Hai risolto l'ultimo livello.", + "Maze.maze": "Labirinto", + "Maze.runTooltip": "Fa fare al giocatore ci\u00f2 che dicono i blocchi", + "Maze.resetTooltip": "Riposiziona il giocatore all'inizio del labirinto.", + "Maze.helpStack": "Impila un paio di blocchi 'avanza diritto' per aiutarmi a raggiungere l'arrivo.", + "Maze.helpOneTopBlock": "In questo livello dovrai impilare tutti i blocchi nella zona bianca.", + "Maze.helpRun": "Esegui il programma per vedere cosa succede.", + "Maze.helpReset": "Il programma non ha risolto il labirinto. Premi 'Reset' e prova di nuovo.", + "Maze.helpRepeat": "I computer hanno una memoria limitata. Raggiungi l'arrivo usando solo due blocchi. Scegli 'ripeti' per eseguire un blocco pi\u00f9 di una volta.", + "Maze.helpCapacity": "Hai utilizzato tutti i blocchi per questo livello. Per creare un nuovo blocco, \u00e8 necessario prima eliminare un blocco esistente.", + "Maze.helpRepeatMany": "\u00c8 possibile inserire pi\u00f9 di un blocco all'interno di un blocco 'Ripeti'.", + "Maze.helpSkins": "Scegli il tuo giocatore preferito da questo menu.", + "Maze.helpIf": "Con 'se' l'azione verr\u00e0 eseguita solo se la condizione \u00e8 soddisfatta. Prova a girare a sinistra se c'\u00e8 una strada a sinistra.", + "Maze.helpMenu": "Fai clic su %1 nel blocco 'se' per cambiare la sua condizione.", + "Maze.helpWallFollow": "Sai risolvere questo labirinto intricato? Prova a seguire il muro di sinistra. Solo per programmatori avanzati!", + "Plane.rows": "File: %1", + "Plane.getRows": "file (%1)", + "Plane.rows1": "File 1\u00aa classe: %1", + "Plane.getRows1": "file 1\u00aa classe (%1)", + "Plane.rows2": "File 2\u00aa classe: %1", + "Plane.getRows2": "File 2\u00aa classe (%1)", + "Plane.seats": "Sedili: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "sedili =", + "Plane.plane": "Aereo", + "Plane.description1": "Un aeroplano ha un numero di file contenenti i posti a sedere dei passeggeri. Ogni fila, contiene quattro posti a sedere.", + "Plane.description2": "Un aeroplano ha due posti a sedere nella cabina di pilotaggio (per il pilota e co-pilota), e un numero di file con i posti a sedere dei passeggeri. Ogni fila contiene quattro posti.", + "Plane.description3": "Un aereo ha due posti nella cabina di pilotaggio (per il pilota e il co-pilota), e un numero di file in prima e seconda classe, con i posti a sedere dei passeggeri. Ogni fila della prima classe contiene quattro posti. Quelle invece della seconda classe, ne contengono cinque.", + "Plane.instructions": "Costruisci una formula (sotto) che calcola il numero totale di posti a sedere su un aeroplano, cos\u00ec come cambiano le file di posti (sopra).", + "Puzzle.country1": "Australia", + "Puzzle.country1Language": "Inglese", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://it.wikipedia.org/wiki/Australia", + "Puzzle.country2": "Germania", + "Puzzle.country2Language": "Tedesco", + "Puzzle.country2City1": "Berlino", + "Puzzle.country2City2": "Monaco di Baviera", + "Puzzle.country2HelpUrl": "http://it.wikipedia.org/wiki/Germania", + "Puzzle.country3": "Cina", + "Puzzle.country3Language": "Cinese", + "Puzzle.country3City1": "Pechino", + "Puzzle.country3City2": "Shanghai", + "Puzzle.country3HelpUrl": "http://it.wikipedia.org/wiki/Cina", + "Puzzle.country4": "Brasile", + "Puzzle.country4Language": "Portoghese", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "San Paolo", + "Puzzle.country4HelpUrl": "http://it.wikipedia.org/wiki/Brasile", + "Puzzle.flag": "bandiera:", + "Puzzle.language": "lingua:", + "Puzzle.languageChoose": "scegli...", + "Puzzle.cities": "citt\u00e0:", + "Puzzle.error0": "Perfetto!\nTutti i %1 blocchi sono corretti.", + "Puzzle.error1": "Quasi! Un blocco non \u00e8 corretto.", + "Puzzle.error2": "%1 blocchi non sono corretti.", + "Puzzle.tryAgain": "Il blocco evidenziato non \u00e8 corretto.\nProva ancora.", + "Puzzle.title": "Puzzle", + "Puzzle.help": "Aiuto", + "Puzzle.checkAnswers": "Controlla le risposte", + "Puzzle.helpText": "Per ogni paese (verde), attaccaci la sua bandiera, scegli la lingua e fai la lista della sua citt\u00e0.", + "Turtle.moveTooltip": "Muove avanti e indietro la tartaruga secondo quanto specificato.", + "Turtle.moveForward": "sposta in avanti di", + "Turtle.moveBackward": "sposta indietro di", + "Turtle.turnTooltip": "Gira la tartaruga a destra o a sinistra, secondo l'angolazione suggerita.", + "Turtle.turnRight": "gira a destra di", + "Turtle.turnLeft": "gira a sinistra di", + "Turtle.widthTooltip": "Cambia la larghezza della penna.", + "Turtle.setWidth": "imposta la larghezza a", + "Turtle.colourTooltip": "Cambia il colore della penna.", + "Turtle.setColour": "imposta colore a", + "Turtle.penTooltip": "Alza o abbassa la penna, per iniziare a disegnare o fermarti.", + "Turtle.penUp": "penna s\u00f9", + "Turtle.penDown": "penna gi\u00f9", + "Turtle.turtleVisibilityTooltip": "Rende la tartaruga (cerchio con la freccia), visibile o invisibile.", + "Turtle.hideTurtle": "nascondi tartaruga", + "Turtle.showTurtle": "mostra tartaruga", + "Turtle.printHelpUrl": "http://it.wikipedia.org/wiki/Stampa", + "Turtle.printTooltip": "disegna il testo nella direzione e alla posizione della tartaruga.", + "Turtle.print": "stampa", + "Turtle.fontHelpUrl": "http://it.wikipedia.org/wiki/Tipo_di_carattere", + "Turtle.fontTooltip": "Imposta il tipo di carattere utilizzato dal blocco di stampa.", + "Turtle.font": "tipo di carattere", + "Turtle.fontSize": "dimensione carattere", + "Turtle.fontNormal": "normale", + "Turtle.fontBold": "grassetto", + "Turtle.fontItalic": "corsivo", + "Turtle.unloadWarning": "Lasciando questa pagina perderai il lavoro svolto.", + "Turtle.title": "Tartaruga grafica", + "Turtle.runTooltip": "Fai fare alla tartaruga ci\u00f2 che il blocco dice.", + "Turtle.captureTooltip": "Salva il disegno.", + "Turtle.imgFilename": "disegno.png", + "Turtle.catTurtle": "Tartaruga" +} \ No newline at end of file diff --git a/apps/json/ja.json b/apps/json/ja.json new file mode 100644 index 000000000..75472e6db --- /dev/null +++ b/apps/json/ja.json @@ -0,0 +1,138 @@ +{ + "@metadata": { + "authors": [ + "Shirayuki" + ] + }, + "Apps.blocklyMessage": "\u30d6\u30ed\u30c3\u30af\u30ea\u30fc", + "Apps.codeTooltip": "\u751f\u6210\u3055\u308c\u305f JavaScript \u30b3\u30fc\u30c9\u3092\u8868\u793a\u3057\u307e\u3059\u3002", + "Apps.linkTooltip": "\u30d6\u30ed\u30c3\u30af\u306e\u72b6\u614b\u3092\u4fdd\u5b58\u3057\u3066\u30ea\u30f3\u30af\u3092\u53d6\u5f97\u3057\u307e\u3059\u3002", + "Apps.runTooltip": "\u30d6\u30ed\u30c3\u30af\u3067\u4f5c\u6210\u3057\u305f\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u5b9f\u884c\u3057\u307e\u3059\u3002", + "Apps.runProgram": "\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u5b9f\u884c", + "Apps.resetProgram": "\u30ea\u30bb\u30c3\u30c8", + "Apps.dialogOk": "OK", + "Apps.dialogCancel": "\u30ad\u30e3\u30f3\u30bb\u30eb", + "Apps.catLogic": "\u8ad6\u7406", + "Apps.catLoops": "\u7e70\u308a\u8fd4\u3057", + "Apps.catMath": "\u6570\u5b66", + "Apps.catText": "\u30c6\u30ad\u30b9\u30c8", + "Apps.catLists": "\u30ea\u30b9\u30c8", + "Apps.catColour": "\u8272", + "Apps.catVariables": "\u5909\u6570", + "Apps.httpRequestError": "\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u63a5\u7d9a\u306e\u30a8\u30e9\u30fc\u3067\u3059\u3002", + "Apps.linkAlert": "\u30d6\u30ed\u30c3\u30af\u306e\u72b6\u614b\u3092\u3053\u306e\u30ea\u30f3\u30af\u3067\u5171\u6709\u3067\u304d\u307e\u3059:\n\n%1", + "Apps.hashError": "\u3059\u307f\u307e\u305b\u3093\u3002\u300c%1\u300d\u3068\u3044\u3046\u540d\u524d\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u306f\u4fdd\u5b58\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002", + "Apps.xmlError": "\u4fdd\u5b58\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u3092\u8aad\u307f\u8fbc\u3081\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u5225\u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u306e\u30d6\u30ed\u30c3\u30af\u30ea\u30fc\u3067\u4f5c\u6210\u3055\u308c\u305f\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002", + "Code.badXml": "XML \u306e\u30a8\u30e9\u30fc\u3067\u3059:\n%1\n\nXML \u306e\u5909\u66f4\u3092\u3084\u3081\u308b\u306b\u306f\u300cOK\u300d\u3001\u7de8\u96c6\u3092\u7d9a\u3051\u308b\u306b\u306f\u300c\u30ad\u30e3\u30f3\u30bb\u30eb\u300d\u3092\u9078\u3093\u3067\u304f\u3060\u3055\u3044\u3002", + "Code.badCode": "\u30d7\u30ed\u30b0\u30e9\u30e0\u306e\u30a8\u30e9\u30fc:\n%1", + "Code.discard": "%1 \u500b\u3059\u3079\u3066\u306e\u30d6\u30ed\u30c3\u30af\u3092\u6d88\u3057\u307e\u3059\u304b?", + "Code.title": "\u30b3\u30fc\u30c9", + "Code.blocks": "\u30d6\u30ed\u30c3\u30af", + "Code.trashTooltip": "\u3059\u3079\u3066\u306e\u30d6\u30ed\u30c3\u30af\u3092\u6d88\u3057\u307e\u3059\u3002", + "Maze.moveForward": "\u307e\u3063\u3059\u3050\u9032\u3080", + "Maze.turnLeft": "\u5de6\u3092\u5411\u304f", + "Maze.turnRight": "\u53f3\u3092\u5411\u304f", + "Maze.doCode": "\u5b9f\u884c", + "Maze.elseCode": "\u305d\u308c\u4ee5\u5916", + "Maze.helpIfElse": "\u300cif-else\u300d(\u3082\u3057-\u305d\u308c\u4ee5\u5916) \u30d6\u30ed\u30c3\u30af\u3067\u306f\u3001\u4e00\u65b9\u3068\u3082\u3046\u4e00\u65b9\u306e 2 \u3064\u306e\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002", + "Maze.pathAhead": "\u3082\u3057\u307e\u3063\u3059\u3050\u9032\u3081\u308b\u306a\u3089", + "Maze.pathLeft": "\u3082\u3057\u5de6\u306b\u9032\u3081\u308b\u306a\u3089", + "Maze.pathRight": "\u3082\u3057\u53f3\u306b\u9032\u3081\u308b\u306a\u3089", + "Maze.moveForwardTooltip": "\u30d7\u30ec\u30fc\u30e4\u30fc\u304c\u307e\u3063\u3059\u3050 1 \u30de\u30b9\u9032\u307f\u307e\u3059\u3002", + "Maze.turnTooltip": "\u30d7\u30ec\u30fc\u30e4\u30fc\u304c\u5de6\u307e\u305f\u306f\u53f3\u306b 90 \u5ea6\u5411\u304d\u3092\u5909\u3048\u307e\u3059\u3002", + "Maze.ifTooltip": "\u9078\u3093\u3060\u65b9\u5411\u306b\u9032\u3081\u308b\u5834\u5408\u306f\u3001\u4f55\u304b\u52d5\u4f5c\u3092\u3057\u307e\u3059\u3002", + "Maze.ifelseTooltip": "\u9078\u3093\u3060\u65b9\u5411\u306b\u9032\u3081\u308b\u5834\u5408\u306f\u6700\u521d\u306e\u30d6\u30ed\u30c3\u30af\u306e\u52d5\u4f5c\u3092\u3001\u9032\u3081\u306a\u3044\u5834\u5408\u306f 2 \u756a\u3081\u306e\u30d6\u30ed\u30c3\u30af\u306e\u52d5\u4f5c\u3092\u3057\u307e\u3059\u3002", + "Maze.whileTooltip": "\u5185\u5074\u306e\u52d5\u4f5c\u3092\u3001\u30b4\u30fc\u30eb\u306b\u7740\u304f\u307e\u3067\u7e70\u308a\u8fd4\u3057\u307e\u3059\u3002", + "Maze.capacity0": "\u6b8b\u308a %0 \u30d6\u30ed\u30c3\u30af\u3067\u3059\u3002", + "Maze.capacity1": "\u6b8b\u308a %1 \u30d6\u30ed\u30c3\u30af\u3067\u3059\u3002", + "Maze.capacity2": "\u6b8b\u308a %2 \u30d6\u30ed\u30c3\u30af\u3067\u3059\u3002", + "Maze.nextLevel": "\u304a\u3081\u3067\u3068\u3046! \u6b21\u306e\u30ec\u30d9\u30eb %1 \u306b\u9032\u307f\u307e\u3059\u304b?", + "Maze.maze": "\u8ff7\u8def", + "Maze.runTooltip": "\u4e26\u3079\u305f\u30d6\u30ed\u30c3\u30af\u306e\u52d5\u4f5c\u3092\u30d7\u30ec\u30fc\u30e4\u30fc\u306b\u5b9f\u884c\u3055\u305b\u307e\u3059\u3002", + "Maze.resetTooltip": "\u30d7\u30ec\u30fc\u30e4\u30fc\u3092\u8ff7\u8def\u306e\u6700\u521d\u306e\u5834\u6240\u306b\u623b\u3057\u307e\u3059\u3002", + "Maze.helpStack": "\u300c\u307e\u3063\u3059\u3050\u9032\u3080\u300d\u306e\u30d6\u30ed\u30c3\u30af\u3092\u3044\u304f\u3064\u304b\u7e26\u306b\u3064\u306a\u3044\u3067\u3001\u30b4\u30fc\u30eb\u306b\u9023\u308c\u3066\u884c\u3063\u3066\u304f\u3060\u3055\u3044\u3002", + "Maze.helpRun": "\u52d5\u4f5c\u3092\u898b\u308b\u306b\u306f\u3001\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u5b9f\u884c\u3057\u3066\u304f\u3060\u3055\u3044\u3002", + "Maze.helpReset": "\u3042\u306a\u305f\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u3067\u306f\u8ff7\u8def\u3092\u89e3\u3051\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u300c\u30ea\u30bb\u30c3\u30c8\u300d\u3092\u62bc\u3057\u3066\u3084\u308a\u76f4\u3057\u3066\u304f\u3060\u3055\u3044\u3002", + "Maze.helpRepeat": "2 \u500b\u306e\u30d6\u30ed\u30c3\u30af\u3060\u3051\u3067\u30b4\u30fc\u30eb\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u30d6\u30ed\u30c3\u30af\u3092\u7e70\u308a\u8fd4\u3057\u5b9f\u884c\u3059\u308b\u300c\u7e70\u308a\u8fd4\u3057\u300d\u3092\u4f7f\u3063\u3066\u304f\u3060\u3055\u3044\u3002", + "Maze.helpCapacity": "\u3053\u306e\u30ec\u30d9\u30eb\u3067\u4f7f\u3048\u308b\u30d6\u30ed\u30c3\u30af\u3092\u3059\u3079\u3066\u4f7f\u3044\u307e\u3057\u305f\u3002\u30d6\u30ed\u30c3\u30af\u3092\u65b0\u3057\u304f\u4f5c\u6210\u3059\u308b\u306b\u306f\u3001\u4eca\u3042\u308b\u30d6\u30ed\u30c3\u30af\u3092\u6d88\u3055\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002", + "Maze.helpRepeatMany": "\u300c\u7e70\u308a\u8fd4\u3057\u300d\u30d6\u30ed\u30c3\u30af\u306e\u4e2d\u3067\u30011 \u500b\u4ee5\u4e0a\u306e\u30d6\u30ed\u30c3\u30af\u3092\u4f7f\u3048\u307e\u3059\u3002", + "Maze.helpSkins": "\u3053\u306e\u30e1\u30cb\u30e5\u30fc\u304b\u3089\u597d\u304d\u306a\u30d7\u30ec\u30fc\u30e4\u30fc\u3092\u9078\u3093\u3067\u304f\u3060\u3055\u3044\u3002", + "Maze.helpIf": "\u300cif\u300d(\u3082\u3057) \u30d6\u30ed\u30c3\u30af\u306f\u6761\u4ef6\u304c\u6b63\u3057\u3044\u3068\u304d\u3060\u3051\u4f55\u304b\u52d5\u4f5c\u3092\u3057\u307e\u3059\u3002\u5de6\u306b\u9032\u3081\u308b\u3068\u304d\u306f\u5de6\u3092\u5411\u304f\u3088\u3046\u306b\u3057\u3066\u307f\u3066\u304f\u3060\u3055\u3044\u3002", + "Maze.helpMenu": "\u300cif\u300d(\u3082\u3057)\u30d6\u30ed\u30c3\u30af\u306e\u6761\u4ef6\u3092\u5909\u3048\u308b\u306b\u306f %1 \u3092\u30af\u30ea\u30c3\u30af\u3057\u3066\u304f\u3060\u3055\u3044\u3002", + "Maze.helpWallFollow": "\u3053\u306e\u96e3\u3057\u3044\u8ff7\u8def\u3092\u89e3\u3051\u307e\u3059\u304b? \u5de6\u5074\u306e\u58c1\u3092\u305f\u3069\u3063\u3066\u307f\u3066\u304f\u3060\u3055\u3044\u3002\u4e0a\u7d1a\u306e\u30d7\u30ed\u30b0\u30e9\u30de\u30fc\u5411\u3051\u306e\u8ff7\u8def\u3067\u3059!", + "Plane.rows": "\u5217\u306e\u6570: %1", + "Plane.getRows": "\u5217\u306e\u6570 (%1)", + "Plane.rows1": "\u30d5\u30a1\u30fc\u30b9\u30c8\u30af\u30e9\u30b9\u306e\u5217\u6570: %1", + "Plane.getRows1": "\u30d5\u30a1\u30fc\u30b9\u30c8\u30af\u30e9\u30b9\u306e\u5217\u6570 (%1)", + "Plane.rows2": "\u30bb\u30ab\u30f3\u30c9\u30af\u30e9\u30b9\u306e\u5217\u6570: %1", + "Plane.getRows2": "\u30bb\u30ab\u30f3\u30c9\u30af\u30e9\u30b9\u306e\u5217\u6570 (%1)", + "Plane.seats": "\u5ea7\u5e2d\u306e\u6570: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "\u5ea7\u5e2d\u306e\u6570 =", + "Plane.plane": "\u98db\u884c\u6a5f", + "Plane.description1": "\u98db\u884c\u6a5f\u306b\u4e57\u5ba2\u306e\u5ea7\u5e2d\u306e\u5217\u304c\u3042\u308a\u307e\u3059\u3002\u305d\u308c\u305e\u308c\u306e\u5217\u306b 4 \u3064\u306e\u5ea7\u5e2d\u304c\u3042\u308a\u307e\u3059\u3002", + "Plane.description2": "\u98db\u884c\u6a5f\u306b\u306f\u3001\u64cd\u7e26\u5ba4\u306e 2 \u3064\u306e\u5ea7\u5e2d (\u64cd\u7e26\u58eb\u3068\u526f\u64cd\u7e26\u58eb) \u3068\u3001\u4e57\u5ba2\u306e\u5ea7\u5e2d\u306e\u5217\u304c\u3042\u308a\u307e\u3059\u3002\u305d\u308c\u305e\u308c\u306e\u5217\u306b 4 \u3064\u306e\u5ea7\u5e2d\u304c\u3042\u308a\u307e\u3059\u3002", + "Plane.description3": "\u98db\u884c\u6a5f\u306b\u306f\u3001\u64cd\u7e26\u5ba4\u306e 2 \u3064\u306e\u5ea7\u5e2d (\u64cd\u7e26\u58eb\u3068\u526f\u64cd\u7e26\u58eb) \u3068\u3001\u30d5\u30a1\u30fc\u30b9\u30c8\u30af\u30e9\u30b9\u3068\u30bb\u30ab\u30f3\u30c9\u30af\u30e9\u30b9\u306e\u4e57\u5ba2\u306e\u5ea7\u5e2d\u306e\u5217\u304c\u3042\u308a\u307e\u3059\u3002\u305d\u308c\u305e\u308c\u306e\u5217\u306b\u3001\u30d5\u30a1\u30fc\u30b9\u30c8\u30af\u30e9\u30b9\u3067\u306f 4 \u3064\u306e\u5ea7\u5e2d\u3001\u30bb\u30ab\u30f3\u30c9\u30af\u30e9\u30b9\u3067\u306f 5 \u3064\u306e\u5ea7\u5e2d\u304c\u3042\u308a\u307e\u3059\u3002", + "Plane.instructions": "\u98db\u884c\u6a5f\u306e\u5ea7\u5e2d\u306e\u6570\u3092\u8a08\u7b97\u3059\u308b\u5f0f\u3092\u3001\u4e0a\u3067\u5217\u306e\u6570\u3092\u5909\u66f4\u3057\u3066\u3082\u6b63\u3057\u304f\u306a\u308b\u3088\u3046\u306b\u3001\u4e0b\u306b\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002", + "Puzzle.country1": "\u30aa\u30fc\u30b9\u30c8\u30e9\u30ea\u30a2", + "Puzzle.country1Language": "\u82f1\u8a9e", + "Puzzle.country1City1": "\u30e1\u30eb\u30dc\u30eb\u30f3", + "Puzzle.country1City2": "\u30b7\u30c9\u30cb\u30fc", + "Puzzle.country1HelpUrl": "http://ja.wikipedia.org/wiki/\u30aa\u30fc\u30b9\u30c8\u30e9\u30ea\u30a2", + "Puzzle.country2": "\u30c9\u30a4\u30c4", + "Puzzle.country2Language": "\u30c9\u30a4\u30c4\u8a9e", + "Puzzle.country2City1": "\u30d9\u30eb\u30ea\u30f3", + "Puzzle.country2City2": "\u30df\u30e5\u30f3\u30d8\u30f3", + "Puzzle.country2HelpUrl": "http://ja.wikipedia.org/wiki/\u30c9\u30a4\u30c4", + "Puzzle.country3": "\u4e2d\u56fd", + "Puzzle.country3Language": "\u4e2d\u56fd\u8a9e", + "Puzzle.country3City1": "\u5317\u4eac", + "Puzzle.country3City2": "\u4e0a\u6d77", + "Puzzle.country3HelpUrl": "http://ja.wikipedia.org/wiki/\u4e2d\u83ef\u4eba\u6c11\u5171\u548c\u56fd", + "Puzzle.country4": "\u30d6\u30e9\u30b8\u30eb", + "Puzzle.country4Language": "\u30dd\u30eb\u30c8\u30ac\u30eb\u8a9e", + "Puzzle.country4City1": "\u30ea\u30aa\u30c7\u30b8\u30e3\u30cd\u30a4\u30ed", + "Puzzle.country4City2": "\u30b5\u30f3\u30d1\u30a6\u30ed", + "Puzzle.country4HelpUrl": "http://ja.wikipedia.org/wiki/\u30d6\u30e9\u30b8\u30eb", + "Puzzle.flag": "\u56fd\u65d7:", + "Puzzle.language": "\u8a00\u8a9e:", + "Puzzle.languageChoose": "\u9078\u3093\u3067\u304f\u3060\u3055\u3044...", + "Puzzle.cities": "\u90fd\u5e02:", + "Puzzle.error0": "\u5b8c\u307a\u304d\u3067\u3059!\n%1 \u500b\u306e\u30d6\u30ed\u30c3\u30af\u304c\u5168\u554f\u6b63\u89e3\u3067\u3059\u3002", + "Puzzle.error1": "\u60dc\u3057\u3044! 1 \u500b\u306e\u30d6\u30ed\u30c3\u30af\u304c\u9593\u9055\u3063\u3066\u3044\u307e\u3059\u3002", + "Puzzle.error2": "%1 \u500b\u306e\u30d6\u30ed\u30c3\u30af\u304c\u9593\u9055\u3063\u3066\u3044\u307e\u3059\u3002", + "Puzzle.tryAgain": "\u5f37\u8abf\u3055\u308c\u3066\u3044\u308b\u30d6\u30ed\u30c3\u30af\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002\n\u304c\u3093\u3070\u3063\u3066\u304f\u3060\u3055\u3044\u3002", + "Puzzle.title": "\u30d1\u30ba\u30eb", + "Puzzle.help": "\u30d8\u30eb\u30d7", + "Puzzle.checkAnswers": "\u7b54\u3048\u5408\u308f\u305b", + "Puzzle.helpText": "\u305d\u308c\u305e\u308c\u306e\u56fd (\u7dd1) \u306b\u3064\u3044\u3066\u3001\u56fd\u65d7\u3092\u3064\u306a\u3052\u3066\u3001\u8a00\u8a9e\u3092\u9078\u3093\u3067\u3001\u90fd\u5e02\u3092\u4e26\u3079\u3066\u304f\u3060\u3055\u3044\u3002", + "Turtle.moveTooltip": "\u6307\u5b9a\u3057\u305f\u9577\u3055\u3060\u3051\u524d\u307e\u305f\u306f\u5f8c\u308d\u306b\u30bf\u30fc\u30c8\u30eb\u3092\u52d5\u304b\u3057\u307e\u3059\u3002", + "Turtle.moveForward": "\u524d\u306b\u9032\u3080", + "Turtle.moveBackward": "\u5f8c\u308d\u306b\u9032\u3080", + "Turtle.turnTooltip": "\u6307\u5b9a\u3057\u305f\u89d2\u5ea6\u3060\u3051\u30bf\u30fc\u30c8\u30eb\u3092\u56de\u8ee2\u3055\u305b\u307e\u3059\u3002", + "Turtle.turnRight": "\u53f3\u306b\u56de\u8ee2", + "Turtle.turnLeft": "\u5de6\u306b\u56de\u8ee2", + "Turtle.widthTooltip": "\u30da\u30f3\u306e\u592a\u3055\u3092\u5909\u3048\u307e\u3059\u3002", + "Turtle.setWidth": "\u592a\u3055\u3092\u5909\u3048\u308b", + "Turtle.colourTooltip": "\u30da\u30f3\u306e\u8272\u3092\u5909\u3048\u307e\u3059\u3002", + "Turtle.setColour": "\u8272\u3092\u5909\u3048\u308b", + "Turtle.penTooltip": "\u7dda\u3092\u5f15\u3044\u305f\u308a\u5f15\u304f\u306e\u3092\u3084\u3081\u305f\u308a\u3059\u308b\u305f\u3081\u306b\u3001\u30da\u30f3\u3092\u4e0a\u3052\u308b\u304b\u4e0b\u3052\u308b\u304b\u3057\u307e\u3059\u3002", + "Turtle.penUp": "\u30da\u30f3\u3092\u4e0a\u3052\u308b", + "Turtle.penDown": "\u30da\u30f3\u3092\u4e0b\u308d\u3059", + "Turtle.turtleVisibilityTooltip": "\u30bf\u30fc\u30c8\u30eb (\u5186\u3068\u77e2\u5370) \u306e\u8868\u793a/\u975e\u8868\u793a\u3092\u5207\u308a\u66ff\u3048\u307e\u3059\u3002", + "Turtle.printHelpUrl": "http://ja.wikipedia.org/wiki/\u5370\u5237", + "Turtle.printTooltip": "\u30bf\u30fc\u30c8\u30eb\u306e\u65b9\u5411\u3068\u5834\u6240\u3092\u6587\u5b57\u3068\u3057\u3066\u8868\u793a\u3057\u307e\u3059\u3002", + "Turtle.print": "\u8868\u793a", + "Turtle.fontHelpUrl": "http://en.wikipedia.org/wiki/Font", + "Turtle.fontTooltip": "\u8868\u793a\u30d6\u30ed\u30c3\u30af\u3067\u4f7f\u3046\u30d5\u30a9\u30f3\u30c8\u3092\u8a2d\u5b9a\u3057\u307e\u3059\u3002", + "Turtle.font": "\u30d5\u30a9\u30f3\u30c8", + "Turtle.fontSize": "\u30d5\u30a9\u30f3\u30c8 \u30b5\u30a4\u30ba", + "Turtle.fontNormal": "\u6a19\u6e96", + "Turtle.fontBold": "\u592a\u5b57", + "Turtle.fontItalic": "\u659c\u4f53", + "Turtle.unloadWarning": "\u3053\u306e\u30da\u30fc\u30b8\u304b\u3089\u96e2\u308c\u308b\u3068\u3001\u4f5c\u3063\u305f\u4f5c\u54c1\u304c\u5931\u308f\u308c\u307e\u3059\u3002", + "Turtle.title": "\u30bf\u30fc\u30c8\u30eb \u30b0\u30e9\u30d5\u30a3\u30c3\u30af\u30b9", + "Turtle.captureTooltip": "\u7d75\u3092\u4fdd\u5b58\u3057\u307e\u3059\u3002", + "Turtle.imgFilename": "\u304a\u7d75\u63cf\u304d.png", + "Turtle.catTurtle": "\u30bf\u30fc\u30c8\u30eb" +} \ No newline at end of file diff --git a/apps/json/ka.json b/apps/json/ka.json new file mode 100644 index 000000000..c2b2a6a87 --- /dev/null +++ b/apps/json/ka.json @@ -0,0 +1,35 @@ +{ + "Puzzle.tryAgain": "გამოყოფილი ბლოკი არასწორია.\nკიდევ სცადეთ.", + "Puzzle.country3City2": "შანხაი", + "Puzzle.country3HelpUrl": "http://ka.wikipedia.org/wiki/ჩინეთი", + "Puzzle.country3Language": "ჩინური", + "Puzzle.checkAnswers": "პასუხების შემოწმება", + "Puzzle.language": "ენა:", + "Apps.dialogOk": "კარგი", + "Puzzle.title": "თავსატეხი", + "Puzzle.country1HelpUrl": "http://ka.wikipedia.org/wiki/ავსტრალია", + "Puzzle.languageChoose": "აირჩიეთ...", + "Puzzle.country4City2": "სან-პაულუ", + "Puzzle.country4City1": "რიო-დე-ჟანეირო", + "Puzzle.country4Language": "პორტუგალიური", + "Puzzle.helpText": "თითოეულ ქვეყანას (მწვანე), მიამაგრეთ მისი დროშა, აირჩიეთ ოფიციალური ენა და ამ ქვეყანაში მდებარე ქალაქები.", + "Puzzle.flag": "დროშა:", + "Puzzle.country4HelpUrl": "http://ka.wikipedia.org/wiki/ბრაზილია", + "Puzzle.error1": "თითქმის! ერთი ბლოკი არასწორია.", + "Puzzle.country3City1": "პეკინი", + "Puzzle.country1City1": "მელბურნი", + "Puzzle.country1City2": "სიდნეი", + "Puzzle.country2Language": "გერმანული", + "Puzzle.country3": "ჩინეთი", + "Puzzle.country2": "გერმანია", + "Puzzle.country1": "ავსტრალია", + "Puzzle.country2HelpUrl": "http://ka.wikipedia.org/wiki/გერმანია", + "Puzzle.error0": "ბრწყინვალეა!\nყველა %1 ბლოკი სწორია.", + "Puzzle.country4": "ბრაზილია", + "Puzzle.error2": "%1 ბლოკი არასწორია.", + "Puzzle.help": "დახმარება", + "Puzzle.country1Language": "ინგლისური", + "Puzzle.country2City1": "ბერლინი", + "Puzzle.cities": "ქალაქები:", + "Puzzle.country2City2": "მიუნხენი" +} diff --git a/apps/json/keys.json b/apps/json/keys.json new file mode 100644 index 000000000..51541e217 --- /dev/null +++ b/apps/json/keys.json @@ -0,0 +1,145 @@ +{ +"Apps.subtitle": "9151382257658567281", +"Apps.blocklyMessage": "6650354588969822092", +"Apps.codeTooltip": "5838195295317713027", +"Apps.linkTooltip": "5391382062551588177", +"Apps.runTooltip": "6316320629891574281", +"Apps.runProgram": "6189808175540281396", +"Apps.resetProgram": "6533409555866489852", +"Apps.dialogOk": "3964361619617826429", +"Apps.dialogCancel": "8605819299263106886", +"Apps.catLogic": "1686883036031489642", +"Apps.catLoops": "8514812131842527965", +"Apps.catMath": "8504064665960111059", +"Apps.catText": "2561306449483326985", +"Apps.catLists": "7880221162350996120", +"Apps.catColour": "5532942470899034153", +"Apps.catVariables": "3279501947911403228", +"Apps.catProcedures": "5803514418162480510", +"Apps.httpRequestError": "6491926390857975299", +"Apps.linkAlert": "6192625840582724866", +"Apps.hashError": "2570539532822249158", +"Apps.xmlError": "5758425077401246127", +"Apps.listVariable": "7314181232693154293", +"Apps.textVariable": "768570576516576913", +"Code.badXml": "148032336181194017", +"Code.badCode": "8943253138333696551", +"Code.timeout": "1350759209070481203", +"Code.discard": "1020451542663054555", +"Code.title": "339365101010834276", +"Code.blocks": "586801704101593425", +"Code.trashTooltip": "1406728939680691839", +"Graph.title": "6161178750148345044", +"Maze.moveForward": "4138774728570944645", +"Maze.turnLeft": "6082253890512898845", +"Maze.turnRight": "2801052495540198573", +"Maze.doCode": "5922351303839855212", +"Maze.elseCode": "9137982570247930589", +"Maze.helpIfElse": "8678021904034212986", +"Maze.pathAhead": "3293197141663117591", +"Maze.pathLeft": "2149839397262503913", +"Maze.pathRight": "8496210457380227143", +"Maze.repeatUntil": "5000330788075193694", +"Maze.moveForwardTooltip": "4634715858389563104", +"Maze.turnTooltip": "4502373380845009974", +"Maze.ifTooltip": "4874525273235336318", +"Maze.ifelseTooltip": "1843334689331866804", +"Maze.whileTooltip": "1190064103412776740", +"Maze.capacity0": "1794249676769577229", +"Maze.capacity1": "5307089055470217701", +"Maze.capacity2": "561418461570337551", +"Maze.nextLevel": "7358214333593766572", +"Maze.finalLevel": "7149849676690329496", +"Maze.maze": "34428208008617605", +"Maze.runTooltip": "2075728723517768097", +"Maze.resetTooltip": "3190825933229819894", +"Maze.helpStack": "4362899193616566882", +"Maze.helpOneTopBlock": "5355893896926183437", +"Maze.helpRun": "4751586063015654997", +"Maze.helpReset": "8109604937581467227", +"Maze.helpRepeat": "6682302477448017479", +"Maze.helpCapacity": "1061578198057067927", +"Maze.helpRepeatMany": "3478101938294488773", +"Maze.helpSkins": "5683520235628284499", +"Maze.helpIf": "5076791813618961196", +"Maze.helpMenu": "1456515588173174520", +"Maze.helpWallFollow": "7135964206164849448", +"Plane.rows": "286555642257111053", +"Plane.getRows": "7030918043298347994", +"Plane.rows1": "7091637686507441682", +"Plane.getRows1": "5622822520334788359", +"Plane.rows2": "6523489254328705062", +"Plane.getRows2": "8347578891541780742", +"Plane.seats": "6636919311618748816", +"Plane.placeholder": "1649099567159388799", +"Plane.setSeats": "990695256953568910", +"Plane.plane": "5107849227960116393", +"Plane.description1": "7784699858027886282", +"Plane.description2": "4755413400587385256", +"Plane.description3": "1327005465775917626", +"Plane.instructions": "3872872459414039837", +"Puzzle.country1": "8225483509416707116", +"Puzzle.country1Language": "1287357579287299642", +"Puzzle.country1City1": "2745637248856614957", +"Puzzle.country1City2": "3526991786845491951", +"Puzzle.country1HelpUrl": "3200098429010885725", +"Puzzle.country2": "4387610548281891603", +"Puzzle.country2Language": "3821803554803730960", +"Puzzle.country2City1": "5350996283015775721", +"Puzzle.country2City2": "2217658647698715954", +"Puzzle.country2HelpUrl": "4355724231168061337", +"Puzzle.country3": "4467754447775177700", +"Puzzle.country3Language": "569611506796947817", +"Puzzle.country3City1": "4831971084084101656", +"Puzzle.country3City2": "9030321566026677700", +"Puzzle.country3HelpUrl": "7513531880031229964", +"Puzzle.country4": "4740404346868773841", +"Puzzle.country4Language": "4353792691863884862", +"Puzzle.country4City1": "4092567125241388941", +"Puzzle.country4City2": "172935374208882914", +"Puzzle.country4HelpUrl": "8973971279553647533", +"Puzzle.flag": "3903900976387299493", +"Puzzle.language": "942647526999045936", +"Puzzle.languageChoose": "2989183467808289061", +"Puzzle.cities": "7544100018692826729", +"Puzzle.error0": "2353453760676853811", +"Puzzle.error1": "8453803544352763294", +"Puzzle.error2": "7264063713014053084", +"Puzzle.tryAgain": "183634583247013051", +"Puzzle.title": "8436599549372868479", +"Puzzle.help": "6508091993289219492", +"Puzzle.checkAnswers": "2827102143774531943", +"Puzzle.helpText": "5519625826423551192", +"Turtle.moveTooltip": "552526916301133670", +"Turtle.moveForward": "1013045213595604872", +"Turtle.moveBackward": "4294783477990312138", +"Turtle.turnTooltip": "7089740218907481322", +"Turtle.turnRight": "6889946611851664425", +"Turtle.turnLeft": "6078028329780496695", +"Turtle.widthTooltip": "1359456544648181295", +"Turtle.setWidth": "8470792861618868667", +"Turtle.colourTooltip": "2201212763190410627", +"Turtle.setColour": "8983835283796130303", +"Turtle.penTooltip": "945126989426193972", +"Turtle.penUp": "196845303311122428", +"Turtle.penDown": "295126337553066153", +"Turtle.turtleVisibilityTooltip": "7922752443358054817", +"Turtle.hideTurtle": "1146327621590900127", +"Turtle.showTurtle": "8598935855828958714", +"Turtle.printHelpUrl": "5700517745634037643", +"Turtle.printTooltip": "6192195229721218364", +"Turtle.print": "8755460901437343901", +"Turtle.fontHelpUrl": "7999536902480463813", +"Turtle.fontTooltip": "4392335668231319812", +"Turtle.font": "4130136547051161134", +"Turtle.fontSize": "2409415650297366191", +"Turtle.fontNormal": "3160118472257830313", +"Turtle.fontBold": "2555132265974908158", +"Turtle.fontItalic": "3792533731296600003", +"Turtle.unloadWarning": "7055959262533612779", +"Turtle.title": "1706166575733269263", +"Turtle.runTooltip": "327067666833971381", +"Turtle.captureTooltip": "793577727112679597", +"Turtle.imgFilename": "7221035465778066902", +"Turtle.catTurtle": "5180825245477618167" +} diff --git a/apps/json/km.json b/apps/json/km.json new file mode 100644 index 000000000..ab46d8e53 --- /dev/null +++ b/apps/json/km.json @@ -0,0 +1,35 @@ +{ + "Puzzle.tryAgain": "ប្លុកដែលដាក់ពណ៌ហ៊ុំមិនទាន់ត្រឹមត្រូវទេ។\nសូមព្យាយាមបន្ត។", + "Puzzle.country3City2": "សៀងហៃ", + "Puzzle.country3HelpUrl": "http://km.wikipedia.org/wiki/ចិន", + "Puzzle.country3Language": "ភាសាចិន", + "Puzzle.checkAnswers": "ផ្ទៀងផ្ទាត់ចម្លើយ", + "Puzzle.language": "ភាសា៖", + "Apps.dialogOk": "យល់ព្រម", + "Puzzle.title": "ល្បែងផ្គុំប្លុក", + "Puzzle.country1HelpUrl": "http://km.wikipedia.org/wiki/អូស្ត្រាលី", + "Puzzle.languageChoose": "ជ្រើសរើស...", + "Puzzle.country4City2": "សៅប៉ូឡូ", + "Puzzle.country4City1": "រ្យូដេចានេរ៉ូ", + "Puzzle.country4Language": "ភាសាព័រទុយហ្គាល់", + "Puzzle.helpText": "ភ្ជាប់ទង់ជាតិ ជ្រើសរើសភាសា និង ផ្គុំឈ្មោះទីក្រុងសម្រាប់ប្រទេសនីមួយៗ (ពណ៌បៃតង)។", + "Puzzle.flag": "ទង់ជាតិ", + "Puzzle.country4HelpUrl": "http://km.wikipedia.org/wiki/ប្រេស៊ីល", + "Puzzle.error1": "ជិតហើយៗ! នៅសល់តែប្លុកមួយទៀតមិនទាន់ត្រូវ។", + "Puzzle.country3City1": "ប៉េកាំង", + "Puzzle.country1City1": "ម៉ែលបូន", + "Puzzle.country1City2": "ស៊ីដនី", + "Puzzle.country2Language": "ភាសាអាល្លឺម៉ង់", + "Puzzle.country3": "ចិន", + "Puzzle.country2": "អាល្លឺម៉ង់", + "Puzzle.country1": "អូស្ត្រាលី", + "Puzzle.country2HelpUrl": "http://km.wikipedia.org/wiki/អាល្លឺម៉ង់", + "Puzzle.error0": "ល្អណាស់!\nផ្គុំត្រូវប្លុកចំនួន%1ទាំងអស់ហើយ។", + "Puzzle.country4": "ប្រេស៊ីល", + "Puzzle.error2": "នៅសល់ប្លុកចំនួន %1 ទៀតមិនទាន់ត្រឹមត្រូវ។", + "Puzzle.help": "ជំនួយ", + "Puzzle.country1Language": "ភាសាអង់គ្លេស", + "Puzzle.country2City1": "ប៊ែរឡាំង", + "Puzzle.cities": "ទីក្រុង៖", + "Puzzle.country2City2": "មុយនិច" +} diff --git a/apps/json/ko.json b/apps/json/ko.json new file mode 100644 index 000000000..2aa642b46 --- /dev/null +++ b/apps/json/ko.json @@ -0,0 +1,151 @@ +{ + "@metadata": { + "authors": [ + "Hym411", + "\uc544\ub77c" + ] + }, + "Apps.subtitle": "\uc2dc\uac01 \ud504\ub85c\uadf8\ub798\ubc0d \ud658\uacbd", + "Apps.blocklyMessage": "\ube14\ub85d\ub9ac", + "Apps.codeTooltip": "\uc0dd\uc131\ub41c \uc790\ubc14\uc2a4\ud06c\ub9bd\ud2b8 \ucf54\ub4dc\ub97c \ubd05\ub2c8\ub2e4.", + "Apps.linkTooltip": "\ube14\ub85d\uc744 \uc800\uc7a5\ud558\uace0 \ub9c1\ud06c\ub97c \uac00\uc838\uc635\ub2c8\ub2e4.", + "Apps.runTooltip": "\uc791\uc5c5 \uacf5\uac04\uc5d0\uc11c \ube14\ub85d\uc73c\ub85c \uc815\uc758\ub41c \ud504\ub85c\uadf8\ub7a8\uc744 \uc2e4\ud589\ud569\ub2c8\ub2e4.", + "Apps.runProgram": "\ud504\ub85c\uadf8\ub7a8 \uc2e4\ud589", + "Apps.resetProgram": "\uc7ac\uc124\uc815", + "Apps.dialogOk": "\ud655\uc778", + "Apps.dialogCancel": "\ucde8\uc18c", + "Apps.catLogic": "\ub17c\ub9ac", + "Apps.catLoops": "\ubc18\ubcf5", + "Apps.catMath": "\uc218\ud559", + "Apps.catText": "\ud14d\uc2a4\ud2b8", + "Apps.catLists": "\ubaa9\ub85d", + "Apps.catColour": "\uc0c9", + "Apps.catVariables": "\ubcc0\uc218", + "Apps.catProcedures": "\uc808\ucc28", + "Apps.httpRequestError": "\uc694\uccad\uc5d0 \ubb38\uc81c\uac00 \uc788\uc2b5\ub2c8\ub2e4.", + "Apps.linkAlert": "\ub2e4\uc74c \ub9c1\ud06c\ub85c \ube14\ub85d\uc744 \uacf5\uc720\ud558\uc138\uc694:\n\n%1", + "Apps.hashError": "\uc8c4\uc1a1\ud558\uc9c0\ub9cc '%1'\uc740 \uc5b4\ub5a4 \uc800\uc7a5\ub41c \ud504\ub85c\uadf8\ub7a8\uc73c\ub85c \uc77c\uce58\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.", + "Apps.xmlError": "\uc800\uc7a5\ub41c \ud30c\uc77c\uc744 \ubd88\ub7ec\uc62c \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. \ud639\uc2dc \ube14\ub85d\ub9ac\uc758 \ub2e4\ub978 \ubc84\uc804\uc73c\ub85c \ub9cc\ub4e4\uc5c8\uc2b5\ub2c8\uae4c?", + "Apps.listVariable": "\ubaa9\ub85d", + "Apps.textVariable": "\ud14d\uc2a4\ud2b8", + "Code.badXml": "XML \uad6c\ubb38 \ubd84\uc11d \uc624\ub958:\n%1\n\n\ubc14\ub01c\uc744 \ud3ec\uae30\ud558\ub824\uba74 '\ud655\uc778'\uc744 \uc120\ud0dd\ud558\uace0 XML\uc744 \ub354 \ud3b8\uc9d1\ud558\ub824\uba74 '\ucde8\uc18c'\ub97c \uc120\ud0dd\ud558\uc138\uc694.", + "Code.badCode": "\ud504\ub85c\uadf8\ub7a8 \uc624\ub958:\n%1", + "Code.timeout": "\ucd5c\ub300 \uc2e4\ud589 \ubc18\ubcf5\uc744 \ucd08\uacfc\ud588\uc2b5\ub2c8\ub2e4.", + "Code.discard": "\ubaa8\ub4e0 \ube14\ub85d %1\uac1c\ub97c \uc0ad\uc81c\ud558\uaca0\uc2b5\ub2c8\uae4c?", + "Code.title": "\ucf54\ub4dc", + "Code.blocks": "\ube14\ub85d", + "Code.trashTooltip": "\ubaa8\ub4e0 \ube14\ub85d\uc744 \ubc84\ub9bd\ub2c8\ub2e4.", + "Graph.title": "\uadf8\ub798\ud504 \uacc4\uc0b0\uae30", + "Maze.moveForward": "\uc55e\uc73c\ub85c \uac00\uae30", + "Maze.turnLeft": "\uc67c\ucabd\uc73c\ub85c \ub3cc\uae30", + "Maze.turnRight": "\uc624\ub978\ucabd\uc73c\ub85c \ub3cc\uae30", + "Maze.doCode": "\ud558\uae30", + "Maze.elseCode": "\uadf8\ub807\uc9c0 \uc54a\uc73c\uba74", + "Maze.helpIfElse": "\ub9cc\uc57d-\uadf8\ub807\uc9c0 \uc54a\uc73c\uba74 \ube14\ub85d\uc740 \ud55c \uac00\uc9c0 \ub610\ub294 \ub2e4\ub978 \ud589\ub3d9\uc744 \ud569\ub2c8\ub2e4.", + "Maze.pathAhead": "\ub9cc\uc57d \uc55e\uc73c\ub85c \uac00\uba74", + "Maze.pathLeft": "\ub9cc\uc57d \uc67c\ucabd\uc73c\ub85c \uac00\uba74", + "Maze.pathRight": "\ub9cc\uc57d \uc624\ub978\ucabd\uc73c\ub85c \uac00\uba74", + "Maze.repeatUntil": "\ub2e4\uc74c\uae4c\uc9c0 \ubc18\ubcf5", + "Maze.moveForwardTooltip": "\ud50c\ub808\uc774\uc5b4\uac00 \ud55c \uce78 \uc55e\uc73c\ub85c \uc774\ub3d9\ud569\ub2c8\ub2e4.", + "Maze.turnTooltip": "\ud50c\ub808\uc774\uc5b4\uac00 90\ub3c4\ub85c \uc67c\ucabd\uc774\ub098 \uc624\ub978\ucabd\uc73c\ub85c \ub3d5\ub2c8\ub2e4.", + "Maze.ifTooltip": "\ub9cc\uc57d \uc9c0\uc815\ub41c \ubc29\ud5a5\uc73c\ub85c \ud558\uace0 \uc788\uc73c\uba74, \uba87 \uac00\uc9c0 \ud589\ub3d9\uc744 \ud569\ub2c8\ub2e4.", + "Maze.ifelseTooltip": "\ub9cc\uc57d \uc9c0\uc815\ub41c \ubc29\ud5a5\uc73c\ub85c \ud558\uace0 \uc788\uc73c\uba74, \uccab \ubc88\uc9f8 \ube14\ub85d\uc744 \ud589\ub3d9\uc744 \ud569\ub2c8\ub2e4. \uadf8\ub807\uc9c0 \uc54a\uc73c\uba74, \ub450 \ubc88\uc9f8 \ube14\ub85d\uc744 \ud589\ub3d9\uc744 \ud569\ub2c8\ub2e4.", + "Maze.whileTooltip": "\ub3c4\ucc29\uc810\uc5d0 \ub3c4\ub2ec\ud560 \ub54c\uae4c\uc9c0 \ub0b4\ubd80 \ud589\ub3d9\uc744 \ubc18\ubcf5\ud569\ub2c8\ub2e4.", + "Maze.capacity0": "\ub098\uba38\uc9c0 \ube14\ub85d %0\uac1c\uac00 \uc788\uc2b5\ub2c8\ub2e4.", + "Maze.capacity1": "\ub098\uba38\uc9c0 \ube14\ub85d %1\uac1c\uac00 \uc788\uc2b5\ub2c8\ub2e4.", + "Maze.capacity2": "\ub098\uba38\uc9c0 \ube14\ub85d %2\uac1c\uac00 \uc788\uc2b5\ub2c8\ub2e4.", + "Maze.nextLevel": "\ucd95\ud558\ud569\ub2c8\ub2e4! %1\ub2e8\uacc4\ub97c \uc9c4\ud589\ud560 \uc900\ube44\uac00 \ub418\uc5c8\uc2b5\ub2c8\uae4c?", + "Maze.finalLevel": "\ucd95\ud558\ud569\ub2c8\ub2e4! \ucd5c\uc885 \ub2e8\uacc4\ub97c \ud574\uacb0\ud588\uc2b5\ub2c8\ub2e4.", + "Maze.maze": "\ubbf8\ub85c", + "Maze.runTooltip": "\ube14\ub85d\uc774 \ub9d0\ud558\ub294 \ud589\ub3d9\uc744 \ud50c\ub808\uc774\uc5b4\uac00 \ud569\ub2c8\ub2e4.", + "Maze.resetTooltip": "\ubbf8\ub85c\uc758 \uc2dc\uc791\uc5d0\uc11c \ud50c\ub808\uc774\uc5b4\ub97c \ub2e4\uc2dc \ub123\uc2b5\ub2c8\ub2e4.", + "Maze.helpStack": "\ubaa9\ud45c\uc5d0 \ub3c4\ub2ec\ud560 \uc218 \uc788\ub3c4\ub85d \ud568\uaed8 '\uc55e\uc73c\ub85c \uac00\uae30' \ube14\ub85d\uc744 \uc138\ub85c\ub85c \uc313\uc73c\uc138\uc694.", + "Maze.helpOneTopBlock": "\uc774 \ub2e8\uacc4\uc5d0\uc11c, \ud558\uc580 \uc791\uc5c5 \uacf5\uac04\uc5d0\uc11c \ubaa8\ub4e0 \ube14\ub85d\uc744 \ud568\uaed8 \uc313\uc744 \ud544\uc694\uac00 \uc788\uc2b5\ub2c8\ub2e4.", + "Maze.helpRun": "\uc5b4\ub5bb\uac8c \ub418\ub294\uc9c0 \ubcf4\ub824\uba74 \ud504\ub85c\uadf8\ub7a8\uc744 \uc2e4\ud589\ud558\uc138\uc694.", + "Maze.helpReset": "\ub2f9\uc2e0\uc758 \ud504\ub85c\uadf8\ub7a8\uc740 \ubbf8\ub85c\ub97c \ud480 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. '\uc7ac\uc124\uc815'\uc744 \ub204\ub974\uace0 \ub2e4\uc2dc \uc2dc\ub3c4\ud558\uc138\uc694.", + "Maze.helpRepeat": "\ucef4\ud4e8\ud130\ub294 \uc81c\ud55c\ub41c \uba54\ubaa8\ub9ac\uac00 \uc788\uc2b5\ub2c8\ub2e4. \ube14\ub85d \ub450 \uac1c\ub9cc \uc0ac\uc6a9\ud574 \uc774 \uae38\uc758 \ub05d\uc5d0 \ub3c4\ub2ec\ud558\uc138\uc694. \ud55c \ubc88 \uc774\uc0c1 \ube14\ub85d\uc744 \uc2e4\ud589\ud558\ub824\uba74 '\ubc18\ubcf5'\uc744 \uc0ac\uc6a9\ud558\uc138\uc694.", + "Maze.helpCapacity": "\uc774 \ub2e8\uacc4\uc5d0 \ub300\ud55c \ubaa8\ub4e0 \ube14\ub85d\uc744 \uc0ac\uc6a9\ud588\uc2b5\ub2c8\ub2e4. \uc0c8 \ube14\ub85d\uc740 \ub9cc\ub4dc\ub824\uba74, \uba3c\uc800 \uae30\uc874 \ube14\ub85d\uc744 \uc0ad\uc81c\ud574\uc57c \ud569\ub2c8\ub2e4.", + "Maze.helpRepeatMany": "'\ubc18\ubcf5' \ube14\ub85d \uc548\uc5d0 \ud558\ub098 \uc774\uc0c1\uc758 \ube14\ub85d\uc744 \ub123\uc744 \uc218 \uc788\uc2b5\ub2c8\ub2e4.", + "Maze.helpSkins": "\uba54\ub274\uc5d0\uc11c \ub2f9\uc2e0\uc774 \uc88b\uc544\ud558\ub294 \uc120\uc218\ub97c \uace0\ub974\uc138\uc694.", + "Maze.helpIf": "'\ub9cc\uc57d' \ube14\ub85d\uc740 \uc870\uac74\uc774 \ucc38\uc774\uba74 \ubb34\uc5b8\uac00\ub97c \ud569\ub2c8\ub2e4. \uc67c\ucabd\uc5d0 \uae38\uc774 \uc788\uc73c\uba74 \uc67c\ucabd\uc73c\ub85c \ub3cc\ub3c4\ub85d \ud558\uc138\uc694.", + "Maze.helpMenu": "'\ub9cc\uc57d' \ube14\ub85d\uc758 \uc870\uac74\uc744 \ubc14\uafb8\ub824\uba74 %1 \ubd80\ubd84\uc744 \ud074\ub9ad\ud558\uc138\uc694.", + "Maze.helpWallFollow": "\ubcf5\uc7a1\ud55c \ubbf8\ub85c\ub97c \ud480 \uc218 \uc788\uc2b5\ub2c8\uae4c? \ub2e4\uc74c \uc67c\ucabd \ubcbd\uc744 \ud558\uc138\uc694. \uace0\uae09 \ud504\ub85c\uadf8\ub798\uba38\ub9cc!", + "Plane.rows": "\ud589 \uc218: %1", + "Plane.getRows": "\ud589 \uc218 (%1)", + "Plane.rows1": "1\ub4f1\uc11d \ud589 \uc218: %1", + "Plane.getRows1": "1\ub4f1\uc11d \ud589 \uc218 (%1)", + "Plane.rows2": "2\ub4f1\uc11d \ud589 \uc218: %1", + "Plane.getRows2": "2\ub4f1\uc11d \ud589 \uc218 (%1)", + "Plane.seats": "\uc88c\uc11d \uc218: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "\uc88c\uc11d\uc218 =", + "Plane.plane": "\ube44\ud589\uae30", + "Plane.description1": "\ube44\ud589\uae30\ub294 \uc2b9\uac1d \uc88c\uc11d\uc758 \ud589 \uc218\uac00 \uc788\uc2b5\ub2c8\ub2e4. \uac01 \ud589\uc5d0\ub294 \uc2dc\ud2b8 \ub124 \uac1c\uac00 \ud3ec\ud568\ub418\uc5b4 \uc788\uc2b5\ub2c8\ub2e4.", + "Plane.description2": "\ube44\ud589\uae30\ub294 \ube44\ud589 \uac11\ud310(\uc870\uc885\uc0ac\uc640 \ubd80\uc870\uc885\uc0ac\uc6a9)\uc5d0\uc11c \uc88c\uc11d \ub450 \uac1c\uac00 \uc788\uace0, \uc2b9\uac1d \uc88c\uc11d\uc758 \ud589 \uc218\uac00 \uc788\uc2b5\ub2c8\ub2e4. \uac01 \ud589\uc5d0\ub294 \uc2dc\ud2b8 \ub124 \uac1c\uac00 \ud3ec\ud568\ub418\uc5b4 \uc788\uc2b5\ub2c8\ub2e4.", + "Plane.description3": "\ube44\ud589\uae30\ub294 \ube44\ud589 \uac11\ud310(\uc870\uc885\uc0ac\uc640 \ubd80\uc870\uc885\uc0ac\uc6a9)\uc5d0\uc11c \uc88c\uc11d \ub450 \uac1c\uac00 \uc788\uace0, 1\ub4f1\uc11d\uacfc 2\ub4f1\uc11d \uc2b9\uac1d \uc88c\uc11d\uc758 \ud589 \uc218\uac00 \uc788\uc2b5\ub2c8\ub2e4. \uac01 1\ub4f1\uc11d \ud589\uc5d0\ub294 \uc2dc\ud2b8 \ub124 \uac1c\uac00 \ud3ec\ud568\ub418\uc5b4 \uc788\uc2b5\ub2c8\ub2e4. \uac01 2\ub4f1\uc11d \ud589\uc5d0\ub294 \uc2dc\ud2b8 \ub2e4\uc12f \uac1c\uac00 \ud3ec\ud568\ub418\uc5b4 \uc788\uc2b5\ub2c8\ub2e4.", + "Plane.instructions": "\ud589\uc774 \ubc14\ub010(\uc704) \ube44\ud589\uae30\uc5d0 \uc88c\uc11d\uc758 \ucd1d \uc218\ub97c \uacc4\uc0b0\ud558\ub294 \uacf5\uc2dd(\uc544\ub798)\uc744 \uad6c\ucd95\ud558\uc138\uc694.", + "Puzzle.country1": "\ud638\uc8fc", + "Puzzle.country1Language": "\uc601\uc5b4", + "Puzzle.country1City1": "\uba5c\ubc84\ub978", + "Puzzle.country1City2": "\uc2dc\ub4dc\ub2c8", + "Puzzle.country1HelpUrl": "http://ko.wikipedia.org/wiki/\uc624\uc2a4\ud2b8\ub808\uc77c\ub9ac\uc544", + "Puzzle.country2": "\ub3c5\uc77c", + "Puzzle.country2Language": "\ub3c5\uc77c\uc5b4", + "Puzzle.country2City1": "\ubca0\ub97c\ub9b0", + "Puzzle.country2City2": "\ubb8c\ud5e8", + "Puzzle.country2HelpUrl": "http://ko.wikipedia.org/wiki/\ub3c5\uc77c", + "Puzzle.country3": "\uc911\uad6d", + "Puzzle.country3Language": "\uc911\uad6d\uc5b4", + "Puzzle.country3City1": "\ubca0\uc774\uc9d5", + "Puzzle.country3City2": "\uc0c1\ud558\uc774", + "Puzzle.country3HelpUrl": "http://ko.wikipedia.org/wiki/\uc911\ud654\uc778\ubbfc\uacf5\ud654\uad6d", + "Puzzle.country4": "\ube0c\ub77c\uc9c8", + "Puzzle.country4Language": "\ud3ec\ub974\ud22c\uac08\uc5b4", + "Puzzle.country4City1": "\ub9ac\uc6b0\ub370\uc790\ub124\uc774\ub8e8", + "Puzzle.country4City2": "\uc0c1\ud30c\uc6b8\ub8e8", + "Puzzle.country4HelpUrl": "http://ko.wikipedia.org/wiki/\ube0c\ub77c\uc9c8", + "Puzzle.flag": "\uad6d\uae30:", + "Puzzle.language": "\uc5b8\uc5b4:", + "Puzzle.languageChoose": "\uc120\ud0dd...", + "Puzzle.cities": "\ub3c4\uc2dc:", + "Puzzle.error0": "\uc644\ubcbd\ud569\ub2c8\ub2e4!\n\ubaa8\ub4e0 \ube14\ub85d %1\uac1c\uac00 \uc815\ud655\ud569\ub2c8\ub2e4.", + "Puzzle.error1": "\uac70\uc758 \ub410\uc2b5\ub2c8\ub2e4! \ube14\ub85d \ud55c \uac1c\uac00 \uc798\ubabb\ub418\uc5c8\uc2b5\ub2c8\ub2e4.", + "Puzzle.error2": "\ube14\ub85d %1\uac1c\uac00 \uc798\ubabb\ub418\uc5c8\uc2b5\ub2c8\ub2e4.", + "Puzzle.tryAgain": "\uac15\uc870\ud55c \ube14\ub85d\uc740 \uc62c\ubc14\ub974\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.\n\uacc4\uc18d \ud574\ubcf4\uc138\uc694.", + "Puzzle.title": "\ud37c\uc990", + "Puzzle.help": "\ub3c4\uc6c0\ub9d0", + "Puzzle.checkAnswers": "\uc815\ub2f5 \ud655\uc778", + "Puzzle.helpText": "\uac01 \uad6d\uac00(\ucd08\ub85d)\uc5d0 \uad6d\uae30\ub97c \uc5f0\uacb0\ud558\uace0 \uc5b8\uc5b4\ub97c \uc120\ud0dd\ud558\uc5ec \ub3c4\uc2dc\ub97c \uc815\ub82c\ud558\uc138\uc694.", + "Turtle.moveTooltip": "\uc9c0\uc815\ub41c \uc591\uc73c\ub85c \ud130\ud2c0\uc744 \uc55e\uc774\ub098 \ub4a4\ub85c \uc774\ub3d9\ud569\ub2c8\ub2e4.", + "Turtle.moveForward": "\uc55e\uc73c\ub85c \uac00\uae30", + "Turtle.moveBackward": "\ub4a4\ub85c \uac00\uae30", + "Turtle.turnTooltip": "\uc9c0\uc815\ub41c \uac01\ub3c4\ub85c \ud130\ud2c0\uc744 \uc67c\ucabd\uc774\ub098 \uc624\ub978\ucabd\uc73c\ub85c \ub3d5\ub2c8\ub2e4.", + "Turtle.turnRight": "\uc624\ub978\ucabd\uc73c\ub85c \ub3cc\uae30", + "Turtle.turnLeft": "\uc67c\ucabd\uc73c\ub85c \ub3cc\uae30", + "Turtle.widthTooltip": "\ud39c\uc758 \ub108\ube44\ub97c \ubc14\uafc9\ub2c8\ub2e4.", + "Turtle.setWidth": "\ub108\ube44 \uc124\uc815", + "Turtle.colourTooltip": "\ud39c\uc758 \uc0c9\uc744 \ubc14\uafc9\ub2c8\ub2e4.", + "Turtle.setColour": "\uc0c9 \uc124\uc815", + "Turtle.penTooltip": "\uadf8\ub9ac\uae30\ub97c \uba48\ucd94\uac70\ub098 \uc2dc\uc791\ud558\uae30 \uc704\ud574 \ud39c\uc744 \uc62c\ub9ac\uac70\ub098 \ub0b4\ub9bd\ub2c8\ub2e4.", + "Turtle.penUp": "\ud39c \uc62c\ub9ac\uae30", + "Turtle.penDown": "\ud39c \ub0b4\ub9ac\uae30", + "Turtle.turtleVisibilityTooltip": "\ud130\ud2c0(\ub3d9\uadf8\ub77c\ubbf8\uc640 \ud654\uc0b4\ud45c)\ub97c \ubcf4\uc774\uac70\ub098 \uc228\uae38 \uc218 \uc788\uc2b5\ub2c8\ub2e4.", + "Turtle.hideTurtle": "\ud130\ud2c0 \uc228\uae30\uae30", + "Turtle.showTurtle": "\ud130\ud2c0 \ubcf4\uc774\uae30", + "Turtle.printHelpUrl": "http://ko.wikipedia.org/wiki/\uc778\uc1c4", + "Turtle.printTooltip": "\ud130\ud2c0\uc758 \ubc29\ud5a5\uacfc \uc704\uce58\ub97c \ud14d\uc2a4\ud2b8\ub85c \uadf8\ub9bd\ub2c8\ub2e4.", + "Turtle.print": "\uc778\uc1c4", + "Turtle.fontHelpUrl": "http://en.wikipedia.org/wiki/Font", + "Turtle.fontTooltip": "\uc778\uc1c4 \ube14\ub85d\uc5d0\uc11c \uc0ac\uc6a9\ub418\ub294 \uae00\uaf34\uc744 \uc124\uc815\ud569\ub2c8\ub2e4.", + "Turtle.font": "\uae00\uaf34", + "Turtle.fontSize": "\uae00\uc790 \ud06c\uae30", + "Turtle.fontNormal": "\ubcf4\ud1b5", + "Turtle.fontBold": "\uad76\uac8c", + "Turtle.fontItalic": "\uae30\uc6b8\uc784", + "Turtle.unloadWarning": "\uc774 \ud398\uc774\uc9c0\ub97c \ub5a0\ub098\uba74 \uc791\uc5c5\uc744 \uc783\uac8c \ub429\ub2c8\ub2e4.", + "Turtle.title": "\ud130\ud2c0 \uadf8\ub798\ud53d", + "Turtle.runTooltip": "\ud130\ud2c0\uc774 \ub9d0\ud558\ub294 \ud589\ub3d9\uc744 \uce90\ub9ad\ud130\uac00 \ud569\ub2c8\ub2e4.", + "Turtle.captureTooltip": "\uadf8\ub9ac\uae30\ub97c \uc800\uc7a5\ud569\ub2c8\ub2e4.", + "Turtle.imgFilename": "\uadf8\ub9ac\uae30.png", + "Turtle.catTurtle": "\ud130\ud2c0" +} \ No newline at end of file diff --git a/apps/json/ksh.json b/apps/json/ksh.json new file mode 100644 index 000000000..f85d0b96c --- /dev/null +++ b/apps/json/ksh.json @@ -0,0 +1,35 @@ +{ + "Puzzle.tryAgain": "Dat eine Klözje es verkeht.\nVersöhg et norr_ens.", + "Puzzle.country3City2": "Schanghai", + "Puzzle.country3HelpUrl": "http://ksh.wikipedia.org/wiki/Schiina", + "Puzzle.country3Language": "Schineesesch", + "Puzzle.checkAnswers": "Prööve!", + "Puzzle.language": "Schprooch:", + "Apps.dialogOk": "Jebongt!", + "Puzzle.title": "Possel", + "Puzzle.country1HelpUrl": "http://ksh.wikipedia.org/wiki/Außtraalijje_(Schtaat)", + "Puzzle.languageChoose": "Söhk jäd uß...", + "Puzzle.country4City2": "São Paulo", + "Puzzle.country4City1": "Rio_de_Schaneero", + "Puzzle.country4Language": "Pochtojeesesch", + "Puzzle.helpText": "För jedes Land, en Jröhn, donn däm sing Fahn draan, söhk sing Schprooch uß, un donn däm sing Schtädt opleßte.", + "Puzzle.flag": "Fahn:", + "Puzzle.country4HelpUrl": "http://ksh.wikipedia.org/wiki/Brasiilije", + "Puzzle.error1": "Beinah! Ei Klözje es verkeeht.", + "Puzzle.country3City1": "Peeking", + "Puzzle.country1City1": "Mälbörn", + "Puzzle.country1City2": "Sydney", + "Puzzle.country2Language": "Deutsch", + "Puzzle.country3": "Schiina", + "Puzzle.country2": "Deutschland", + "Puzzle.country1": "Außtraalije", + "Puzzle.country2HelpUrl": "http://ksh.wikipedia.org/wiki/Deutschland", + "Puzzle.error0": "Supper!\nAlle %1 Klözje sin reschtesch.", + "Puzzle.country4": "Brasiilije", + "Puzzle.error2": "%1 Klözje sin verkeeht.", + "Puzzle.help": "Hölp", + "Puzzle.country1Language": "Änglesch", + "Puzzle.country2City1": "Bälliin", + "Puzzle.cities": "Schtädt:", + "Puzzle.country2City2": "Mönnsche" +} diff --git a/apps/json/ku-latn.json b/apps/json/ku-latn.json new file mode 100644 index 000000000..bba52aa6b --- /dev/null +++ b/apps/json/ku-latn.json @@ -0,0 +1,15 @@ +{ + "Puzzle.country2": "Elmanya", + "Puzzle.country1": "Awistralya", + "Puzzle.country4City2": "São Paulo", + "Puzzle.flag": "al:", + "Puzzle.help": "Alîkarî", + "Puzzle.checkAnswers": "Bersivan kontrol bike", + "Puzzle.country1Language": "Îngilîzî", + "Puzzle.country2City1": "Berlîn", + "Puzzle.languageChoose": "hilbijêre...", + "Puzzle.language": "ziman:", + "Apps.dialogOk": "Baş e", + "Puzzle.cities": "bajar:", + "Puzzle.country2Language": "Elmanî" +} diff --git a/apps/json/ky.json b/apps/json/ky.json new file mode 100644 index 000000000..23ae5a6bf --- /dev/null +++ b/apps/json/ky.json @@ -0,0 +1,35 @@ +{ + "Puzzle.tryAgain": "Белгиленген блок туура эмес жайгашкан.\nДагы аракет кылыңыз.", + "Puzzle.country3City2": "Шанхай", + "Puzzle.country3HelpUrl": "http://ky.wikipedia.org/wiki/Кытай", + "Puzzle.country3Language": "Кытайча", + "Puzzle.checkAnswers": "Жоопторду текшерүү", + "Puzzle.language": "Тили:", + "Apps.dialogOk": "OK", + "Puzzle.title": "Баш катырма.", + "Puzzle.country1HelpUrl": "http://ky.wikipedia.org/wiki/Австралия", + "Puzzle.languageChoose": "тандаңыз...", + "Puzzle.country4City2": "Сан-Паулу", + "Puzzle.country4City1": "Рио-де-Жанейро", + "Puzzle.country4Language": "Португалча", + "Puzzle.helpText": "Ар бир өлкөгө (жашыл), туусун кадаңыз, расмий тилин тандаңыз, жана ал өлкөнүн шаарларын белгилеңиз.", + "Puzzle.flag": "туу:", + "Puzzle.country4HelpUrl": "http://ky.wikipedia.org/wiki/Бразилия", + "Puzzle.error1": "Аз калды!\nБир блок гана туура эмес жайгашкан.", + "Puzzle.country3City1": "Бээжин", + "Puzzle.country1City1": "Мельбурн", + "Puzzle.country1City2": "Сидней", + "Puzzle.country2Language": "Немисче", + "Puzzle.country3": "Кытай", + "Puzzle.country2": "Германия", + "Puzzle.country1": "Австралия", + "Puzzle.country2HelpUrl": "http://ky.wikipedia.org/wiki/Германия", + "Puzzle.error0": "Мыкты!\nБардык блоктор %1 туура жайгашкан.", + "Puzzle.country4": "Бразилия", + "Puzzle.error2": "Бир нече блок (%1) туура эмес жайгашкан.", + "Puzzle.help": "Жардам", + "Puzzle.country1Language": "Англисче", + "Puzzle.country2City1": "Берлин", + "Puzzle.cities": "шаарлары:", + "Puzzle.country2City2": "Мюнхен" +} diff --git a/apps/json/la.json b/apps/json/la.json new file mode 100644 index 000000000..e24df5cf0 --- /dev/null +++ b/apps/json/la.json @@ -0,0 +1,35 @@ +{ + "Puzzle.tryAgain": "Sectio excerpta vitiosa est.", + "Puzzle.country3City2": "Sciamhaevum", + "Puzzle.country3HelpUrl": "http://la.wikipedia.org/wiki/Res_Publica_Popularis_Sinarum", + "Puzzle.country3Language": "Lingua Sinica", + "Puzzle.checkAnswers": "Responsa examinare", + "Puzzle.language": "Lingua:", + "Apps.dialogOk": "ASSENTIOR", + "Puzzle.title": "Ludus", + "Puzzle.country1HelpUrl": "http://la.wikipedia.org/wiki/Australia", + "Puzzle.languageChoose": "elige...", + "Puzzle.country4City2": "Urbs Paulistana", + "Puzzle.country4City1": "Urbs Fluminensis", + "Puzzle.country4Language": "Lingua Lusitana", + "Puzzle.helpText": "Unicuique civitati vexillum proprium adiunge, linguam elige et urbes eius indice.", + "Puzzle.flag": "vexillum:", + "Puzzle.country4HelpUrl": "http://la.wikipedia.org/wiki/Brasilia", + "Puzzle.error1": "Paene! Una sectio vitiosa est.", + "Puzzle.country3City1": "Pechinum", + "Puzzle.country1City1": "Melburnia", + "Puzzle.country1City2": "Sydneium", + "Puzzle.country2Language": "Lingua Theodisca", + "Puzzle.country3": "Sina", + "Puzzle.country2": "Germania", + "Puzzle.country1": "Australia", + "Puzzle.country2HelpUrl": "http://la.wikipedia.org/wiki/Germania", + "Puzzle.error0": "Bene!\nOmnes %1 sectiones recte solvisti.", + "Puzzle.country4": "Brasilia", + "Puzzle.error2": "%1 sectiones vitiosae sunt.", + "Puzzle.help": "Auxilium", + "Puzzle.country1Language": "Lingua Anglica", + "Puzzle.country2City1": "Berolinum", + "Puzzle.cities": "urbes:", + "Puzzle.country2City2": "Monacum" +} diff --git a/apps/json/lb.json b/apps/json/lb.json new file mode 100644 index 000000000..54fc2ed09 --- /dev/null +++ b/apps/json/lb.json @@ -0,0 +1,95 @@ +{ + "@metadata": { + "authors": [ + "Robby" + ] + }, + "Apps.codeTooltip": "Gener\u00e9ierte JavaScript Code kucken.", + "Apps.linkTooltip": "Sp\u00e4icheren a mat de Bl\u00e9ck verlinken", + "Apps.runProgram": "Programm ausf\u00e9ieren", + "Apps.resetProgram": "Zr\u00e9cksetzen", + "Apps.dialogOk": "OK", + "Apps.dialogCancel": "Ofbriechen", + "Apps.catLogic": "Logik", + "Apps.catText": "Text", + "Apps.catLists": "L\u00ebschten", + "Apps.catColour": "Faarf", + "Apps.catVariables": "Variabelen", + "Apps.catProcedures": "Prozeduren", + "Apps.httpRequestError": "Et gouf e Problem mat der Ufro.", + "Apps.hashError": "Pardon, '%1' entspr\u00e9cht kengem vun de gesp\u00e4icherte Programmer.", + "Apps.listVariable": "L\u00ebscht", + "Apps.textVariable": "Text", + "Code.badXml": "Feeler beim Parse vum XML:\n%1\n\nKlickt 'OK' fir \u00c4r \u00c4nnerungen opzeginn oder 'Ofbriechen' fir den XML weider z'\u00e4nneren.", + "Code.badCode": "Programmfeeler:\n%1", + "Code.discard": "All %1 Bl\u00e9ck l\u00e4schen?", + "Code.title": "Code", + "Code.blocks": "Bl\u00e9ck", + "Maze.moveForward": "viru goen", + "Maze.turnLeft": "no l\u00e9nks ofb\u00e9ien", + "Maze.turnRight": "no riets ofb\u00e9ien", + "Maze.doCode": "maachen", + "Maze.elseCode": "soss", + "Maze.repeatUntil": "widderhuele bis", + "Maze.capacity0": "Dir hutt %0 Bl\u00e9ck iwwreg.", + "Maze.capacity1": "Dir hutt %1 Block iwwreg.", + "Maze.capacity2": "Dir hutt %2 Bl\u00e9ck iwwreg.", + "Maze.nextLevel": "Gratulatioun! Sidd dir prett fir den Niveau %1?", + "Maze.finalLevel": "Bravo! Dir hutt de leschten Niveau gel\u00e9ist.", + "Maze.helpRun": "\u00c4re Programm starte fir ze kucke wat geschitt.", + "Plane.rows": "Reien: %1", + "Plane.getRows": "Reien (%1)", + "Plane.rows1": "1. Klass Reien: %1", + "Plane.getRows1": "1. Klass Reien (%1)", + "Plane.rows2": "2. Klass Reien: %1", + "Plane.getRows2": "2. Klass Reien (%1)", + "Plane.seats": "S\u00ebtzer: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "S\u00ebtzer =", + "Plane.plane": "Fliger", + "Plane.description1": "E Fliger huet en gew\u00ebss Zuel vu Reie mat S\u00ebtzer fir d'Passag\u00e9ier. All Rei huet v\u00e9ier S\u00ebtzer.", + "Plane.description2": "E Fliger huet zwee S\u00ebtzer am Cockpit (fir de Pilot an de Co-Pilot), an eng gew\u00ebss Zuel vu Reie mat S\u00ebtzer fir d'Passag\u00e9ier. An all Rei si v\u00e9ier S\u00ebtzer.", + "Puzzle.country1": "Australien", + "Puzzle.country1Language": "Englesch", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://lb.wikipedia.org/wiki/Australien", + "Puzzle.country2": "D\u00e4itschland", + "Puzzle.country2Language": "D\u00e4itsch", + "Puzzle.country2City1": "Berlin", + "Puzzle.country2City2": "M\u00fcnchen", + "Puzzle.country2HelpUrl": "http://lb.wikipedia.org/wiki/D\u00e4itschland", + "Puzzle.country3": "China", + "Puzzle.country3Language": "Chinesesch", + "Puzzle.country3City1": "Peking", + "Puzzle.country3City2": "Shanghai", + "Puzzle.country3HelpUrl": "http://lb.wikipedia.org/wiki/China", + "Puzzle.country4": "Brasilien", + "Puzzle.country4Language": "Portugisesch", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "S\u00e3o Paulo", + "Puzzle.country4HelpUrl": "http://lb.wikipedia.org/wiki/Brasilien", + "Puzzle.flag": "F\u00e4ndel:", + "Puzzle.language": "Sprooch:", + "Puzzle.languageChoose": "eraussichen...", + "Puzzle.cities": "Stied:", + "Puzzle.error0": "Perfekt!\nAll %1 Blocke si korrekt.", + "Puzzle.error1": "Bal! Just ee Block ass net richteg.", + "Puzzle.error2": "%1 Bl\u00e9ck si falsch.", + "Puzzle.title": "Puzzle", + "Puzzle.help": "H\u00ebllef", + "Puzzle.checkAnswers": "\u00c4ntwerten nokucken", + "Puzzle.helpText": "Fir all Land (gr\u00e9ng), setzt de F\u00e4ndel derb\u00e4i, sicht seng Sprooch eraus a maacht e Koup mat senge Stied.", + "Turtle.turnLeft": "no lenks dr\u00e9inen \u00ebm", + "Turtle.colourTooltip": "\u00c4nnert d'Faarf vum Bic.", + "Turtle.setColour": "d'Faarf \u00e4nneren op", + "Turtle.hideTurtle": "Deckelsmouk verstoppen", + "Turtle.showTurtle": "Deckelsmouk weisen", + "Turtle.print": "dr\u00e9cken", + "Turtle.font": "Schr\u00ebftart", + "Turtle.fontNormal": "normal", + "Turtle.fontBold": "fett", + "Turtle.unloadWarning": "Wann Dir vun d\u00ebser S\u00e4it erof gitt verl\u00e9iert Dir \u00c4r Aarbecht.", + "Turtle.captureTooltip": "Zeechnung sp\u00e4icheren.", + "Turtle.catTurtle": "Deckelsmouk" +} \ No newline at end of file diff --git a/apps/json/lt.json b/apps/json/lt.json new file mode 100644 index 000000000..76d04bfa6 --- /dev/null +++ b/apps/json/lt.json @@ -0,0 +1,89 @@ +{ + "@metadata": { + "authors": [ + "Eitvys200", + "Vilius2001" + ] + }, + "Apps.blocklyMessage": "Blockly", + "Apps.runProgram": "Paleisti Program\u0105", + "Apps.resetProgram": "Atnaujinti", + "Apps.dialogOk": "Gerai", + "Apps.dialogCancel": "At\u0161aukti", + "Apps.catLogic": "Logika", + "Apps.catMath": "Matematika", + "Apps.catText": "Tekstas", + "Apps.catLists": "S\u0105ra\u0161ai", + "Apps.catColour": "Spalva", + "Apps.catVariables": "Kintamieji", + "Apps.catProcedures": "Proced\u016bros", + "Apps.httpRequestError": "I\u0161kilo problema su pra\u0161ymu.", + "Apps.listVariable": "s\u0105ra\u0161as", + "Apps.textVariable": "tekstas", + "Code.badCode": "Programos klaida:\n%1", + "Code.title": "Kodas", + "Code.blocks": "Blokai", + "Code.trashTooltip": "Pa\u0161alinti visus blokus.", + "Maze.moveForward": "jud\u0117ti \u012f priek\u012f", + "Maze.turnLeft": "Suk \u012f kair\u0119", + "Maze.turnRight": "Suk \u012f de\u0161in\u0119", + "Maze.doCode": "daryti", + "Maze.elseCode": "kitas", + "Maze.repeatUntil": "kartoti iki", + "Maze.maze": "Labirintas", + "Plane.rows": "Eilut\u0117s: %1", + "Plane.getRows": "eilut\u0117s (%1)", + "Plane.seats": "Vietos: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "Vietos =", + "Plane.plane": "L\u0117ktuvas", + "Puzzle.country1": "Australija", + "Puzzle.country1Language": "Angl\u0173", + "Puzzle.country1City1": "Melburnas", + "Puzzle.country1City2": "Sidn\u0117jus", + "Puzzle.country1HelpUrl": "http://en.wikipedia.org/wiki/Australia", + "Puzzle.country2": "Vokietija", + "Puzzle.country2Language": "Vokietijos", + "Puzzle.country2City1": "Berlynas", + "Puzzle.country2City2": "Miunchenas", + "Puzzle.country2HelpUrl": "http://en.wikipedia.org/wiki/Germany", + "Puzzle.country3": "Kinija", + "Puzzle.country3Language": "Kin\u0173", + "Puzzle.country3City1": "Pekinas", + "Puzzle.country3City2": "\u0160anchajus", + "Puzzle.country3HelpUrl": "http://en.wikipedia.org/wiki/China", + "Puzzle.country4": "Brazilija", + "Puzzle.country4Language": "Portugal\u0173", + "Puzzle.country4City1": "Rio de \u017daneiras", + "Puzzle.country4City2": "San Paulas", + "Puzzle.country4HelpUrl": "http://en.wikipedia.org/wiki/Brazil", + "Puzzle.flag": "v\u0117liava:", + "Puzzle.language": "kalba:", + "Puzzle.languageChoose": "pasirinkti...", + "Puzzle.cities": "miestai:", + "Puzzle.error0": "Puiku!\nVisi %1 blokai yra teisingi.", + "Puzzle.error1": "Beveik! Vienas blokas yra neteisingas.", + "Puzzle.error2": "%1 blokai yra neteisingi.", + "Puzzle.tryAgain": "Pary\u0161kintas blokas n\u0117ra teisingas.\nToliau bandykite.", + "Puzzle.title": "Galvos\u016bkis", + "Puzzle.help": "Pagalba", + "Puzzle.checkAnswers": "Patikrinti Atsakymus", + "Puzzle.helpText": "Kiekvienai \u0161aliai (\u017ealia), prid\u0117kite v\u0117liav\u0105, pasirinkite savo kalb\u0105, ir padarykite savo miest\u0173 kamin\u0105.", + "Turtle.setWidth": "nustatyti plot\u012f", + "Turtle.setColour": "nustatyti spalv\u0105", + "Turtle.hideTurtle": "sl\u0117pti v\u0117\u017el\u012f", + "Turtle.showTurtle": "rodyti v\u0117\u017el\u012f", + "Turtle.printHelpUrl": "http://en.wikipedia.org/wiki/Printing", + "Turtle.print": "spausdinti", + "Turtle.fontHelpUrl": "http://en.wikipedia.org/wiki/Font", + "Turtle.font": "\u0161riftas", + "Turtle.fontSize": "\u0161rifto dydis", + "Turtle.fontNormal": "normalus", + "Turtle.fontBold": "pary\u0161kinti", + "Turtle.fontItalic": "pasvirasis", + "Turtle.unloadWarning": "Paliekant \u0161\u012f puslap\u012f jus prarasite savo darb\u0105.", + "Turtle.title": "V\u0117\u017elio Grafika", + "Turtle.captureTooltip": "I\u0161saugoti prie\u0161in\u012f.", + "Turtle.imgFilename": "drawing.png", + "Turtle.catTurtle": "V\u0117\u017elys" +} \ No newline at end of file diff --git a/apps/json/lv.json b/apps/json/lv.json new file mode 100644 index 000000000..186490968 --- /dev/null +++ b/apps/json/lv.json @@ -0,0 +1,115 @@ +{ + "@metadata": { + "authors": [ + "Elomage", + "Papuass" + ] + }, + "Apps.subtitle": "vizu\u0101la programm\u0113\u0161anas vide", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Apskat\u012bt \u0123ener\u0113to JavaScript pirmkodu.", + "Apps.linkTooltip": "Saglam\u0101t un piesaist\u012bt blokiem.", + "Apps.runTooltip": "Palaidiet programmu, ko defin\u0113 bloki darbviet\u0101.", + "Apps.runProgram": "Izpild\u012bt programmu", + "Apps.resetProgram": "S\u0101kt no s\u0101kuma", + "Apps.dialogOk": "Labi", + "Apps.dialogCancel": "Atcelt", + "Apps.catLogic": "Lo\u0123ika", + "Apps.catLoops": "Cikli", + "Apps.catMath": "Matem\u0101tika", + "Apps.catText": "Teksts", + "Apps.catLists": "Saraksti", + "Apps.catColour": "Kr\u0101sa", + "Apps.catVariables": "Main\u012bgie", + "Apps.catProcedures": "Proced\u016bras", + "Apps.httpRequestError": "Piepras\u012bjuma k\u013c\u016bda.", + "Apps.linkAlert": "Dalies ar saviem blokiem ar \u0161o saiti:\n\n%1", + "Apps.hashError": "Atvainojiet, bet '%1' neatbilst nevienai no saglab\u0101taj\u0101m programm\u0101m.", + "Apps.xmlError": "Nevaru iel\u0101d\u0113t tavu saglab\u0101to failu. Iesp\u0113jams, tas tika izveidots ar citu Blockly versiju?", + "Apps.listVariable": "saraksts", + "Apps.textVariable": "teksts", + "Code.badXml": "XML pars\u0113\u0161anas k\u013c\u016bda:\n %1\n\nIzv\u0113lieties 'Labi', lai zaud\u0113tu savas izmai\u0146as vai 'Atcelt', lai redi\u0123\u0113tu XML.", + "Code.badCode": "Programmas k\u013c\u016bda:\n %1", + "Code.timeout": "P\u0101rsniegts maksim\u0101lais iter\u0101ciju skaits.", + "Code.discard": "Vai izdz\u0113st visus %1 blokus?", + "Code.title": "Pirmkods", + "Code.blocks": "Bloki", + "Code.trashTooltip": "Izmest visus blokus.", + "Graph.title": "Grafiku kalkulators", + "Maze.moveForward": "ej uz priek\u0161u", + "Maze.turnLeft": "pagriezies pa kreisi", + "Maze.turnRight": "pagriezies pa labi", + "Maze.doCode": "dari", + "Maze.elseCode": "cit\u0101di", + "Maze.helpIfElse": "P\u0101rbaudes komandas 'ja-cit\u0101di' izpild\u012bs vai nu vienu, vai otru bloku atkar\u012bb\u0101 no p\u0101rbaudes.", + "Maze.pathAhead": "ja priek\u0161\u0101 ir br\u012bvs ce\u013c\u0161", + "Maze.pathLeft": "ja pa kreisi ir br\u012bvs ce\u013c\u0161", + "Maze.pathRight": "ja pa labi ir br\u012bvs ce\u013c\u0161", + "Maze.repeatUntil": "atk\u0101rto tikm\u0113r kam\u0113r", + "Maze.moveForwardTooltip": "P\u0101rvieto cilv\u0113ci\u0146u uz priek\u0161u par vienu soli.", + "Maze.turnTooltip": "P\u0101rvieto cilv\u0113ci\u0146u pa kreisi vai pa labi par 90 gr\u0101diem.", + "Maze.ifTooltip": "Ja attiec\u012bgaj\u0101 virzien\u0101 ir br\u012bvs ce\u013c\u0161, tad izpild\u012bt attiec\u012bg\u0101s darb\u012bbas.", + "Maze.ifelseTooltip": "Ja attiec\u012bgaj\u0101 virzien\u0101 ir br\u012bvs ce\u013c\u0161, tad izpild\u012bt pirmo bloku ar darb\u012bb\u0101m. Cit\u0101di izpild\u012bt otro bloku ar darb\u012bb\u0101m.", + "Maze.whileTooltip": "Atk\u0101rtot iek\u013caut\u0101s darb\u012bbas kam\u0113r sasniegts m\u0113r\u0137is.", + "Maze.capacity0": "Tev atliku\u0161i %0 bloki.", + "Maze.capacity1": "Tev atlicis %1 bloks.", + "Maze.capacity2": "Tev atliku\u0161i %2 bloki.", + "Maze.nextLevel": "Apsveicu! Vai esi gatavs turpin\u0101t ar %1 l\u012bmeni?", + "Maze.finalLevel": "Apsveicu! Tu esi atrisin\u0101jis p\u0113d\u0113jo l\u012bmeni.", + "Maze.maze": "Labirints", + "Maze.runTooltip": "Liek sp\u0113l\u0113t\u0101jam dar\u012bt to, ko saka bloki.", + "Maze.resetTooltip": "Novietot sp\u0113l\u0113t\u0101ju atpaka\u013c labirinta s\u0101kum\u0101.", + "Maze.helpStack": "Saliec kop\u0101 da\u017eus 'ej uz priek\u0161u' blokus lai m\u0113s var\u0113tu sasniegt m\u0113r\u0137i.", + "Maze.helpOneTopBlock": "\u0160aj\u0101 l\u012bmen\u012b tev bloki j\u0101saliek kop\u0101 baltaj\u0101 laumum\u0101.", + "Maze.helpRun": "Palaidiet programmu, lai redz\u0113tu, kas notiek.", + "Maze.helpReset": "J\u016bsu programma neatrisin\u0101ja labirintu. Nospiediet 'Ats\u0101kt' un m\u0113\u0123iniet v\u0113lreiz.", + "Maze.helpRepeat": "Datoriem ir ierobe\u017eota atmi\u0146a. Sasniedz ce\u013ca m\u0113r\u0137i lietojot tikai divus blokus. Lieto atk\u0101rto\u0161anas bloku lai var\u0113tu izpild\u012bt darb\u012bbu vair\u0101k k\u0101 vienu reizi.", + "Maze.helpCapacity": "J\u016bs esat izmantojis visus blokus \u0161aj\u0101 l\u012bmeni. Lai izveidotu jaunu bloku, jums vispirms nepiecie\u0161ams izmest k\u0101du eso\u0161u bloku.", + "Maze.helpRepeatMany": "J\u016bs varat ievietot vair\u0101k nek\u0101 vienu bloku \"atk\u0101rtot\" bloka iek\u0161pus\u0113.", + "Maze.helpSkins": "Izv\u0113l\u0113ties j\u016bsu iecien\u012bt\u0101ko sp\u0113l\u0113t\u0101ju no \u0161\u012bs izv\u0113lnes.", + "Maze.helpIf": "P\u0101rbaudes komanda 'ja' dara kaut ko tikai tad, ja p\u0101rbaude ir patiesa. Pam\u0113\u0123ini pagriezties pa kreisi, ja pa kreisi ir br\u012bvs ce\u013c\u0161.", + "Maze.helpMenu": "Noklik\u0161\u0137iniet uz %1 \"ja\" blok\u0101 lai main\u012btu t\u0101 nosac\u012bjumu.", + "Maze.helpWallFollow": "Vai tu vari atrisin\u0101t \u0161o sare\u017e\u0123\u012bto labirintu? M\u0113\u0123ini sekot sienai kreisaj\u0101 pus\u0113. \u0160is ir pieredz\u0113ju\u0161iem programm\u0113t\u0101jiem!", + "Plane.rows": "Rindas: %1", + "Plane.getRows": "rindas (%1)", + "Plane.rows1": "Pirm\u0101s klases rindas: %1", + "Plane.getRows1": "Pirm\u0101s klases rindas (%1)", + "Plane.rows2": "Otr\u0101s klases rindas: %1", + "Plane.getRows2": "Otr\u0101s klases rindas (%1)", + "Plane.seats": "S\u0113dvietas: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "s\u0113dvietas =", + "Plane.plane": "Lidma\u0161\u012bna", + "Puzzle.country1": "Austr\u0101lija", + "Puzzle.country1Language": "Ang\u013cu", + "Puzzle.country1City1": "Melburna", + "Puzzle.country1City2": "Sidneja", + "Puzzle.country1HelpUrl": "http://lv.wikipedia.org/wiki/Austr\u0101lija", + "Puzzle.country2": "V\u0101cija", + "Puzzle.country2Language": "V\u0101cu", + "Puzzle.country2City1": "Berl\u012bne", + "Puzzle.country2City2": "Minhene", + "Puzzle.country2HelpUrl": "http://en.wikipedia.org/wiki/Germany", + "Puzzle.country3": "\u0136\u012bna", + "Puzzle.country3Language": "\u0136\u012bnie\u0161u", + "Puzzle.country3City1": "Pekina", + "Puzzle.country3City2": "\u0160anhaja", + "Puzzle.country3HelpUrl": "http://en.wikipedia.org/wiki/China", + "Puzzle.country4": "Braz\u012blija", + "Puzzle.country4Language": "Portug\u0101\u013cu", + "Puzzle.country4City1": "Riode\u017eaneiro", + "Puzzle.country4City2": "Sanpaulu", + "Puzzle.country4HelpUrl": "http://lv.wikipedia.org/wiki/Braz\u012blija", + "Puzzle.flag": "karogs:", + "Puzzle.language": "valoda:", + "Puzzle.languageChoose": "izv\u0113lies...", + "Puzzle.cities": "pils\u0113tas:", + "Puzzle.error0": "Lieliski!\nVisi %1 bloki ir pareizi.", + "Puzzle.error1": "Gandr\u012bz! Viens bloks nav pareizs.", + "Puzzle.error2": "%1 bloki nav pareizi.", + "Puzzle.tryAgain": "Iez\u012bm\u0113tais bloks nav pareizs.\nM\u0113\u0123ini v\u0113l.", + "Puzzle.title": "Saliekamatt\u0113ls", + "Puzzle.help": "Pal\u012bdz\u012bba", + "Puzzle.checkAnswers": "P\u0101rbaud\u012bt atbildes", + "Puzzle.helpText": "Katrai valstij (za\u013cas), pievieno t\u0101s karogu, izv\u0113lies t\u0101s valodu un saliec t\u0101s pils\u0113tas stabi\u0146\u0101." +} \ No newline at end of file diff --git a/apps/json/mk.json b/apps/json/mk.json new file mode 100644 index 000000000..64b91d7d7 --- /dev/null +++ b/apps/json/mk.json @@ -0,0 +1,151 @@ +{ + "@metadata": { + "authors": [ + "Bjankuloski06", + "M4r51n" + ] + }, + "Apps.subtitle": "\u0432\u0438\u0437\u0443\u0435\u043b\u043d\u0430 \u043e\u043a\u043e\u043b\u0438\u043d\u0430 \u0437\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438\u0440\u0430\u045a\u0435", + "Apps.blocklyMessage": "\u0411\u043b\u043e\u043a\u043b\u0438", + "Apps.codeTooltip": "\u041f\u043e\u0433\u043b. \u0441\u043e\u0437\u0434\u0430\u0434\u0435\u043d\u0438\u043e\u0442 JavaScript-\u043a\u043e\u0434.", + "Apps.linkTooltip": "\u0417\u0430\u0447\u0443\u0432\u0430\u0458 \u0438 \u0441\u0442\u0430\u0432\u0438 \u0432\u0440\u0441\u043a\u0430 \u0434\u043e \u0431\u043b\u043e\u043a\u0447\u0438\u045a\u0430\u0442\u0430.", + "Apps.runTooltip": "\u041f\u0443\u0448\u0442\u0438 \u0433\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043e\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d \u043e\u0434 \u0431\u043b\u043e\u043a\u0447\u0438\u045a\u0430\u0442\u0430 \u0432\u043e \u0440\u0430\u0431\u043e\u0442\u043d\u0438\u043e\u0442 \u043f\u0440\u043e\u0441\u0442\u043e\u0440.", + "Apps.runProgram": "\u041f\u0443\u0448\u0442\u0438 \u0433\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043e\u0442", + "Apps.resetProgram": "\u041e\u0434\u043d\u043e\u0432\u043e", + "Apps.dialogOk": "\u041e\u041a", + "Apps.dialogCancel": "\u041e\u0442\u043a\u0430\u0436\u0438", + "Apps.catLogic": "\u041b\u043e\u0433\u0438\u043a\u0430", + "Apps.catLoops": "\u0408\u0430\u043c\u043a\u0438", + "Apps.catMath": "\u041c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0430", + "Apps.catText": "\u0422\u0435\u043a\u0441\u0442", + "Apps.catLists": "\u0421\u043f\u0438\u0441\u043e\u0446\u0438", + "Apps.catColour": "\u0411\u043e\u0458\u0430", + "Apps.catVariables": "\u041f\u0440\u043e\u043c\u0435\u043d\u043b\u0438\u0432\u0438", + "Apps.catProcedures": "\u041f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0438", + "Apps.httpRequestError": "\u0421\u0435 \u043f\u043e\u0458\u0430\u0432\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0432\u043e \u0431\u0430\u0440\u0430\u045a\u0435\u0442\u043e.", + "Apps.linkAlert": "\u0421\u043f\u043e\u0434\u0435\u043b\u0435\u0442\u0435 \u0433\u0438 \u0432\u0430\u0448\u0438\u0442\u0435 \u0431\u043b\u043e\u043a\u0447\u0438\u045a\u0430 \u0441\u043e \u043e\u0432\u0430\u0430 \u0432\u0440\u0441\u043a\u0430:\n\n%1", + "Apps.hashError": "\u201e%1\u201c \u043d\u0435 \u043e\u0434\u0433\u043e\u0432\u0430\u0440\u0430 \u043d\u0430 \u043d\u0438\u0435\u0434\u0435\u043d \u0437\u0430\u0447\u0443\u0432\u0430\u043d \u043f\u0440\u043e\u0433\u0440\u0430\u043c.", + "Apps.xmlError": "\u041d\u0435 \u043c\u043e\u0436\u0435\u0432 \u0434\u0430 \u0458\u0430 \u0432\u0447\u0438\u0442\u0430\u043c \u0437\u0430\u0447\u0443\u0432\u0430\u043d\u0430\u0442\u0430 \u043f\u043e\u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430. \u0414\u0430 \u043d\u0435 \u0441\u0442\u0435 \u0458\u0430 \u0441\u043e\u0437\u0434\u0430\u043b\u0435 \u0441\u043e \u0434\u0440\u0443\u0433\u0430 \u0432\u0435\u0440\u0437\u0438\u0458\u0430 \u043d\u0430 Blockly?", + "Apps.listVariable": "\u0441\u043f\u0438\u0441\u043e\u043a", + "Apps.textVariable": "\u0442\u0435\u043a\u0441\u0442", + "Code.badXml": "\u0413\u0440\u0435\u0448\u043a\u0430 \u043f\u0440\u0438 \u043f\u0430\u0440\u0441\u0438\u0440\u0430\u045a\u0435\u0442\u043e \u043d\u0430 XML:\n%1\n\n\u0421\u0442\u0438\u0441\u043d\u0435\u0442\u0435 \u043d\u0430 \u201e\u041e\u041a\u201c \u0437\u0430 \u0434\u0430 \u0433\u0438 \u043d\u0430\u043f\u0443\u0448\u0442\u0438\u0442\u0435 \u043f\u0440\u043e\u043c\u0435\u043d\u0438\u0442\u0435 \u0438\u043b\u0438 \u043d\u0430 \u201e\u041e\u0442\u043a\u0430\u0436\u0438\u201c \u0430\u043a\u043e \u0441\u0430\u043a\u0430\u0442\u0435 \u0443\u0448\u0442\u0435 \u0434\u0430 \u0458\u0430 \u0443\u0440\u0435\u0434\u0443\u0432\u0430\u0442\u0435 XML-\u043f\u043e\u0434\u0430\u0442\u043e\u0442\u0435\u043a\u0430\u0442\u0430.", + "Code.badCode": "\u0413\u0440\u0435\u0448\u043a\u0430 \u0432\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043e\u0442:\n%1", + "Code.timeout": "\u0413\u043e \u043d\u0430\u0434\u043c\u0438\u043d\u0430\u0432\u0442\u0435 \u0434\u043e\u043f\u0443\u0448\u0442\u0435\u043d\u0438\u043e\u0442 \u0431\u0440\u043e\u0458 \u043d\u0430 \u043f\u043e\u0432\u0442\u043e\u0440\u0443\u0432\u0430\u045a\u0430 \u0432\u043e \u0438\u0437\u0432\u0440\u0448\u0443\u0432\u0430\u045a\u0435\u0442\u043e.", + "Code.discard": "\u0414\u0430 \u0433\u0438 \u0438\u0437\u0431\u0440\u0438\u0448\u0430\u043c \u0441\u0438\u0442\u0435 %1 \u0431\u043b\u043e\u043a\u0447\u0438\u045a\u0430?", + "Code.title": "\u041a\u043e\u0434", + "Code.blocks": "\u0411\u043b\u043e\u043a\u0447\u0438\u045a\u0430", + "Code.trashTooltip": "\u041e\u0442\u0441\u0442\u0440\u0430\u043d\u0438 \u0433\u0438 \u0441\u0438\u0442\u0435 \u0431\u043b\u043e\u043a\u0447\u0438\u045a\u0430.", + "Graph.title": "\u0413\u0440\u0430\u0444\u0438\u0447\u043a\u0438 \u0434\u0438\u0433\u0438\u0442\u0440\u043e\u043d", + "Maze.moveForward": "\u043c\u0440\u0434\u043d\u0438 \u043d\u0430\u043f\u0440\u0435\u0434", + "Maze.turnLeft": "\u0441\u0432\u0440\u0442\u0438 \u043b\u0435\u0432\u043e", + "Maze.turnRight": "\u0441\u0432\u0440\u0442\u0438 \u0434\u0435\u0441\u043d\u043e", + "Maze.doCode": "\u0438\u0437\u0432\u0435\u0434\u0438", + "Maze.elseCode": "\u0438\u043d\u0430\u043a\u0443", + "Maze.helpIfElse": "\u0411\u043b\u043e\u043a\u0447\u0438\u045a\u0430\u0442\u0430 \u201e\u0430\u043a\u043e-\u0442\u043e\u0433\u0430\u0448\u201c \u045c\u0435 \u0438\u0437\u0432\u0440\u0448\u0430\u0442 \u0438\u043b\u0438 \u0435\u0434\u043d\u043e \u043d\u0435\u0448\u0442\u043e \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u043e.", + "Maze.pathAhead": "\u0430\u043a\u043e \u0438\u043c\u0430 \u043f\u0430\u0442 \u043d\u0430\u043f\u0440\u0435\u0434", + "Maze.pathLeft": "\u0430\u043a\u043e \u0438\u043c\u0430 \u043f\u0430\u0442 \u043b\u0435\u0432\u043e", + "Maze.pathRight": "\u0430\u043a\u043e \u0438\u043c\u0430 \u043f\u0430\u0442 \u0434\u0435\u0441\u043d\u043e", + "Maze.repeatUntil": "\u043f\u043e\u0432\u0442\u043e\u0440\u0443\u0432\u0430\u0458 \u0441\u00e8 \u0434\u043e", + "Maze.moveForwardTooltip": "\u0413\u043e \u043c\u0440\u0434\u043d\u0443\u0432\u0430 \u0438\u0433\u0440\u0430\u0447\u043e\u0442 \u043d\u0430\u043f\u0440\u0435\u0434 \u0437\u0430 \u0435\u0434\u043d\u043e \u043c\u0435\u0441\u0442\u043e.", + "Maze.turnTooltip": "\u0413\u043e \u0441\u0432\u0440\u0442\u0443\u0432\u0430 \u0438\u0433\u0440\u0430\u0447\u043e\u0442 \u043d\u0430 \u043b\u0435\u0432\u043e \u0438\u043b\u0438 \u043d\u0430 \u0434\u0435\u0441\u043d\u043e \u0437\u0430 90 \u0441\u0442\u0435\u043f\u0435\u043d\u0438.", + "Maze.ifTooltip": "\u0410\u043a\u043e \u043f\u043e\u0441\u0442\u043e\u0438 \u043f\u0430\u0442\u0435\u043a\u0430 \u0432\u043e \u0437\u0430\u0434\u0430\u0434\u0435\u043d\u0430\u0442\u0430 \u043d\u0430\u0441\u043e\u043a\u0430, \u0442\u043e\u0433\u0430\u0448 \u0438\u0437\u0432\u0440\u0448\u0438 \u043d\u0435\u043a\u043e\u0438 \u0434\u0435\u0458\u0441\u0442\u0432\u0430.", + "Maze.ifelseTooltip": "\u0410\u043a\u043e \u043f\u043e\u0441\u0442\u043e\u0438 \u043f\u0430\u0442\u0435\u043a\u0430 \u0432\u043e \u0437\u0430\u0434\u0430\u0434\u0435\u043d\u0430\u0442\u0430 \u043d\u0430\u0441\u043e\u043a\u0430, \u0442\u043e\u0433\u0430\u0448 \u0438\u0437\u0432\u0440\u0448\u0438 \u0433\u043e \u043f\u0440\u0432\u0438\u043e\u0442 \u0431\u043b\u043e\u043a \u0434\u0435\u0458\u0441\u0442\u0432\u0430. \u0412\u043e \u0441\u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e, \u0438\u0437\u0432\u0440\u0448\u0438 \u0433\u043e \u0432\u0442\u043e\u0440\u0438\u043e\u0442.", + "Maze.whileTooltip": "\u041f\u043e\u0432\u0442\u043e\u0440\u0443\u0432\u0430\u0458 \u0433\u0438 \u0437\u0430\u0434\u0430\u0434\u0435\u043d\u0438\u0442\u0435 \u0434\u0435\u0458\u0441\u0442\u0432\u0430 \u0434\u043e\u0434\u0435\u043a\u0430 \u0434\u043e\u0458\u0434\u0435\u0448 \u0434\u043e \u0446\u0435\u043b\u0442\u0430 (\u043a\u0440\u0430\u0458\u043e\u0442).", + "Maze.capacity0": "\u0412\u0438 \u043f\u0440\u0435\u043e\u0441\u0442\u0430\u043d\u0443\u0432\u0430\u0430\u0442 %0 \u0431\u043b\u043e\u043a\u0447\u0438\u045a\u0430.", + "Maze.capacity1": "\u0412\u0438 \u043f\u0440\u0435\u043e\u0441\u0442\u0430\u043d\u0443\u0432\u0430 %1 \u0431\u043b\u043e\u043a\u0447\u0435.", + "Maze.capacity2": "\u0418\u043c\u0430\u0442\u0435 \u0443\u0448\u0442\u0435 %2 \u0431\u043b\u043e\u043a\u0447\u0438\u045a\u0430.", + "Maze.nextLevel": "\u0427\u0435\u0441\u0442\u0438\u0442\u0430\u043c\u0435! \u0414\u0430\u043b\u0438 \u0441\u0442\u0435 \u0434\u0430 \u043f\u0440\u0435\u043c\u0438\u043d\u0435\u0442\u0435 \u043d\u0430 \u041d\u0438\u0432\u043e %1?", + "Maze.finalLevel": "\u0427\u0435\u0441\u0442\u0438\u0442\u0430\u043c\u0435! \u0413\u043e \u0440\u0435\u0448\u0438\u0432\u0442\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u043e\u0442\u043e \u043d\u0438\u0432\u043e.", + "Maze.maze": "\u041b\u0430\u0432\u0438\u0440\u0438\u043d\u0442", + "Maze.runTooltip": "\u041c\u0443 \u043a\u0430\u0436\u0443\u0432\u0430 \u043d\u0430 \u0438\u0433\u0440\u0430\u0447\u043e\u0442 \u0434\u0430 \u043f\u0440\u0430\u0432\u0438 \u043a\u0430\u043a\u043e \u0448\u0442\u043e \u0432\u0435\u043b\u0430\u0442 \u0431\u043b\u043e\u043a\u0447\u0438\u045a\u0430\u0442\u0430.", + "Maze.resetTooltip": "\u0412\u0440\u0430\u0442\u0438 \u0433\u043e \u0438\u0433\u0440\u0430\u0447\u043e\u0442 \u043d\u0430 \u043f\u043e\u0447\u0435\u0442\u043e\u043a\u043e\u0442 \u043e\u0434 \u043b\u0430\u0432\u0438\u0440\u0438\u043d\u0442\u043e\u0442.", + "Maze.helpStack": "\u041d\u0430\u0440\u0435\u0434\u0435\u0442\u0435 \u0434\u0432\u0435 \u0431\u043b\u043e\u043a\u0447\u0438\u045a\u0430 \u201e\u043e\u0434\u0438 \u043d\u0430\u043f\u0440\u0435\u0434\u201c \u0437\u0430 \u0434\u0430 \u043c\u0438 \u043f\u043e\u043c\u043e\u0433\u043d\u0435\u0442\u0435 \u0434\u0430 \u0434\u043e\u0458\u0434\u0430\u043c \u0434\u043e \u0446\u0435\u043b\u0442\u0430.", + "Maze.helpOneTopBlock": "\u041d\u0430 \u043e\u0432\u0430 \u043d\u0438\u0432\u043e \u045c\u0435 \u0442\u0440\u0435\u0431\u0430 \u0434\u0430 \u0433\u0438 \u043d\u0430\u0440\u0435\u0434\u0438\u0442\u0435 \u0441\u0438\u0442\u0435 \u0431\u043b\u043e\u043a\u0447\u0438\u045a\u0430 \u0432\u043e \u0431\u0435\u043b\u0438\u043e\u0442 \u0440\u0430\u0431\u043e\u0442\u0435\u043d \u043f\u0440\u043e\u0441\u0442\u043e\u0440.", + "Maze.helpRun": "\u041f\u0443\u0448\u0442\u0435\u0442\u0435 \u0433\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043e\u0442 \u0438 \u0431\u0438\u0434\u0435\u0442\u0435 \u0448\u0442\u043e \u045c\u0435 \u0441\u0435 \u0441\u043b\u0443\u0447\u0438.", + "Maze.helpReset": "\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043e\u0442 \u043d\u0435 \u0433\u043e \u0440\u0435\u0448\u0438 \u043b\u0430\u0432\u0438\u0440\u0438\u043d\u0442\u043e\u0442. \u0421\u0442\u0438\u0441\u043d\u0435\u0442\u0435 \u201e\u041e\u0434\u043d\u043e\u0432\u043e\u201c \u0437\u0430 \u0434\u0430 \u0441\u0435 \u043e\u0431\u0438\u0434\u0435\u0442\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e.", + "Maze.helpRepeat": "\u0421\u043c\u0435\u0442\u0430\u0447\u0438\u0442\u0435 \u0438\u043c\u0430\u0430\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430 \u043c\u0435\u043c\u043e\u0440\u0438\u0458\u0430. \u0414\u043e\u0458\u0434\u0435\u0442\u0435 \u0434\u043e \u043a\u0440\u0430\u0458\u043e\u0442 \u043d\u0430 \u0441\u043e \u043f\u043e\u043c\u043e\u0448 \u043d\u0430 \u0441\u0430\u043c\u043e \u0434\u0432\u0430 \u0431\u043b\u043e\u043a\u0430. \u041f\u043e\u0441\u043b\u0443\u0436\u0435\u0442\u0435 \u0441\u0435 \u0441\u043e \u201e\u043f\u043e\u0432\u0442\u043e\u0440\u0438\u201c \u0437\u0430 \u0434\u0430 \u043f\u0443\u0448\u0442\u0438\u0442\u0435 \u0435\u0434\u043d\u043e \u0431\u043b\u043e\u043a\u0447\u0435 \u043f\u043e\u0432\u0435\u045c\u0435 \u043f\u0430\u0442\u0438.", + "Maze.helpCapacity": "\u0413\u0438 \u0438\u0441\u043a\u043e\u0440\u0438\u0441\u0442\u0438\u0432\u0442\u0435 \u0441\u0438\u0442\u0435 \u0431\u043b\u043e\u043a\u0447\u0438\u045a\u0430 \u0437\u0430 \u043e\u0432\u0430 \u043d\u0438\u0432\u043e. \u0417\u0430 \u0434\u0430 \u043d\u0430\u043f\u0440\u0430\u0432\u0438\u0442\u0435 \u043d\u043e\u0432\u043e \u0431\u043b\u043e\u043a\u0447\u0435, \u045c\u0435 \u0442\u0440\u0435\u0431\u0430 \u043f\u0440\u0432\u043e \u0434\u0430 \u0438\u0437\u0431\u0440\u0438\u0448\u0435\u0442\u0435 \u043d\u0435\u043a\u043e\u0435 \u043f\u043e\u0441\u0442\u043e\u0435\u0447\u043a\u043e.", + "Maze.helpRepeatMany": "\u041c\u043e\u0436\u0435\u0442\u0435 \u0434\u0430 \u0441\u0442\u0430\u0432\u0438\u0442\u0435 \u043f\u043e\u0432\u0435\u045c\u0435 \u043e\u0434 \u0435\u0434\u043d\u043e \u0431\u043b\u043e\u043a\u0447\u0435 \u0432\u043e \u0441\u0435\u043a\u043e\u0435 \u0431\u043b\u043e\u043a\u0447\u0435 \u201e\u043f\u043e\u0432\u0442\u043e\u0440\u0438\u201c", + "Maze.helpSkins": "\u0418\u0437\u0431\u0435\u0440\u0435\u0442\u0435 \u0433\u043e \u0432\u0430\u0448\u0438\u043e\u0442 \u043e\u043c\u0438\u043b\u0435\u043d \u0438\u0433\u0440\u0430\u0447 \u043e\u0434 \u043c\u0435\u043d\u0438\u0442\u043e.", + "Maze.helpIf": "\u0411\u043b\u043e\u043a\u0447\u0435\u0442\u043e \u201e\u0430\u043a\u043e\u201c \u045c\u0435 \u0438\u0437\u0432\u0440\u0448\u0438 \u043d\u0435\u0448\u0442\u043e \u0441\u0430\u043c\u043e \u0430\u043a\u043e \u0443\u0441\u043b\u043e\u0432\u043e\u0442 \u0435 \u0442\u043e\u0447\u0435\u043d. \u041d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u0432\u0440\u0442\u0435\u0442\u0435 \u043b\u0435\u0432\u043e \u0430\u043a\u043e \u0438\u043c\u0430 \u043f\u0430\u0442\u0435\u043a\u0430 \u043d\u0430\u0442\u0430\u043c\u0443.", + "Maze.helpMenu": "\u0421\u0442\u0438\u0441\u043d\u0435\u0442\u0435 \u043d\u0430 %1 \u0432\u043e \u0431\u043b\u043e\u043a\u043e\u0442 \u201e\u0430\u043a\u043e\u201c \u0437\u0430 \u0434\u0430 \u043c\u0443 \u0433\u043e \u0441\u043c\u0435\u043d\u0438\u0442\u0435 \u0443\u0441\u043b\u043e\u0432\u043e\u0442.", + "Maze.helpWallFollow": "\u0414\u0430\u043b\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0434\u0430 \u0433\u043e \u0440\u0435\u0448\u0438\u0442\u0435 \u043e\u0432\u043e\u0458 \u0441\u043b\u043e\u0436\u0435\u043d \u043b\u0430\u0432\u0438\u0440\u0438\u043d\u0442? \u041e\u0431\u0438\u0434\u0435\u0442\u0435 \u0441\u0435 \u0441\u043e \u0441\u043b\u0435\u0434\u043d\u0438\u043e\u0432 \u0455\u0438\u0434 \u043d\u0430 \u043b\u0435\u0432\u043e. \u0421\u0430\u043c\u043e \u0437\u0430 \u043d\u0430\u043f\u0440\u0435\u0434\u043d\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0435\u0440\u0438!", + "Plane.rows": "\u0420\u0435\u0434\u043e\u0432\u0438: %1", + "Plane.getRows": "\u0440\u0435\u0434\u043e\u0432\u0438 (%1)", + "Plane.rows1": "\u0420\u0435\u0434\u043e\u0432\u0438 \u043e\u0434 I \u043a\u043b\u0430\u0441\u0430: %1", + "Plane.getRows1": "\u0420\u0435\u0434\u043e\u0432\u0438 \u043e\u0434 I \u043a\u043b\u0430\u0441\u0430 (%1)", + "Plane.rows2": "\u0420\u0435\u0434\u043e\u0432\u0438 \u043e\u0434 II \u043a\u043b\u0430\u0441\u0430: %1", + "Plane.getRows2": "\u0420\u0435\u0434\u043e\u0432\u0438 \u043e\u0434 II \u043a\u043b\u0430\u0441\u0430: (%1)", + "Plane.seats": "\u0421\u0435\u0434\u0438\u0448\u0442\u0430: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "\u043c\u0435\u0441\u0442\u0430 =", + "Plane.plane": "\u0410\u0432\u0438\u043e\u043d", + "Plane.description1": "\u0410\u0432\u0438\u043e\u043d\u043e\u0442 \u0438\u043c\u0430 \u0438\u0437\u0432\u0435\u0441\u0435\u043d \u0431\u0440\u043e\u0458 \u0440\u0435\u0434\u043e\u0432\u0438 \u043e\u0434 \u0441\u0435\u0434\u0438\u0448\u0442\u0430. \u0421\u0435\u043a\u043e\u0458 \u0440\u0435\u0434 \u0438\u043c\u0430 \u043f\u043e \u0447\u0435\u0442\u0438\u0440\u0438 \u0441\u0435\u0434\u0438\u0448\u0442\u0430.", + "Plane.description2": "\u0410\u0432\u0438\u043e\u043d\u043e\u0442 \u0438\u043c\u0430 \u0434\u0432\u0435 \u0441\u0435\u0434\u0438\u0448\u0442\u0430 \u0432\u043e \u043f\u0438\u043b\u043e\u0442\u0441\u043a\u0430\u0442\u0430 \u043a\u0430\u0431\u0438\u043d\u0430 (\u0437\u0430 \u043f\u0438\u043b\u043e\u0442\u043e\u0442 \u0438 \u043a\u043e\u043f\u0438\u043b\u043e\u0442\u043e\u0442) \u0438 \u043f\u043e\u0432\u0435\u045c\u0435 \u0440\u0435\u0434\u043e\u0432\u0438 \u0441\u0435\u0434\u0438\u0448\u0442\u0430 \u0437\u0430 \u043f\u0430\u0442\u043d\u0438\u0446\u0438. \u0421\u0435\u043a\u043e\u0458 \u0440\u0435\u0434 \u0438\u043c\u0430 \u043f\u043e \u0447\u0435\u0442\u0438\u0440\u0438 \u0441\u0435\u0434\u0438\u0448\u0442\u0430.", + "Plane.description3": "\u0410\u0432\u0438\u043e\u043d\u043e\u0442 \u0438\u043c\u0430 \u0434\u0432\u0435 \u0441\u0435\u0434\u0438\u0448\u0442\u0430 \u0432\u043e \u043f\u0438\u043b\u043e\u0442\u0441\u043a\u0430\u0442\u0430 \u043a\u0430\u0431\u0438\u043d\u0430 (\u0437\u0430 \u043f\u0438\u043b\u043e\u0442\u043e\u0442 \u0438 \u043a\u043e\u043f\u0438\u043b\u043e\u0442\u043e\u0442) \u0438 \u043f\u043e\u0432\u0435\u045c\u0435 \u0440\u0435\u0434\u043e\u0432\u0438 \u0441\u0435\u0434\u0438\u0448\u0442\u0430 \u0437\u0430 \u043f\u0430\u0442\u043d\u0438\u0446\u0438 \u043e\u0434 I \u0438 II \u043a\u043b\u0430\u0441\u0430. \u0421\u0435\u043a\u043e\u0458 \u0440\u0435\u0434 \u043e\u0434 II \u043a\u043b\u0430\u0441\u0430 \u0438\u043c\u0430 \u043f\u043e \u043f\u0435\u0442 \u0441\u0435\u0434\u0438\u0448\u0442\u0430.", + "Plane.instructions": "\u0421\u043e\u0441\u0442\u0430\u0432\u0435\u0442\u0435 \u0444\u043e\u0440\u043c\u0443\u043b\u0430 (\u043f\u043e\u0434\u043e\u043b\u0443) \u0448\u0442\u043e \u0433\u043e \u043f\u0440\u0435\u0441\u043c\u0435\u0442\u0443\u0432\u0430 \u0432\u043a\u0443\u043f\u043d\u0438\u043e\u0442 \u0431\u0440\u043e\u0458 \u043d\u0430 \u0441\u0435\u0434\u0438\u0448\u0442\u0430 \u0432\u043e \u0430\u0432\u0438\u043e\u043d\u043e\u0442 \u043a\u0430\u043a\u043e \u0448\u0442\u043e \u0441\u0435 \u043c\u0435\u043d\u0443\u0432\u0430\u0430\u0442 \u0440\u0435\u0434\u043e\u0432\u0438\u0442\u0435 (\u043f\u043e\u0433\u043e\u0440\u0435).", + "Puzzle.country1": "\u0410\u0432\u0441\u0442\u0440\u0430\u043b\u0438\u0458\u0430", + "Puzzle.country1Language": "\u0430\u043d\u0433\u043b\u0438\u0441\u043a\u0438", + "Puzzle.country1City1": "\u041c\u0435\u043b\u0431\u0443\u0440\u043d", + "Puzzle.country1City2": "\u0421\u0438\u0434\u043d\u0435\u0458", + "Puzzle.country1HelpUrl": "http://mk.wikipedia.org/wiki/\u0410\u0432\u0441\u0442\u0440\u0430\u043b\u0438\u0458\u0430", + "Puzzle.country2": "\u0413\u0435\u0440\u043c\u0430\u043d\u0438\u0458\u0430", + "Puzzle.country2Language": "\u0433\u0435\u0440\u043c\u0430\u043d\u0441\u043a\u0438", + "Puzzle.country2City1": "\u0411\u0435\u0440\u043b\u0438\u043d", + "Puzzle.country2City2": "\u041c\u0438\u043d\u0445\u0435\u043d", + "Puzzle.country2HelpUrl": "http://mk.wikipedia.org/wiki/\u0413\u0435\u0440\u043c\u0430\u043d\u0438\u0458\u0430", + "Puzzle.country3": "\u041a\u0438\u043d\u0430", + "Puzzle.country3Language": "\u043a\u0438\u043d\u0435\u0441\u043a\u0438", + "Puzzle.country3City1": "\u041f\u0435\u043a\u0438\u043d\u0433", + "Puzzle.country3City2": "\u0428\u0430\u043d\u0433\u0430\u0458", + "Puzzle.country3HelpUrl": "http://mk.wikipedia.org/wiki/\u041a\u0438\u043d\u0430", + "Puzzle.country4": "\u0411\u0440\u0430\u0437\u0438\u043b", + "Puzzle.country4Language": "\u043f\u043e\u0440\u0442\u0443\u0433\u0430\u043b\u0441\u043a\u0438", + "Puzzle.country4City1": "\u0420\u0438\u043e \u0434\u0435 \u0416\u0430\u043d\u0435\u0438\u0440\u043e", + "Puzzle.country4City2": "\u0421\u0430\u043e \u041f\u0430\u043e\u043b\u043e", + "Puzzle.country4HelpUrl": "http://mk.wikipedia.org/wiki/\u0411\u0440\u0430\u0437\u0438\u043b", + "Puzzle.flag": "\u0437\u043d\u0430\u043c\u0435:", + "Puzzle.language": "\u0458\u0430\u0437\u0438\u043a:", + "Puzzle.languageChoose": "\u043e\u0434\u0431\u0435\u0440\u0435\u0442\u0435...", + "Puzzle.cities": "\u0433\u0440\u0430\u0434\u043e\u0432\u0438:", + "Puzzle.error0": "\u0421\u043e\u0432\u0440\u0448\u0435\u043d\u043e!\n\u0421\u0438\u0442\u0435 %1 \u0431\u043b\u043e\u043a\u043e\u0432\u0438 \u0441\u0435 \u0442\u043e\u0447\u043d\u0438.", + "Puzzle.error1": "\u0417\u0430 \u043c\u0430\u043b\u043a\u0443! \u0421\u0430\u043c\u043e \u0435\u0434\u0435\u043d \u0431\u043b\u043e\u043a \u0435 \u0433\u0440\u0435\u0448\u0435\u043d.", + "Puzzle.error2": "\u0418\u043c\u0430 %1 \u0433\u0440\u0435\u0448\u043d\u0438 \u0431\u043b\u043e\u043a\u043e\u0432\u0438.", + "Puzzle.tryAgain": "\u041f\u043e\u0442\u0446\u0440\u0442\u0430\u043d\u0438\u043e\u0442 \u0431\u043b\u043e\u043a \u043d\u0435 \u0435 \u0438\u0441\u043f\u0440\u0430\u0432\u0435\u043d.\n\u041e\u0431\u0438\u0434\u0443\u0432\u0430\u0458\u0442\u0435 \u0441\u0435 \u0438 \u043f\u043e\u043d\u0430\u0442\u0430\u043c\u0443.", + "Puzzle.title": "\u0421\u043b\u043e\u0436\u0443\u0432\u0430\u043b\u043a\u0430", + "Puzzle.help": "\u041f\u043e\u043c\u043e\u0448", + "Puzzle.checkAnswers": "\u041f\u0440\u043e\u0432\u0435\u0440\u0438 \u043e\u0434\u0433\u043e\u0432\u043e\u0440\u0438", + "Puzzle.helpText": "\u0417\u0430 \u0441\u0435\u043a\u043e\u0458\u0430 \u0437\u0435\u043c\u0458\u0430 (\u0437\u0435\u043b\u0435\u043d\u043e), \u043f\u0440\u0438\u043a\u0430\u0447\u0435\u0442\u0435 \u0433\u043e \u0437\u043d\u0430\u043c\u0435\u0442\u043e, \u0438\u0437\u0431\u0435\u0440\u0435\u0442\u0435 \u043a\u043e\u0458 \u0458\u0430\u0437\u0438\u043a \u0433\u043e \u0437\u0431\u043e\u0440\u0443\u0432\u0430 \u0438 \u043d\u0430\u0440\u0435\u0434\u0435\u0442\u0435 \u0433\u0438 \u0433\u0440\u0430\u0434\u043e\u0432\u0438\u0442\u0435.", + "Turtle.moveTooltip": "\u0408\u0430 \u043c\u0440\u0434\u043d\u0443\u0432\u0430 \u0436\u0435\u043b\u043a\u0430\u0442\u0430 \u043d\u0430\u043f\u0440\u0435\u0434 \u0438\u043b\u0438 \u043d\u0430\u0437\u0430\u0434 \u0437\u0430 \u0437\u0430\u0434\u0430\u0434\u0435\u043d\u0438\u043e\u0442 \u0438\u0437\u043d\u043e\u0441.", + "Turtle.moveForward": "\u043c\u0440\u0434\u043d\u0438 \u043d\u0430\u043f\u0440\u0435\u0434 \u0437\u0430", + "Turtle.moveBackward": "\u043c\u0440\u0434\u043d\u0438 \u043d\u0430\u0437\u0430\u0434 \u0437\u0430", + "Turtle.turnTooltip": "\u0408\u0430 \u0441\u0432\u0440\u0442\u0443\u0432\u0430 \u0436\u0435\u043b\u043a\u0430\u0442\u0430 \u043d\u0430 \u043b\u0435\u0432\u043e \u0438\u043b\u0438 \u043d\u0430 \u0434\u0435\u0441\u043d\u043e \u0437\u0430 \u0437\u0430\u0434\u0430\u0434\u0435\u043d \u0431\u0440\u043e\u0458 \u0441\u0442\u0435\u043f\u0435\u043d\u0438.", + "Turtle.turnRight": "\u0441\u0432\u0440\u0442\u0438 \u0434\u0435\u0441\u043d\u043e \u0437\u0430", + "Turtle.turnLeft": "\u0441\u0432\u0440\u0442\u0438 \u043b\u0435\u0432\u043e \u0437\u0430", + "Turtle.widthTooltip": "\u0408\u0430 \u043c\u0435\u043d\u0443\u0432\u0430 \u0434\u0435\u0431\u0435\u043b\u0438\u043d\u0430\u0442\u0430 \u043d\u0430 \u043c\u043e\u043b\u0438\u0432\u043e\u0442.", + "Turtle.setWidth": "\u043a\u043e\u0440\u0438\u0441\u0442\u0438 \u0434\u0435\u0431\u0435\u043b\u0438\u043d\u0430:", + "Turtle.colourTooltip": "\u0413\u0438 \u043c\u0435\u043d\u0443\u0432\u0430 \u0431\u043e\u0438\u0442\u0435 \u043d\u0430 \u043c\u043e\u043b\u0438\u0432\u043e\u0442.", + "Turtle.setColour": "\u043a\u043e\u0440\u0438\u0441\u0442\u0438 \u0431\u043e\u0458\u0430:", + "Turtle.penTooltip": "\u0413\u043e \u043f\u043e\u0434\u0438\u0433\u0430 \u0438 \u0441\u043f\u0443\u0448\u0442\u0430 \u043c\u043e\u043b\u0438\u0432\u043e\u0442 \u0437\u0430 \u0434\u0430 \u0437\u0430\u043f\u0440\u0435 \u0438\u043b\u0438 \u043f\u043e\u0447\u043d\u0435 \u0441\u043e \u0446\u0440\u0442\u0430\u045a\u0435.", + "Turtle.penUp": "\u0434\u0438\u0433\u043d\u0438 \u043c\u043e\u043b\u0438\u0432", + "Turtle.penDown": "\u0441\u043f\u0443\u0448\u0442\u0438 \u043c\u043e\u043b\u0438\u0432", + "Turtle.turtleVisibilityTooltip": "\u0408\u0430 \u043f\u0440\u0438\u043a\u0430\u0436\u0443\u0432\u0430 \u0438\u043b\u0438 \u0441\u043a\u0440\u0438\u0432\u0430 \u0436\u0435\u043b\u043a\u0430\u0442\u0430 (\u043a\u0440\u0443\u043a\u0447\u0435 \u0438 \u0441\u0442\u0440\u0435\u043b\u043a\u0430).", + "Turtle.hideTurtle": "\u0441\u043a\u0440\u0438\u0458 \u0436\u0435\u043b\u043a\u0430", + "Turtle.showTurtle": "\u043f\u0440\u0438\u043a\u0430\u0436\u0438 \u0436\u0435\u043b\u043a\u0430", + "Turtle.printHelpUrl": "http://mk.wikipedia.org/wiki/\u041f\u0435\u0447\u0430\u0442\u0430\u0440\u0441\u0442\u0432\u043e", + "Turtle.printTooltip": "\u0426\u0440\u0442\u0430 \u0442\u0435\u043a\u0441\u0442 \u0432\u043e \u043d\u0430\u0441\u043e\u043a\u0430 \u0438 \u043c\u0435\u0441\u0442\u043e\u043f\u043e\u043b\u043e\u0436\u0431\u0430 \u043d\u0430 \u0436\u0435\u043b\u043a\u0430\u0442\u0430.", + "Turtle.print": "\u0438\u0441\u043f\u0438\u0448\u0438", + "Turtle.fontHelpUrl": "http://mk.wikipedia.org/wiki/\u0424\u043e\u043d\u0442", + "Turtle.fontTooltip": "\u0417\u0430\u0434\u0430\u0432\u0430 \u0444\u043e\u043d\u0442 \u0437\u0430 \u0443\u043f\u043e\u0442\u0440\u0435\u0431\u0430 \u043d\u0430 \u043f\u0435\u0447\u0430\u0442\u043d\u043e\u0442\u043e \u0431\u043b\u043e\u043a\u0447\u0435.", + "Turtle.font": "\u0444\u043e\u043d\u0442", + "Turtle.fontSize": "\u0413\u043e\u043b\u0435\u043c\u0438\u043d\u0430 \u043d\u0430 \u0444\u043e\u043d\u0442\u043e\u0442", + "Turtle.fontNormal": "\u043d\u043e\u0440\u043c\u0430\u043b\u0435\u043d", + "Turtle.fontBold": "\u0437\u0430\u0434\u0435\u0431\u0435\u043b\u0435\u043d", + "Turtle.fontItalic": "\u0437\u0430\u043a\u043e\u0441\u0435\u043d", + "Turtle.unloadWarning": "\u0410\u043a\u043e \u0458\u0430 \u043d\u0430\u043f\u0443\u0448\u0442\u0438\u0442\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0442\u0430, \u045c\u0435 \u0433\u043e \u0438\u0437\u0433\u0443\u0431\u0438\u0442\u0435 \u0434\u043e\u0441\u0435\u0433\u0430 \u043d\u0430\u043f\u0440\u0430\u0432\u0435\u043d\u043e\u0442\u043e.", + "Turtle.title": "\u0416\u0435\u043b\u043a\u0438\u043d\u0430 \u0433\u0440\u0430\u0444\u0438\u043a\u0430", + "Turtle.runTooltip": "\u040d \u043a\u0430\u0436\u0443\u0432\u0430 \u043d\u0430 \u0436\u0435\u043b\u043a\u0430\u0442\u0430 \u0434\u0430 \u043f\u0440\u0430\u0432\u0438 \u043a\u0430\u043a\u043e \u0448\u0442\u043e \u0432\u0435\u043b\u0430\u0442 \u0431\u043b\u043e\u043a\u0447\u0438\u045a\u0430\u0442\u0430.", + "Turtle.captureTooltip": "\u0417\u0430\u0447\u0443\u0432\u0430\u0458 \u0433\u043e \u0446\u0440\u0442\u0435\u0436\u043e\u0442.", + "Turtle.imgFilename": "\u0446\u0440\u0442\u0435\u0436.png", + "Turtle.catTurtle": "\u0416\u0435\u043b\u043a\u0430" +} \ No newline at end of file diff --git a/apps/json/ml.json b/apps/json/ml.json new file mode 100644 index 000000000..19d828c20 --- /dev/null +++ b/apps/json/ml.json @@ -0,0 +1,35 @@ +{ + "Puzzle.tryAgain": "പ്രമുഖമാക്കി കാണിക്കുന്ന തടയൽ ശരിയല്ല.\nവീണ്ടും ശ്രമിക്കുക.", + "Puzzle.country3City2": "ഷാങ്ഹായ്", + "Puzzle.country3HelpUrl": "http://ml.wikipedia.org/wiki/China", + "Puzzle.country3Language": "ചൈനീസ്", + "Puzzle.checkAnswers": "ഉത്തരങ്ങൾ പരിശോധിക്കുക", + "Puzzle.language": "ഭാഷ:", + "Apps.dialogOk": "ശരി", + "Puzzle.title": "പ്രഹേളിക", + "Puzzle.country1HelpUrl": "http://ml.wikipedia.org/wiki/Australia", + "Puzzle.languageChoose": "തിരഞ്ഞെടുക്കുക:", + "Puzzle.country4City2": "സാവോ പോളോ", + "Puzzle.country4City1": "റിയോ ഡി ജനീറോ", + "Puzzle.country4Language": "പോർച്ചുഗീസ്", + "Puzzle.helpText": "ഓരോ രാജ്യത്തിനും (പച്ച), അതിന്റെ പതാക ചേർക്കുക, ഭാഷ തിരഞ്ഞെടുക്കുക ഒപ്പം നഗരങ്ങളുടെ പട്ടിക തയ്യാറാക്കുക.", + "Puzzle.flag": "പതാക:", + "Puzzle.country4HelpUrl": "http://ml.wikipedia.org/wiki/Brazil", + "Puzzle.error1": "കുഴപ്പമില്ല! ഒരു തടയൽ ശരിയല്ല.", + "Puzzle.country3City1": "ബീജിങ്ങ്", + "Puzzle.country1City1": "മെൽബൺ", + "Puzzle.country1City2": "സിഡ്നി", + "Puzzle.country2Language": "ജെർമ്മൻ", + "Puzzle.country3": "ചൈന", + "Puzzle.country2": "ജർമ്മനി", + "Puzzle.country1": "ഓസ്ട്രേലിയ", + "Puzzle.country2HelpUrl": "http://ml.wikipedia.org/wiki/Germany", + "Puzzle.error0": "കൊള്ളാം!\nഎല്ലാ %1 തടയലുകളും ശരിയാണ്.", + "Puzzle.country4": "ബ്രസീൽ", + "Puzzle.error2": "%1 തടയലുകൾ ശരിയല്ല.", + "Puzzle.help": "സഹായം", + "Puzzle.country1Language": "ഇംഗ്ലീഷ്", + "Puzzle.country2City1": "ബെർലിൻ", + "Puzzle.cities": "പട്ടണങ്ങൾ:", + "Puzzle.country2City2": "മ്യൂണിക്" +} diff --git a/apps/json/mr.json b/apps/json/mr.json new file mode 100644 index 000000000..15fec3a89 --- /dev/null +++ b/apps/json/mr.json @@ -0,0 +1,76 @@ +{ + "@metadata": { + "authors": [ + "V.narsikar" + ] + }, + "Apps.runProgram": "\u092a\u094d\u0930\u094b\u0917\u094d\u0930\u093e\u092e \u091a\u093e\u0932\u0935\u093e(\u0926\u094c\u0921\u0935\u093e)", + "Apps.resetProgram": "\u092a\u0941\u0928\u0930\u094d\u0938\u094d\u0925\u093e\u092a\u093f\u0924 \u0915\u0930\u093e", + "Apps.catLoops": "\u0935\u0947\u091f\u094b\u0933\u094d\u092f\u093e(\u0932\u0942\u092a\u094d\u0938)", + "Apps.catText": "\u092e\u091c\u0915\u0942\u0930", + "Apps.catColour": "\u0930\u0902\u0917", + "Apps.catVariables": "\u0905\u0938\u094d\u0925\u093f\u0930\u0915\u0947", + "Apps.listVariable": "\u092f\u093e\u0926\u0940", + "Apps.textVariable": "\u092e\u091c\u0915\u0942\u0930", + "Code.title": "\u0938\u0902\u0915\u0947\u0924", + "Code.blocks": "\u092c\u094d\u0932\u0949\u0915\u094d\u0938", + "Maze.moveForwardTooltip": "\u0916\u0947\u0933\u093e\u0921\u0942\u0938 \u090f\u0915 \u092a\u093e\u0909\u0932 \u092a\u0941\u0922\u0947 \u0915\u0930\u0924\u094b", + "Maze.runTooltip": "\u092c\u094d\u0932\u0949\u0915\u094d\u0938 \u0915\u093e\u092f \u092e\u094d\u0939\u0923\u0924\u093e\u0924 \u0924\u094d\u092f\u093e\u0928\u0941\u0938\u093e\u0930 \u092a\u093e\u0924\u094d\u0930\u093e\u0938 \u0915\u093e\u092e \u0915\u0930\u093e\u0935\u092f\u093e\u0938 \u0932\u093e\u0935\u0924\u0947.", + "Plane.getRows": "\u0930\u093e\u0902\u0917\u093e (%1)", + "Plane.rows1": "\u092a\u094d\u0930\u0925\u092e \u0936\u094d\u0930\u0947\u0923\u0940\u091a\u094d\u092f\u093e \u0913\u0933\u0940: %1", + "Plane.getRows2": "\u0926\u0941\u0938\u0931\u094d\u092f\u093e \u0935\u0930\u094d\u0917\u093e\u091a\u0940 \u0930\u093e\u0902\u0917(%1)", + "Plane.setSeats": "\u0906\u0938\u0928\u0947 =", + "Plane.plane": "\u0935\u093f\u092e\u093e\u0928", + "Plane.description1": "\u0935\u093f\u092e\u093e\u0928\u093e\u0924,\u092a\u094d\u0930\u0935\u093e\u0936\u094d\u092f\u093e\u0902\u0938\u093e\u0920\u0940 \u0906\u0938\u0928\u093e\u0902\u091a\u094d\u092f\u093e \u0905\u0928\u0947\u0915 \u0930\u093e\u0902\u0917\u093e \u0905\u0938\u0924\u093e\u0924.\u092a\u094d\u0930\u0924\u094d\u092f\u0947\u0915 \u0930\u093e\u0902\u0917\u0947\u0924 \u091a\u093e\u0930 \u0906\u0938\u0928\u0947 \u0905\u0938\u0924\u093e\u0924.", + "Plane.description2": "\u0935\u093f\u092e\u093e\u0928\u093e\u0938, \u0935\u093f\u092e\u093e\u0928\u0928 \u0915\u0915\u094d\u0937\u093e\u0924 \u0926\u094b\u0928 \u0906\u0938\u0928\u0947 \u0905\u0938\u0924\u093e\u0924(\u0935\u0948\u092e\u093e\u0928\u093f\u0915 \u0935 \u0938\u0939-\u0935\u0948\u092e\u093e\u0928\u093f\u0915\u093e\u0938\u093e\u0920\u0940) \u0935 \u092a\u094d\u0930\u0935\u093e\u0936\u094d\u092f\u093e\u0902\u0938\u093e\u0920\u0940 \u0906\u0938\u0928\u093e\u0902\u091a\u094d\u092f\u093e \u0905\u0928\u0947\u0915 \u0930\u093e\u0902\u0917\u093e \u0905\u0938\u0924\u093e\u0924.\u092a\u094d\u0930\u0924\u094d\u092f\u0947\u0915 \u0930\u093e\u0902\u0917\u0947\u0924 \u091a\u093e\u0930 \u0906\u0938\u0928\u0947 \u0905\u0938\u0924\u093e\u0924.", + "Plane.description3": "\u0935\u093f\u092e\u093e\u0928\u093e\u0938, \u0935\u093f\u092e\u093e\u0928\u0928 \u0915\u0915\u094d\u0937\u093e\u0924 \u0926\u094b\u0928 \u0906\u0938\u0928\u0947 \u0905\u0938\u0924\u093e\u0924(\u0935\u0948\u092e\u093e\u0928\u093f\u0915 \u0935 \u0938\u0939-\u0935\u0948\u092e\u093e\u0928\u093f\u0915\u093e\u0938\u093e\u0920\u0940) \u0935 \u092a\u094d\u0930\u0925\u092e \u0936\u094d\u0930\u0947\u0923\u0940 \u0935 \u0926\u094d\u0935\u093f\u0924\u0940\u092f \u0936\u094d\u0930\u0947\u0923\u0940 \u0906\u0938\u0928\u093e\u0902\u091a\u094d\u092f\u093e \u0905\u0928\u0947\u0915 \u0930\u093e\u0902\u0917\u093e \u0905\u0938\u0924\u093e\u0924.\u092a\u094d\u0930\u0924\u094d\u092f\u0947\u0915 \u092a\u094d\u0930\u0925\u092e \u0936\u094d\u0930\u0947\u0923\u0940\u091a\u094d\u092f\u093e \u0930\u093e\u0902\u0917\u0947\u0924 \u091a\u093e\u0930 \u0906\u0938\u0928\u0947 \u0905\u0938\u0924\u093e\u0924.\u092a\u094d\u0930\u0924\u094d\u092f\u0947\u0915 \u0926\u094d\u0935\u093f\u0924\u0940\u092f \u0936\u094d\u0930\u0947\u0923\u0940\u091a\u094d\u092f\u093e \u0930\u093e\u0902\u0917\u0947\u0924 \u092a\u093e\u091a \u0906\u0938\u0928\u0947 \u0905\u0938\u0924\u093e\u0924.", + "Puzzle.country1": "\u0911\u0938\u094d\u091f\u094d\u0930\u0947\u0932\u093f\u092f\u093e", + "Puzzle.country1Language": "\u0907\u0902\u0917\u094d\u0932\u093f\u0936", + "Puzzle.country1City1": "\u092e\u0947\u0932\u092c\u094b\u0930\u094d\u0928", + "Puzzle.country1City2": "\u0938\u093f\u0921\u0928\u0940", + "Puzzle.country1HelpUrl": "http://mr.wikipedia.org/wiki/%E0%A4%91%E0%A4%B8%E0%A5%8D%E0%A4%9F%E0%A5%8D%E0%A4%B0%E0%A5%87%E0%A4%B2%E0%A4%BF%E0%A4%AF%E0%A4%BE", + "Puzzle.country2": "\u091c\u0930\u094d\u092e\u0928\u0940", + "Puzzle.country2Language": "\u091c\u0930\u094d\u092e\u0928", + "Puzzle.country2City1": "\u092c\u0930\u094d\u0932\u093f\u0928", + "Puzzle.country2City2": "\u092e\u094d\u092f\u0941\u0928\u093f\u0915", + "Puzzle.country2HelpUrl": "http://mr.wikipedia.org/wiki/%E0%A4%9C%E0%A4%B0%E0%A5%8D%E0%A4%AE%E0%A4%A8%E0%A5%80", + "Puzzle.country3": "\u091a\u0940\u0928", + "Puzzle.country3Language": "\u091a\u0940\u0928\u091a\u093e/\u091a\u0940", + "Puzzle.country3City1": "\u092c\u0940\u091c\u093f\u0902\u0917", + "Puzzle.country3City2": "\u0936\u093e\u0902\u0918\u093e\u092f", + "Puzzle.country3HelpUrl": "http://mr.wikipedia.org/wiki/%E0%A4%9A%E0%A5%80%E0%A4%A8", + "Puzzle.country4": "\u092c\u094d\u0930\u093e\u091d\u093f\u0932", + "Puzzle.country4Language": "\u092a\u094b\u0930\u094d\u0924\u0941\u0917\u0940\u091c", + "Puzzle.country4City1": "\u0930\u093f\u0913-\u0926\u093f-\u091c\u093e\u0928\u0947\u0930\u094b", + "Puzzle.country4City2": "\u0938\u093e\u0913 \u092a\u093e\u0909\u0932\u094b", + "Puzzle.country4HelpUrl": "http://mr.wikipedia.org/wiki/%E0%A4%AC%E0%A5%8D%E0%A4%B0%E0%A4%BE%E0%A4%9D%E0%A5%80%E0%A4%B2", + "Puzzle.flag": "\u0927\u094d\u0935\u091c:", + "Puzzle.language": "\u092d\u093e\u0937\u093e:", + "Puzzle.languageChoose": "\u0928\u093f\u0935\u0921\u093e...", + "Puzzle.cities": "\u0936\u0939\u0930\u0947:", + "Puzzle.error0": "\u0938\u0930\u094d\u0935 %1 \u092c\u094d\u0932\u0949\u0915\u094d\u0938 \u092c\u0930\u094b\u092c\u0930 \u0906\u0939\u0947\u0924.", + "Puzzle.error1": "\u091c\u0935\u0933\u092a\u093e\u0938! \u090f\u0915 \u092c\u094d\u0932\u0949\u0915 \u091a\u0941\u0915\u093f\u091a\u093e \u0906\u0939\u0947.", + "Puzzle.error2": "%1 \u092c\u094d\u0932\u0949\u0915\u094d\u0938 \u091a\u0941\u0915\u093f\u091a\u0947 \u0906\u0939\u0947\u0924.", + "Puzzle.title": "\u0915\u094b\u0921\u0947", + "Puzzle.help": "\u0938\u0939\u093e\u092f\u094d\u092f", + "Puzzle.checkAnswers": "\u0909\u0924\u094d\u0924\u0930\u0947 \u0924\u092a\u093e\u0938\u093e", + "Puzzle.helpText": "\u092a\u094d\u0930\u0924\u094d\u092f\u0947\u0915 \u0926\u0947\u0936\u093e\u0938 (\u0939\u093f\u0930\u0935\u094d\u092f\u093e \u0930\u0902\u0917\u093e\u0924),\u0924\u094d\u092f\u093e\u091a\u093e \u0930\u093e\u0937\u094d\u091f\u094d\u0930\u0927\u094d\u0935\u091c \u0932\u093e\u0935\u093e,\u0924\u094d\u092f\u093e\u091a\u0940 \u092d\u093e\u0937\u093e \u0928\u093f\u0935\u0921\u093e \u0935 \u0924\u094d\u092f\u093e\u091a\u094d\u092f\u093e \u0936\u0939\u0930\u093e\u0902\u091a\u0940 \u091a\u0933\u0924 \u0932\u093e\u0935\u093e.", + "Turtle.moveBackward": "\u0928\u0940 \u092e\u093e\u0917\u0947 \u091a\u0932\u093e", + "Turtle.turnTooltip": "\u0928\u092e\u0942\u0926 \u0915\u0947\u0932\u0947\u0932\u094d\u092f\u093e \u0935\u093f\u0936\u093f\u0937\u094d\u091f \u0915\u094b\u0928\u093e\u0924\u0942\u0928 \u0915\u093e\u0938\u0935\u093e\u0938 \u0921\u093e\u0935\u0940\u0915\u0921\u0947 \u0915\u093f\u0902\u0935\u093e \u0909\u091c\u0935\u0940\u0915\u0921\u0947 \u0935\u0933\u0935\u093f\u0924\u0947.", + "Turtle.turnRight": "\u0928\u0947 \u0909\u091c\u0935\u0940\u0915\u0921\u0947 \u0935\u0933\u093e", + "Turtle.turnLeft": "\u0928\u0947 \u0921\u093e\u0935\u0940\u0915\u0921\u0947 \u0935\u0933\u093e", + "Turtle.widthTooltip": "\u092a\u0947\u0928\u091a\u094d\u092f\u093e \u0930\u0947\u0937\u0947\u091a\u0940 \u0930\u0941\u0902\u0926\u0940 \u092c\u0926\u0932\u0935\u0924\u094b.", + "Turtle.setWidth": "\u0939\u0940 \u0930\u0941\u0902\u0926\u0940 \u092e\u093e\u0902\u0921\u093e", + "Turtle.setColour": "\u0939\u093e \u0930\u0902\u0917 \u092e\u093e\u0902\u0921\u093e", + "Turtle.turtleVisibilityTooltip": "\u0915\u093e\u0938\u0935\u093e\u0938 (\u0939\u093f\u0930\u0935\u0947 \u0935\u0930\u094d\u0924\u0941\u0933 \u0935 \u092c\u093e\u0923) \u0926\u0943\u0937\u094d\u092f \u0915\u093f\u0902\u0935\u093e \u0905\u0926\u0943\u0937\u094d\u092f \u0915\u0930\u0924\u094b.", + "Turtle.hideTurtle": "\u0915\u093e\u0938\u0935\u093e\u0938 \u0932\u092a\u0935\u093e", + "Turtle.showTurtle": "\u0915\u093e\u0938\u0935 \u0926\u093e\u0916\u0935\u093e", + "Turtle.fontSize": "\u091f\u0902\u0915\u093e\u091a\u093e \u0906\u0915\u093e\u0930(\u0938\u093e\u0908\u091d)", + "Turtle.fontNormal": "\u0938\u093e\u0927\u093e\u0930\u0923", + "Turtle.fontBold": "\u0920\u0933\u0915", + "Turtle.fontItalic": "\u0924\u093f\u0930\u092a\u0940 \u0905\u0915\u094d\u0937\u0930\u0947", + "Turtle.unloadWarning": "\u092f\u093e \u092a\u093e\u0928\u093e\u0935\u0930\u0942\u0928 \u092c\u093e\u0939\u0947\u0930 \u0928\u093f\u0918\u0923\u094d\u092f\u093e\u0928\u0947, \u0906\u092a\u0923 \u0915\u0947\u0932\u0947\u0932\u0947 \u0915\u093e\u092e \u0905\u0926\u0943\u0936\u094d\u092f \u0939\u094b\u0908\u0932.", + "Turtle.runTooltip": "\u092c\u094d\u0932\u0949\u0915\u094d\u0938 \u0915\u093e\u092f \u092e\u094d\u0939\u0923\u0924\u093e\u0924 \u0924\u094d\u092f\u093e\u0928\u0941\u0938\u093e\u0930 \u0915\u093e\u0938\u0935\u093e\u0938 \u0915\u093e\u092e \u0915\u0930\u093e\u0935\u092f\u093e\u0938 \u0932\u093e\u0935\u0924\u0947.", + "Turtle.captureTooltip": "\u0930\u0947\u0916\u093e\u091f\u0928 \u091c\u0924\u0928 \u0915\u0930\u093e.", + "Turtle.catTurtle": "\u0915\u093e\u0938\u0935" +} \ No newline at end of file diff --git a/apps/json/ms.json b/apps/json/ms.json new file mode 100644 index 000000000..1af3aa714 --- /dev/null +++ b/apps/json/ms.json @@ -0,0 +1,149 @@ +{ + "@metadata": { + "authors": [ + "Anakmalaysia", + "Aurora" + ] + }, + "Apps.subtitle": "persekitaran pengaturcaraan visual", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Lihat kod JavaScript yang dihasilkan.", + "Apps.linkTooltip": "Simpan dan pautkan kepada blok.", + "Apps.runTooltip": "Jalankan aturcara yang ditetapkan oleh blok-blok di dalam ruang kerja.", + "Apps.runProgram": "Jalankan Program", + "Apps.resetProgram": "Reset", + "Apps.dialogOk": "OK", + "Apps.dialogCancel": "Batalkan", + "Apps.catLogic": "Logik", + "Apps.catLoops": "Gelung", + "Apps.catMath": "Matematik", + "Apps.catText": "Teks", + "Apps.catLists": "Senarai", + "Apps.catColour": "Warna", + "Apps.catVariables": "Pemboleh ubah", + "Apps.catProcedures": "Prosedur", + "Apps.httpRequestError": "Permintaan itu terdapat masalah.", + "Apps.linkAlert": "Kongsikan blok-blok anda dengan pautan ini:\n\n%1", + "Apps.hashError": "Maaf, '%1' tidak berpadanan dengan sebarang aturcara yang disimpan.", + "Apps.xmlError": "Fail simpanan anda tidak dapat dimuatkan. Jangan-jangan ia dicipta dengan versi Blockly yang berlainan?", + "Apps.listVariable": "senarai", + "Apps.textVariable": "teks", + "Code.badXml": "Ralat ketika menghuraian XML:\n%1\n\nPilih 'OK' untuk melucutkan suntingan anda atau 'Batal' untuk bersambung menyunting XML-nya.", + "Code.badCode": "Ralat atur cara:\n%1", + "Code.timeout": "Takat maksimum lelaran pelaksanaan dicecah.", + "Code.discard": "Hapuskan kesemua %1 blok?", + "Code.title": "Kod", + "Code.blocks": "Blok", + "Code.trashTooltip": "Buang semua blok.", + "Graph.title": "Kalkulator Graf", + "Maze.moveForward": "mara ke hadapan", + "Maze.turnLeft": "belok kiri", + "Maze.turnRight": "belok kanan", + "Maze.doCode": "lakukan", + "Maze.elseCode": "jika tidak", + "Maze.helpIfElse": "Blok 'jika-jika tidak' akan memilih salah satu tindakan yang diberikan.", + "Maze.pathAhead": "jika ada laluan ke hadapan", + "Maze.pathLeft": "jika ada laluan ke kiri", + "Maze.pathRight": "jika ada laluan ke kanan", + "Maze.repeatUntil": "ulangi sehingga", + "Maze.moveForwardTooltip": "Mengalihkan Pegman satu petak ke hadapan.", + "Maze.turnTooltip": "Membelokkan Pegman 90 darjah ke kiri atau ke kanan.", + "Maze.ifTooltip": "Jika terdapat laluan ke arah yang tertentu, lakukan beberapa tindakan.", + "Maze.ifelseTooltip": "Jika terdapat laluan ke arah yang tertentu, ambil blok tindakan yang pertama. Jika tidak, ambil blok tindakan yang kedua.", + "Maze.whileTooltip": "Ulangi tindakan-tindakan yang dilampirkan sehingga titik penamat dicapai.", + "Maze.capacity0": "Tinggal %0 blok.", + "Maze.capacity1": "Tinggal %1 blok.", + "Maze.capacity2": "Tinggal %2 blok.", + "Maze.nextLevel": "Tahniah! Adakah anda sedia untuk meningkat ke peringkat %1?", + "Maze.finalLevel": "Tahniah! Anda telah menyelesaikan peringkat terakhir.", + "Maze.maze": "Pagar Sesat", + "Maze.runTooltip": "Membuatkan pemain menurut pesan blok.", + "Maze.resetTooltip": "Letakkn pemain kembali di pangkal pagar sesat.", + "Maze.helpStack": "Program merupakan turutan blok. Susunkan beberapa blok 'maju' untuk menolong saya mencapai tempat tujuan.", + "Maze.helpOneTopBlock": "Di tingkat ini, anda perlu menyusun semua blok secara bertingkat-tingkat ini di dalam ruang kerja putih.", + "Maze.helpRun": "Jalankan program anda untuk melihat apa yang berlaku.", + "Maze.helpReset": "Program anda tidak menyelesaikan pagar sesat. Tekan 'Reset' dan cuba lagi.", + "Maze.helpRepeat": "Komputer mempunyai memori yang terhad. Capai hujung jalan dengan menggunakan dua blok sahaja. Gunakan 'ulang' untuk menjalankan satu blok lebih daripada sekali.", + "Maze.helpCapacity": "Anda telah menggunakan semua blok untuk tahap ini. Untuk membuat blok baru, anda perlu memadamkan satu blok yang sedia ada dahulu.", + "Maze.helpRepeatMany": "Anda boleh memuatkan lebih daripada satu blok di dalam blok 'ulang'.", + "Maze.helpIf": "Blok 'jika' akan melakukan sesuatu hanya jika keadaannya benar. Cuba belok ke kiri jika terdapat laluan ke kiri.", + "Maze.helpMenu": "Klik pada %1 di dalam blok 'if' untuk mengubah keadaannya.", + "Maze.helpWallFollow": "Bolehkah anda menyelesaikan pagar sesat yang rumit ini? Cuba ikut tembok sebelah kiri. Untuk pengaturcara pakar sahaja!", + "Plane.rows": "Baris: %1", + "Plane.getRows": "baris (%1)", + "Plane.rows1": "Baris kelas pertama: %1", + "Plane.getRows1": "baris kelas pertama (%1)", + "Plane.rows2": "Baris kelas ke-2: %1", + "Plane.getRows2": "baris kelas ke-2 (%1)", + "Plane.seats": "Tempat duduk: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "tempat duduk =", + "Plane.plane": "Kapal Terbang", + "Plane.description1": "Sebuah kapal terbang mempunyai sebilangan baris tempat duduk penumpang. Setiap baris mengandungi empat tempat duduk.", + "Plane.description2": "Sebuah kapal terbnag mempunyai tempat duduk di kokpit (untuk juruterbang dan pembantunya) dan sebilangan baris tempat duduk penumpang. Setiap baris mengandungi empat tempat duduk.", + "Plane.description3": "Sebuah kapal terbnag mempunyai tempat duduk di kokpit (untuk juruterbang dan pembantunya) dan sebilangan baris tempat duduk penumpang kelas pertama dan kelas kedua. Setiap baris kelas pertama mengandungi empat tempat duduk. Setiap baris kelas pertama mengandungi lima tempat duduk.", + "Plane.instructions": "Wujudkan formula (di bawah) yang mengira jumlah tempat duduk di dalam kapal terbang sedangkan baris-barisnya diubah (di atas).", + "Puzzle.country1": "Australia", + "Puzzle.country1Language": "Inggeris", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://ms.wikipedia.org/wiki/Australia", + "Puzzle.country2": "Jerman", + "Puzzle.country2Language": "Jerman", + "Puzzle.country2City1": "Berlin", + "Puzzle.country2City2": "Munich", + "Puzzle.country2HelpUrl": "http://ms.wikipedia.org/wiki/Jerman", + "Puzzle.country3": "China", + "Puzzle.country3Language": "Cina", + "Puzzle.country3City1": "Beijing", + "Puzzle.country3City2": "Shanghai", + "Puzzle.country3HelpUrl": "http://ms.wikipedia.org/wiki/Republik_Rakyat_China", + "Puzzle.country4": "Brazil", + "Puzzle.country4Language": "Portugis", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "S\u00e3o Paulo", + "Puzzle.country4HelpUrl": "http://ms.wikipedia.org/wiki/Brazil", + "Puzzle.flag": "bendera:", + "Puzzle.language": "bahasa:", + "Puzzle.languageChoose": "pilih...", + "Puzzle.cities": "bandar:", + "Puzzle.error0": "Sempurna!\nKesemua %1 blok adalah betul.", + "Puzzle.error1": "Sikit saja lagi! Satu blok tidak betul.", + "Puzzle.error2": "%1 blok tidak betul.", + "Puzzle.tryAgain": "Blok yang ditonjolkan itu tidak betul. Cuba lagi.", + "Puzzle.title": "Teka-teki", + "Puzzle.help": "Bantuan", + "Puzzle.checkAnswers": "Semak Jawapan", + "Puzzle.helpText": "Untuk setiap negara (hijau), lampirkan benderanya, pilih bahasanya, dan susunkan bandar-bandarnya.", + "Turtle.moveTooltip": "Mengalihkan kekura ke hadapan atau ke belakang pada bilangan yang dinyatakan.", + "Turtle.moveForward": "mara ke hadapan", + "Turtle.moveBackward": "undur ke belakang", + "Turtle.turnTooltip": "Membelokkan kekura ke kiri atau kanan dengan bilangan darjah yang ditetapkan.", + "Turtle.turnRight": "belok kanan", + "Turtle.turnLeft": "belok kiri", + "Turtle.widthTooltip": "Mengubah keluasan pena.", + "Turtle.setWidth": "laraskan lebarnya pada", + "Turtle.colourTooltip": "Mengubah warna pena.", + "Turtle.setColour": "gunakan warna", + "Turtle.penTooltip": "Mengangkat atau menurunkan pena untuk berhenti atau bersambung melukis.", + "Turtle.penUp": "angkat pen", + "Turtle.penDown": "turunkan pen", + "Turtle.turtleVisibilityTooltip": "Memperlihatkan atau menghalimunankan kekura (bulatan dan anak panah).", + "Turtle.hideTurtle": "halimunankan kekura", + "Turtle.showTurtle": "perlihatkan kekura", + "Turtle.printHelpUrl": "http://ms.wikipedia.org/wiki/Pencetakan", + "Turtle.printTooltip": "Melukis teks di arah kekura pada kedudukannya.", + "Turtle.print": "cetak", + "Turtle.fontTooltip": "Menetapkan fon (rupa huruf) yang digunakan oleh blok cetak.", + "Turtle.font": "fon", + "Turtle.fontSize": "saiz fon", + "Turtle.fontNormal": "biasa", + "Turtle.fontBold": "tebal", + "Turtle.fontItalic": "condong", + "Turtle.unloadWarning": "Hasil kerja anda akan terhapus jika anda meninggalkan halaman ini.", + "Turtle.title": "Turtle Graphics", + "Turtle.runTooltip": "Membuat kekura menurut perintah blok.", + "Turtle.captureTooltip": "Simpan lukisan.", + "Turtle.imgFilename": "lukisan.png", + "Turtle.catTurtle": "Pepenyu" +} \ No newline at end of file diff --git a/apps/json/mzn.json b/apps/json/mzn.json new file mode 100644 index 000000000..d70af1393 --- /dev/null +++ b/apps/json/mzn.json @@ -0,0 +1,35 @@ +{ + "Puzzle.tryAgain": "پررنگ بلوک غلطه.\nاَی دِباره تِلاش هاکن.", + "Puzzle.country3City2": "شانگهای", + "Puzzle.country3HelpUrl": "http://en.wikipedia.org/wiki/China", + "Puzzle.country3Language": "چینی", + "Puzzle.checkAnswers": "جوابِ بررسی", + "Puzzle.language": "زوون:", + "Apps.dialogOk": "خا", + "Puzzle.title": "پازل", + "Puzzle.country1HelpUrl": "http://mzn.wikipedia.org/wiki/استرالیا", + "Puzzle.languageChoose": "چینه...", + "Puzzle.country4City2": "سائوپائولو", + "Puzzle.country4City1": "ریو دوژانیرو", + "Puzzle.country4Language": "پرتغال", + "Puzzle.helpText": "هر کشور وسّه (سَوز)، وشونِ پرچم پَلی، زوون ره چینه هاکن و ونه شهرون فهرست ره بساز", + "Puzzle.flag": "پرچم:", + "Puzzle.country4HelpUrl": "http://mzn.wikipedia.org/wiki/برزیل", + "Puzzle.error1": "تقریباً! اتا بلوک غلطه.", + "Puzzle.country3City1": "پکن", + "Puzzle.country1City1": "ملبورن", + "Puzzle.country1City2": "سیدنی", + "Puzzle.country2Language": "آلمانی", + "Puzzle.country3": "چین", + "Puzzle.country2": "آلمان", + "Puzzle.country1": "استرالیا", + "Puzzle.country2HelpUrl": "http://en.wikipedia.org/wiki/Germany", + "Puzzle.error0": "خاره!\nتموم %1 بلوک‌ها درست هسته.", + "Puzzle.country4": "برزیل", + "Puzzle.error2": " %1 بلوک‌ها غلط هستنه.", + "Puzzle.help": "کومک", + "Puzzle.country1Language": "اینگلیسی", + "Puzzle.country2City1": "برلین", + "Puzzle.cities": "شهر:", + "Puzzle.country2City2": "مونیخ" +} diff --git a/apps/json/nb.json b/apps/json/nb.json new file mode 100644 index 000000000..9c19d6a53 --- /dev/null +++ b/apps/json/nb.json @@ -0,0 +1,35 @@ +{ + "Puzzle.tryAgain": "Den merkede blokken er ikke riktig.\nFortsett å prøve.", + "Puzzle.country3City2": "Shanghai", + "Puzzle.country3HelpUrl": "http://no.wikipedia.org/wiki/Kina", + "Puzzle.country3Language": "Kinesisk", + "Puzzle.checkAnswers": "Sjekk svar", + "Puzzle.language": "språk:", + "Apps.dialogOk": "OK", + "Puzzle.title": "Puslespill", + "Puzzle.country1HelpUrl": "http://no.wikipedia.org/wiki/Australia", + "Puzzle.languageChoose": "velg...", + "Puzzle.country4City2": "São Paulo", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4Language": "Portugal", + "Puzzle.helpText": "For hvert land (grønt), sett ut flagget som hører til, velg språket og lag en gruppe med dets byer.", + "Puzzle.flag": "flagg:", + "Puzzle.country4HelpUrl": "http://no.wikipedia.org/wiki/Brasil", + "Puzzle.error1": "Nesten! En blokk er feil.", + "Puzzle.country3City1": "Beijing", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country2Language": "Tysk", + "Puzzle.country3": "Kina", + "Puzzle.country2": "Tyskland", + "Puzzle.country1": "Australia", + "Puzzle.country2HelpUrl": "http://no.wikipedia.org/wiki/Tyskland", + "Puzzle.error0": "Perfekt!\nAlle %1 blokker er riktig.", + "Puzzle.country4": "Brasil", + "Puzzle.error2": "%1 blokker er feil.", + "Puzzle.help": "Hjelp", + "Puzzle.country1Language": "Engelsk", + "Puzzle.country2City1": "Berlin", + "Puzzle.cities": "byer:", + "Puzzle.country2City2": "München" +} diff --git a/apps/json/nl.json b/apps/json/nl.json new file mode 100644 index 000000000..00738f729 --- /dev/null +++ b/apps/json/nl.json @@ -0,0 +1,151 @@ +{ + "@metadata": { + "authors": [ + "Moorooboorai", + "Siebrand" + ] + }, + "Apps.subtitle": "een visuele programmeeromgeving", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Bekijk de gemaakte JavaScriptcode.", + "Apps.linkTooltip": "Opslaan en koppelen naar blokken.", + "Apps.runTooltip": "Voer het programma uit dat met de blokken in de werkruimte is gemaakt.", + "Apps.runProgram": "Programma uitvoeren", + "Apps.resetProgram": "Opnieuw instellen", + "Apps.dialogOk": "OK", + "Apps.dialogCancel": "Annuleren", + "Apps.catLogic": "Logica", + "Apps.catLoops": "Lussen", + "Apps.catMath": "Formules", + "Apps.catText": "Tekst", + "Apps.catLists": "Lijsten", + "Apps.catColour": "Kleur", + "Apps.catVariables": "Variabelen", + "Apps.catProcedures": "Procedures", + "Apps.httpRequestError": "Er is een probleem opgetreden tijdens het verwerken van het verzoek.", + "Apps.linkAlert": "Deel uw blokken via deze koppeling:\n\n%1", + "Apps.hashError": "\"%1\" komt helaas niet overeen met een opgeslagen bestand.", + "Apps.xmlError": "Uw opgeslagen bestand kan niet geladen worden. Is het misschien gemaakt met een andere versie van Blockly?", + "Apps.listVariable": "lijst", + "Apps.textVariable": "tekst", + "Code.badXml": "Fout tijdens het verwerken van de XML:\n%1\n\nSelecteer \"OK\" om uw wijzigingen te negeren of \"Annuleren\" om de XML verder te bewerken.", + "Code.badCode": "Programmafout:\n%1", + "Code.timeout": "Het maximale aantal iteraties is overschreden.", + "Code.discard": "Alle %1 blokken verwijderen?", + "Code.title": "Code", + "Code.blocks": "Blokken", + "Code.trashTooltip": "Alle blokken verwijderen", + "Graph.title": "Grafische rekenmachine", + "Maze.moveForward": "vooruit", + "Maze.turnLeft": "linksaf", + "Maze.turnRight": "rechtsaf", + "Maze.doCode": "uitvoeren", + "Maze.elseCode": "anders", + "Maze.helpIfElse": "\"als-dan\"-blokken doen het ene of het andere.", + "Maze.pathAhead": "doorgaan als er een pad is", + "Maze.pathLeft": "als pad naar links", + "Maze.pathRight": "als pad naar rechts", + "Maze.repeatUntil": "herhalen totdat", + "Maze.moveForwardTooltip": "Hiermee wordt Pegman \u00e9\u00e9n vakje vooruit verplaatst.", + "Maze.turnTooltip": "Hiermee draait Pegman 90 graden naar links of naar rechts.", + "Maze.ifTooltip": "Als er een pad in de aangegeven richting is, voer dan wat handelingen uit.", + "Maze.ifelseTooltip": "Als er een pad is in de aangegeven richting, voer dan het eerste blok van handelingen uit, anders het tweede blok.", + "Maze.whileTooltip": "Herhaal de ingesloten handelingen totdat het eindpunt is bereikt.", + "Maze.capacity0": "U hebt %0 blokken over.", + "Maze.capacity1": "U hebt %1 blok over.", + "Maze.capacity2": "U hebt %2 blokken over.", + "Maze.nextLevel": "Gefeliciteerd! Bent u klaar om verder te gaan naar niveau %1?", + "Maze.finalLevel": "Gefeliciteerd! U hebt het laatste niveau opgelost.", + "Maze.maze": "Doolhof", + "Maze.runTooltip": "Zorgt ervoor dat de speler doet wat de blokken voorschrijven.", + "Maze.resetTooltip": "Zet de speler terug naar het begin van het doolhof.", + "Maze.helpStack": "Stop een paar 'ga vooruit' instructies samen en help me op mijn doel te bereiken.", + "Maze.helpOneTopBlock": "Op dit niveau moet u alle blokken uit de witte werkruimte opstapelen.", + "Maze.helpRun": "Voer uw programma uit en kijk wat er gebeurt.", + "Maze.helpReset": "Uw programma heeft het doolhof niet opgelost. Klik op \"Opnieuw instellen\" en probeert het opnieuw.", + "Maze.helpRepeat": "Computers hebben een beperkt geheugen. Ga naar het einde van dit pad door maximaal twee blokken te gebruiken. Gebruik \"herhalen\" om een blok meerdere keren uit te voeren.", + "Maze.helpCapacity": "U hebt alle blokken voor dit niveau gebruikt. Om een nieuw blok te maken, moet u eerst een bestaand blok.", + "Maze.helpRepeatMany": "U kunt meer dan \u00e9\u00e9n blok toevoegen binnen een \"herhalen\"-blok", + "Maze.helpSkins": "Kies uw favoriete speler uit dit menu.", + "Maze.helpIf": "Het blok \"als\" doet alleen iets als de voorwaarde waar is. Probeer naar link te draaien als er een pad naar links is.", + "Maze.helpMenu": "Klik op %1 in het blok \"als\" om de voorwaarde te wijzigen.", + "Maze.helpWallFollow": "Kunt u dit ingewikkelde doolhof oplossen? Probeer de linkermuur te volgen. Dit is een opdracht voor gevorderde programmeurs!", + "Plane.rows": "Rijen: %1", + "Plane.getRows": "rijen (%1)", + "Plane.rows1": "Rijen 1e klas: %1", + "Plane.getRows1": "Rijen 1e klas (%1)", + "Plane.rows2": "Rijen 2e klas: %1", + "Plane.getRows2": "Rijen 2e klas (%1)", + "Plane.seats": "Zitplaatsen: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "stoelen=", + "Plane.plane": "Vliegtuig", + "Plane.description1": "Een vliegtuig heeft een aantal rijen met stoelen. Iedere rij heeft vier stoelen.", + "Plane.description2": "Een vliegtuig heeft twee stoelen in de cockpit (voor de piloot en de copiloot) en een aantal rijen met stoelen voor passagiers. Iedere rij bevat vier stoelen.", + "Plane.description3": "Een vliegtuig heeft twee stoelen in de cockpit (voor de piloot en de copiloot) en een aantal rijen voor 1e klasse en 2e klasse passagiers. Iedere rij in de 1e klasse heeft vier stoelen. Iedere rij in de 2e klasse heeft vijf stoelen.", + "Plane.instructions": "Maak hieronder een formule die het totale aantal stoelen in het vliegtuig berekent als het aantal rijen hierboven wordt aangepast.", + "Puzzle.country1": "Australi\u00eb", + "Puzzle.country1Language": "Engels", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://nl.wikipedia.org/wiki/Australi\u00eb", + "Puzzle.country2": "Duitsland", + "Puzzle.country2Language": "Duits", + "Puzzle.country2City1": "Berlijn", + "Puzzle.country2City2": "M\u00fcnchen", + "Puzzle.country2HelpUrl": "http://nl.wikipedia.org/wiki/Duitsland", + "Puzzle.country3": "China", + "Puzzle.country3Language": "Chinees", + "Puzzle.country3City1": "Beijing", + "Puzzle.country3City2": "Shanghai", + "Puzzle.country3HelpUrl": "http://nl.wikipedia.org/wiki/China", + "Puzzle.country4": "Brazili\u00eb", + "Puzzle.country4Language": "Portugees", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "S\u00e3o Paulo", + "Puzzle.country4HelpUrl": "http://nl.wikipedia.org/wiki/Brazili\u00eb", + "Puzzle.flag": "vlag:", + "Puzzle.language": "taal:", + "Puzzle.languageChoose": "kies...", + "Puzzle.cities": "steden:", + "Puzzle.error0": "Perfect\nAlle %1 blokken zijn correct.", + "Puzzle.error1": "Bijna! E\u00e9n blok is onjuist.", + "Puzzle.error2": "%1 blokken zijn onjuist.", + "Puzzle.tryAgain": "Het gemarkeerde blok is niet correct.\nBlijf het proberen.", + "Puzzle.title": "Puzzel", + "Puzzle.help": "Hulp", + "Puzzle.checkAnswers": "Antwoorden controleren", + "Puzzle.helpText": "Koppel de vlag, kies de taal en maak een stapel van de steden voor ieder land (groen).", + "Turtle.moveTooltip": "Verplaatst de schildpad vooruit of achteruit met het ingestelde aantal stappen.", + "Turtle.moveForward": "aantal vooruit", + "Turtle.moveBackward": "aantal achteruit", + "Turtle.turnTooltip": "Draait de schildpad naar link of naar rechts met het opgegeven aantal graden.", + "Turtle.turnRight": "rechts draaien,", + "Turtle.turnLeft": "links draaien", + "Turtle.widthTooltip": "Wijzigt de breedte van de pen.", + "Turtle.setWidth": "breedte instellen op", + "Turtle.colourTooltip": "Wijzigt de kleur van de pen.", + "Turtle.setColour": "kleur instellen op", + "Turtle.penTooltip": "Tilt de pen op of zet die neer, om te stoppen of te beginnen met tekenen.", + "Turtle.penUp": "pen omhoog", + "Turtle.penDown": "pen omlaag", + "Turtle.turtleVisibilityTooltip": "Maakt de schildpad zichtbaar of onzichtbaar (cirkel en pijl).", + "Turtle.hideTurtle": "schildpad verbergen", + "Turtle.showTurtle": "Schildpad weergeven", + "Turtle.printHelpUrl": "http://nl.wikipedia.org/wiki/Boekdrukkunst", + "Turtle.printTooltip": "Tekent tekst in de richting van de schildpad vanaf de huidige positie.", + "Turtle.print": "afdrukken", + "Turtle.fontHelpUrl": "http://nl.wikipedia.org/wiki/Lettertype", + "Turtle.fontTooltip": "Stelt het lettertype in voor tekst.", + "Turtle.font": "lettertype", + "Turtle.fontSize": "lettergrootte", + "Turtle.fontNormal": "normaal", + "Turtle.fontBold": "vet", + "Turtle.fontItalic": "cursief", + "Turtle.unloadWarning": "Als u deze pagina verlaat, gaat uw werk verloren.", + "Turtle.title": "Schildpadtekeningen", + "Turtle.runTooltip": "Laat de schildpad doen wat de blokken opdragen.", + "Turtle.captureTooltip": "De tekening opslaan.", + "Turtle.imgFilename": "drawing.png", + "Turtle.catTurtle": "Schildpad" +} \ No newline at end of file diff --git a/apps/json/oc.json b/apps/json/oc.json new file mode 100644 index 000000000..8a996d81f --- /dev/null +++ b/apps/json/oc.json @@ -0,0 +1,139 @@ +{ + "@metadata": { + "authors": [ + "Cedric31" + ] + }, + "Apps.subtitle": "un environament de programacion visual", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Veire lo c\u00f2de JavaScript generat.", + "Apps.linkTooltip": "Salva e liga als bl\u00f2ts.", + "Apps.runTooltip": "Aviar lo programa definit pels bl\u00f2ts dins l\u2019espaci de trabalh.", + "Apps.runProgram": "Executa lo programa", + "Apps.resetProgram": "Re\u00efnicializar", + "Apps.dialogOk": "D'ac\u00f2rdi", + "Apps.dialogCancel": "Anullar", + "Apps.catLogic": "Logic", + "Apps.catLoops": "Boclas", + "Apps.catMath": "Math", + "Apps.catText": "T\u00e8xte", + "Apps.catLists": "Listas", + "Apps.catColour": "Color", + "Apps.catVariables": "Variablas", + "Apps.catProcedures": "Proceduras", + "Apps.httpRequestError": "I a agut un probl\u00e8ma amb la demanda.", + "Apps.linkAlert": "Partejatz v\u00f2stres bl\u00f2ts gr\u00e0cia a aqueste ligam :\n\n%1", + "Apps.hashError": "O planh\u00e8m, '%1' correspond pas a un fichi\u00e8r Blockly salvament.", + "Apps.xmlError": "Impossible de cargar lo fichi\u00e8r de salvament. Benl\u00e8u qu'es estat creat amb una autra version de Blockly ?", + "Apps.listVariable": "lista", + "Apps.textVariable": "t\u00e8xte", + "Code.badXml": "Error d\u2019analisi del XML :\n%1\n\nAbandonar las modificacions\u202f?", + "Code.badCode": "Error del programa :\n%1", + "Code.timeout": "Nombre maximum d\u2019iteracions d\u2019execucion depassat.", + "Code.discard": "Suprimir totes los %1 bl\u00f2ts\u202f?", + "Code.title": "C\u00f2de", + "Code.blocks": "Bl\u00f2ts", + "Code.trashTooltip": "Getar totes los bl\u00f2ts.", + "Graph.title": "Calculadoira grafica", + "Maze.moveForward": "avan\u00e7a", + "Maze.turnLeft": "vira a esqu\u00e8rra", + "Maze.turnRight": "vira a drecha", + "Maze.doCode": "far", + "Maze.elseCode": "siquenon", + "Maze.helpIfElse": "Un bl\u00f2t 'Se-Siquenon' executa una causa o una autra.", + "Maze.pathAhead": "se camin davant", + "Maze.pathLeft": "se camin cap a esqu\u00e8rra", + "Maze.pathRight": "se camin cap a drecha", + "Maze.repeatUntil": "repet\u00eds fins a", + "Maze.moveForwardTooltip": "Fa avan\u00e7ar s\u00e9nher Pegman en avant d'un espaci.", + "Maze.turnTooltip": "Fa virar s\u00e9nher Pegman a esqu\u00e8rra o a drecha de 90 grases.", + "Maze.ifTooltip": "Se i a un camin dins la direccion especificada, alara efectua aquelas accions.", + "Maze.ifelseTooltip": "Se i a un camin dins la direccion especificada, alara fas\u00e8tz lo premi\u00e8r bl\u00f2t d'accions. Siquenon fas\u00e8tz lo segond bl\u00f2t d'accions.", + "Maze.whileTooltip": "Repet\u00edse los bl\u00f2ts que son a l'interior fins a at\u00e9nher la t\u00f2ca.", + "Maze.capacity0": "Te dem\u00f2ra %0 bl\u00f2t.", + "Maze.capacity1": "Te dem\u00f2ra %1 bl\u00f2t.", + "Maze.capacity2": "Te dem\u00f2ran %2 bl\u00f2ts.", + "Maze.nextLevel": "\u00d2sca ! S\u00e8tz pr\u00e8st pel niv\u00e8l %1?", + "Maze.finalLevel": "\u00d2sca ! As acabat lo darri\u00e8r niv\u00e8l.", + "Maze.maze": "Laberint", + "Maze.runTooltip": "Far far al jogaire \u00e7\u00f2 que los bl\u00f2ts dison.", + "Maze.resetTooltip": "Repla\u00e7ar lo jogaire al comen\u00e7ament del laberint.", + "Maze.helpStack": "Empilar dos bl\u00f2ts d'instruccions 'avan\u00e7a' per m'ajudar a at\u00e9nher ma t\u00f2ca.", + "Maze.helpOneTopBlock": "Dins aqueste niv\u00e8l, av\u00e8tz besonh d'empilar los bl\u00f2ts los uns en dess\u00fas dels autres dins la z\u00f2na de trabalh blanca.", + "Maze.helpRepeat": "Los ordenadors an pas gaire de mem\u00f2ria. Utilizatz solament dos bl\u00f2ts per at\u00e9nher la t\u00f2ca. Utilizatz lo bl\u00f2t 'repet\u00eds' per executar un bl\u00f2t mai d'un c\u00f2p.", + "Maze.helpRepeatMany": "Atenh la t\u00f2ca en utilizant solament cinc bl\u00f2ts.", + "Plane.rows": "Linhas : %1", + "Plane.getRows": "linhas (%1)", + "Plane.rows1": "linhas de primi\u00e8ra classa : %1", + "Plane.getRows1": "linhas de primi\u00e8ra classa (%1)", + "Plane.rows2": "linhas de segonda classa : %1", + "Plane.getRows2": "linhas de segonda classa (%1)", + "Plane.seats": "S\u00e8tis : %1", + "Plane.placeholder": "?", + "Plane.setSeats": "s\u00e8tis =", + "Plane.plane": "Avion", + "Puzzle.country1": "Austr\u00e0lia", + "Puzzle.country1Language": "Angl\u00e9s", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://oc.wikipedia.org/wiki/Austr%C3%A0lia", + "Puzzle.country2": "Alemanha", + "Puzzle.country2Language": "Alemand", + "Puzzle.country2City1": "Berlin", + "Puzzle.country2City2": "Munich", + "Puzzle.country2HelpUrl": "http://oc.wikipedia.org/wiki/Alemanha", + "Puzzle.country3": "Chine", + "Puzzle.country3Language": "Chin\u00e9s", + "Puzzle.country3City1": "Pequin", + "Puzzle.country3City2": "Shanghai", + "Puzzle.country3HelpUrl": "http://oc.wikipedia.org/wiki/Republica_Populara_de_China", + "Puzzle.country4": "Brasil", + "Puzzle.country4Language": "Portugu\u00e9s", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "S\u00e3o Paulo", + "Puzzle.country4HelpUrl": "http://oc.wikipedia.org/wiki/Brasil", + "Puzzle.flag": "bandi\u00e8ra :", + "Puzzle.language": "lenga :", + "Puzzle.languageChoose": "causiss\u00e8tz...", + "Puzzle.cities": "vilas :", + "Puzzle.error0": "Perfi\u00e8ch ! Totes los %1 bl\u00f2ts son corr\u00e8ctes.", + "Puzzle.error1": "Gaireben ! Un bl\u00f2t es incorr\u00e8cte.", + "Puzzle.error2": "%1 bl\u00f2ts son incorr\u00e8ctes.", + "Puzzle.tryAgain": "Lo bl\u00f2t en susbrilhan\u00e7a es incorr\u00e8cte. Tornatz ensajar.", + "Puzzle.title": "Puzzle", + "Puzzle.help": "Ajuda", + "Puzzle.checkAnswers": "Verificatz las responsas", + "Puzzle.helpText": "Per cada pa\u00eds (en verd), estaca sa bandi\u00e8ra, caus\u00eds sa lenga, e fa un empilatge de sas vilas.", + "Turtle.moveTooltip": "Despla\u00e7a la tortuga en avant o en arri\u00e8r de la quantitat indicada.", + "Turtle.moveForward": "avan\u00e7ar de", + "Turtle.moveBackward": "recuolar de", + "Turtle.turnTooltip": "Far virar la tortuga a esqu\u00e8rra o a drecha del nombre de grases indicat.", + "Turtle.turnRight": "virar a drecha de", + "Turtle.turnLeft": "virar a esqu\u00e8rra de", + "Turtle.widthTooltip": "Modificar la grossor de l'estil\u00f2.", + "Turtle.setWidth": "metre la grossor a", + "Turtle.colourTooltip": "Modificar la color de l'estil\u00f2.", + "Turtle.setColour": "metre la color a", + "Turtle.penTooltip": "Levar o pausar l'estil\u00f2, per arrestar o comen\u00e7ar de dessenhar.", + "Turtle.penUp": "levar l'estil\u00f2", + "Turtle.penDown": "pausar l'estil\u00f2", + "Turtle.turtleVisibilityTooltip": "Rend la tortuga (cercle e fl\u00e8cha) visibla o pas.", + "Turtle.hideTurtle": "amagar la tortuga", + "Turtle.showTurtle": "afichar la tortuga", + "Turtle.printHelpUrl": "http://en.wikipedia.org/wiki/Printing", + "Turtle.printTooltip": "Dessenha lo t\u00e8xte dins la direccion de la tortuga a son empla\u00e7ament.", + "Turtle.print": "ecrire", + "Turtle.fontHelpUrl": "http://en.wikipedia.org/wiki/Font", + "Turtle.fontTooltip": "Defin\u00eds la poli\u00e7a utilizada pel bl\u00f2t d\u2019escritura.", + "Turtle.font": "poli\u00e7a", + "Turtle.fontSize": "talha de la poli\u00e7a", + "Turtle.fontNormal": "normal", + "Turtle.fontBold": "gras", + "Turtle.fontItalic": "italica", + "Turtle.unloadWarning": "Quitar aquesta pagina provocar\u00e0 la p\u00e8rda de v\u00f2stre trabalh.", + "Turtle.title": "Tortuga dessenhaira", + "Turtle.runTooltip": "Far far a la tortuga \u00e7\u00f2 que dison los bl\u00f2ts.", + "Turtle.captureTooltip": "Enregistrar lo dessenh.", + "Turtle.imgFilename": "drawing.png", + "Turtle.catTurtle": "Tortuga" +} \ No newline at end of file diff --git a/apps/json/pa.json b/apps/json/pa.json new file mode 100644 index 000000000..55ba04d89 --- /dev/null +++ b/apps/json/pa.json @@ -0,0 +1,35 @@ +{ + "Puzzle.tryAgain": "ਉੱਭਰਿਆ ਹੋਇਆ ਬਲਾਕ ਗ਼ਲਤ ਹੈ।\nਕੋਸ਼ਿਸ਼ ਕਰਦੇ ਰਹੋ।", + "Puzzle.country3City2": "ਸ਼ੰਘਾਈ", + "Puzzle.country3HelpUrl": "http://pa.wikipedia.org/wiki/ਚੀਨ", + "Puzzle.country3Language": "ਚੀਨੀ", + "Puzzle.checkAnswers": "ਜੁਆਬ ਚੈੱਕ ਕਰੋ", + "Puzzle.language": "ਭਾਸ਼ਾ:", + "Apps.dialogOk": "ਠੀਕ ਹੈ।", + "Puzzle.title": "ਬੁਝਾਰਤ", + "Puzzle.country1HelpUrl": "http://pa.wikipedia.org/wiki/ਆਸਟਰੇਲੀਆ", + "Puzzle.languageChoose": "ਚੁਣੋ...", + "Puzzle.country4City2": "ਸਾਓ ਪਾਓਲੋ", + "Puzzle.country4City1": "ਰਿਓ ਡੀ ਜਨੇਰੋ", + "Puzzle.country4Language": "ਪੁਰਤਗਾਲੀ", + "Puzzle.helpText": "ਹਰੇਕ ਦੇਸ਼ (ਹਰਾ) ਲਈ, ਉਹਦਾ ਝੰਡਾ ਲਗਾਓ, ਉਹਦੀ ਭਾਸ਼ਾ ਚੁਣੋ ਅਤੇ ਉਹਦੇ ਸ਼ਹਿਰਾਂ ਦਾ ਢੇਰ ਬਣਾਓ।", + "Puzzle.flag": "ਝੰਡਾ:", + "Puzzle.country4HelpUrl": "http://pa.wikipedia.org/wiki/ਬ੍ਰਾਜ਼ੀਲ", + "Puzzle.error1": "ਬਸ ਹੋ ਗਿਆ ਸੀ! ਇੱਕ ਬਲਾਕ ਗ਼ਲਤ ਸੀ।", + "Puzzle.country3City1": "ਬੀਜਿੰਗ", + "Puzzle.country1City1": "ਮੈਲਬਰਨ", + "Puzzle.country1City2": "ਸਿਡਨੀ", + "Puzzle.country2Language": "ਗਰਮਨ", + "Puzzle.country3": "ਚੀਨ", + "Puzzle.country2": "ਜਰਮਨੀ", + "Puzzle.country1": "ਆਸਟਰੇਲੀਆ", + "Puzzle.country2HelpUrl": "http://pa.wikipedia.org/wiki/ਜਰਮਨੀ", + "Puzzle.error0": "ਬਹੁਤ ਵਧੀਆ!\nਸਾਰੇ $1 ਬਲਾਕ ਸਹੀ ਹਨ।", + "Puzzle.country4": "ਬ੍ਰਾਜ਼ੀਲ", + "Puzzle.error2": "%1 ਬਲਾਕ ਗ਼ਲਤ ਹਨ।", + "Puzzle.help": "ਮਦਦ", + "Puzzle.country1Language": "ਅੰਗਰੇਜ਼ੀ", + "Puzzle.country2City1": "ਬਰਲਿਨ", + "Puzzle.cities": "ਸ਼ਹਿਰ:", + "Puzzle.country2City2": "ਮਿਊਨਿਖ" +} diff --git a/apps/json/pl.json b/apps/json/pl.json new file mode 100644 index 000000000..1a3ff6e35 --- /dev/null +++ b/apps/json/pl.json @@ -0,0 +1,127 @@ +{ + "@metadata": { + "authors": [ + "Chrumps", + "Faren", + "Ty221" + ] + }, + "Apps.subtitle": "graficzne \u015brodowisko programistyczne", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Zobacz wygenerowany kod JavaScript.", + "Apps.linkTooltip": "Zapisz i podlinkuj do blok\u00f3w", + "Apps.runTooltip": "Uruchom program zdefinowany przez bloki w obszarze roboczym", + "Apps.runProgram": "Uruchom Program", + "Apps.resetProgram": "Zresetuj", + "Apps.dialogOk": "OK", + "Apps.dialogCancel": "Anuluj", + "Apps.catLogic": "Logika", + "Apps.catLoops": "P\u0119tle", + "Apps.catMath": "Matematyka", + "Apps.catText": "Tekst", + "Apps.catLists": "Listy", + "Apps.catColour": "Kolor", + "Apps.catVariables": "Zmienne", + "Apps.catProcedures": "Procedury", + "Apps.httpRequestError": "Wyst\u0105pi\u0142 problem z za\u017c\u0105daniem.", + "Apps.linkAlert": "Udpost\u0119pnij swoje bloki korzystaj\u0105c z poni\u017cszego linku : \n\n\n%1", + "Apps.hashError": "Przepraszamy, '%1' nie odpowiada z jakimkolwiek zapisanym programem.", + "Apps.xmlError": "Nie mo\u017cna za\u0142adowa\u0107 zapisanego pliku. By\u0107 mo\u017ce zosta\u0142 utworzony za pomoc\u0105 innej wersji Blockly?", + "Apps.listVariable": "lista", + "Apps.textVariable": "tekst", + "Code.badXml": "B\u0142\u0105d parsowania XML : \n%1\n\nZaznacz 'OK' aby odrzuci\u0107 twoje zmiany lub 'Cancel', \u017ceby w przysz\u0142o\u015bci edytowa\u0107 XML.", + "Code.badCode": "B\u0142\u0105d programu:\n%1", + "Code.timeout": "Maksymalna liczba iteracji wykonywa\u0144 przekroczona", + "Code.discard": "Usun\u0105\u0107 wszystkie %1 bloki?", + "Code.title": "Kod", + "Code.blocks": "Bloki", + "Code.trashTooltip": "Odrzu\u0107 wszystkie bloki.", + "Graph.title": "Kalkulator graficzny", + "Maze.moveForward": "id\u017a naprz\u00f3d", + "Maze.turnLeft": "skr\u0119\u0107 w lewo", + "Maze.turnRight": "skr\u0119\u0107 w prawo", + "Maze.doCode": "Wykonaj", + "Maze.elseCode": "W innym wypadku", + "Maze.helpIfElse": "Bloki \"if-else (je\u017celi-lub)\" bed\u0105 wykonywa\u0107 jedn\u0105 czynno\u015b\u0107 lub inn\u0105 czynno\u015b\u0107.", + "Maze.pathAhead": "je\u015bli droga prowadzi prosto", + "Maze.pathLeft": "Je\u015bli \u015bcie\u017cka w lewo", + "Maze.pathRight": "Je\u015bli \u015bcie\u017cka w prawo", + "Maze.repeatUntil": "Powt\u00f3rz", + "Maze.moveForwardTooltip": "Porusza gracza do przodu o jedn\u0105 przestrze\u0144", + "Maze.turnTooltip": "Obraca gracza w lewo lub prawo o 90 stopni.", + "Maze.ifTooltip": "Je\u015bli istnieje \u015bcie\u017cka jest w okre\u015blonym kierunku, wykonaj jakie\u015b akcje", + "Maze.ifelseTooltip": "Je\u015bli istnieje \u015bcie\u017cka jest w okre\u015blonym kierunku, wykonaj pierwszy blok akcji. W innym wypadku wykonaj drugi blok akcji", + "Maze.whileTooltip": "Powtarza\u0107 za\u0142\u0105czone kroki, dop\u00f3ki punkt nie zostanie osi\u0105gni\u0119ty.", + "Maze.capacity0": "Masz %0 pozosta\u0142ych blok\u00f3w.", + "Maze.capacity1": "Masz %1 pozosta\u0142y blok.", + "Maze.capacity2": "Masz %2 pozosta\u0142e(ych) bloki(\u00f3w).", + "Maze.nextLevel": "Gratulacje! Czy jeste\u015b gotowy, aby przej\u015b\u0107 do poziomu %1?", + "Maze.finalLevel": "Gratulacje! Rozwi\u0105za\u0142e\u015b ko\u0144cowy poziom.", + "Maze.maze": "Labirynt", + "Maze.helpStack": "Ustaw kilka polece\u0144 'id\u017a naprz\u00f3d' jedno po drugi abym doszed\u0142 do celu.", + "Maze.helpOneTopBlock": "Na tym poziomie, musisz u\u0142o\u017cy\u0107 razem wszystkie bloki w bia\u0142ym obszarze roboczym.", + "Maze.helpRepeat": "Komputery maj\u0105 ograniczon\u0105 pami\u0119\u0107. Dotrzyj do ko\u0144ca tej \u015bcie\u017cki za pomoc\u0105 tylko dw\u00f3ch blok\u00f3w. U\u017cyj \"powt\u00f3rz\" aby uruchomi\u0107 blok wi\u0119cej ni\u017c raz.", + "Maze.helpRepeatMany": "Osi\u0105gnij cel u\u017cywaj\u0105c tylko pi\u0119ciu blok\u00f3w.", + "Maze.helpIf": "Blok \"if (je\u017celi)\" wykona okre\u015blon\u0105 czynno\u015b\u0107 tylko kiedy wyra\u017cenie warunkowe jest prawdziwe. Spr\u00f3buj p\u00f3j\u015b\u0107 w lewo je\u015bli \u015bcie\u017cka jest w lewo.", + "Maze.helpWallFollow": "Czy dasz rad\u0119 przej\u015b\u0107 ten trudny labirynt? Wypr\u00f3bnuj metod\u0119 trzymania si\u0119 lew\u0105 r\u0119k\u0105 \u015bciany. Tylko dla zaawansowanych programist\u00f3w!", + "Plane.rows": "Wiersze: %1", + "Plane.getRows": "wiersze (%1)", + "Plane.placeholder": "?", + "Plane.setSeats": "miejsc =", + "Plane.plane": "Samolot", + "Plane.description1": "Samolot ma kilka rz\u0119d\u00f3w siedze\u0144 pasa\u017cer\u00f3w. Ka\u017cdy rz\u0105d zawiera cztery miejsca.", + "Puzzle.country1": "Australia", + "Puzzle.country1Language": "Angielski", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://pl.wikipedia.org/wiki/Australia", + "Puzzle.country2": "Niemcy", + "Puzzle.country2Language": "Niemiecki", + "Puzzle.country2City1": "Berlin", + "Puzzle.country2City2": "Monachium", + "Puzzle.country2HelpUrl": "http://pl.wikipedia.org/wiki/Niemcy", + "Puzzle.country3": "Chiny", + "Puzzle.country3Language": "Chi\u0144ski", + "Puzzle.country3City1": "Pekin", + "Puzzle.country3City2": "Szanghaj", + "Puzzle.country3HelpUrl": "http://pl.wikipedia.org/wiki/Chiny", + "Puzzle.country4": "Brazylia", + "Puzzle.country4Language": "Portugalski", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "S\u00e3o Paulo", + "Puzzle.country4HelpUrl": "http://pl.wikipedia.org/wiki/Brazylia", + "Puzzle.flag": "flaga:", + "Puzzle.language": "j\u0119zyk:", + "Puzzle.languageChoose": "wybierz...", + "Puzzle.cities": "miasta:", + "Puzzle.error0": "Doskonale!\nWszystkie %1 bloki s\u0105 poprawne.", + "Puzzle.error1": "Prawie! Jeden blok jest niepoprawny.", + "Puzzle.error2": "%1 blok\u00f3w jest nieprawid\u0142owych.", + "Puzzle.tryAgain": "Zaznaczony blok nie jest poprawny.\nSpr\u00f3buj jeszcze raz.", + "Puzzle.title": "Puzzle", + "Puzzle.help": "Pomoc", + "Puzzle.checkAnswers": "Sprawd\u017a Odpowiedzi", + "Puzzle.helpText": "Dla ka\u017cdego kraju (zielony), za\u0142\u0105cz jego flag\u0119, wybierz j\u0119zyk urz\u0119dowy, i okre\u015bl miasta, znajduj\u0105cych si\u0119 w tym kraju.", + "Turtle.turnTooltip": "Obr\u00f3\u0107 \u017c\u00f3\u0142wia w lewo lub w prawo o okre\u015blon\u0105 liczb\u0119 stopni.", + "Turtle.turnRight": "skr\u0119ci\u0107 w prawo przez", + "Turtle.turnLeft": "skr\u0119ci\u0107 w lewo przez", + "Turtle.widthTooltip": "Zmienia szeroko\u015b\u0107 pi\u00f3ra.", + "Turtle.setWidth": "ustaw szeroko\u015b\u0107 na", + "Turtle.colourTooltip": "Zmienia kolor pi\u00f3ra.", + "Turtle.setColour": "ustaw kolor na", + "Turtle.turtleVisibilityTooltip": "Sprawia \u017ce \u017c\u00f3\u0142w (zielone k\u00f3\u0142ko i strza\u0142ka) staje si\u0119 widoczny lub niewidoczny.", + "Turtle.hideTurtle": "ukryj \u017c\u00f3\u0142wia", + "Turtle.showTurtle": "poka\u017c \u017c\u00f3\u0142wia", + "Turtle.printHelpUrl": "http://pl.wikipedia.org/wiki/Druk", + "Turtle.print": "drukuj", + "Turtle.font": "czcionka", + "Turtle.fontSize": "rozmiar czcionki", + "Turtle.fontNormal": "normalny", + "Turtle.fontBold": "pogrubienie", + "Turtle.fontItalic": "kursywa", + "Turtle.unloadWarning": "Pozostawienie tej strony spowoduje utrat\u0119 pracy.", + "Turtle.title": "Grafiki \u017b\u00f3\u0142wia", + "Turtle.captureTooltip": "Zapisz rysunek.", + "Turtle.imgFilename": "drawing.png", + "Turtle.catTurtle": "\u017b\u00f3\u0142w" +} \ No newline at end of file diff --git a/apps/json/pms.json b/apps/json/pms.json new file mode 100644 index 000000000..950b1c173 --- /dev/null +++ b/apps/json/pms.json @@ -0,0 +1,150 @@ +{ + "@metadata": { + "authors": [ + "Borich\u00e8t" + ] + }, + "Apps.subtitle": "n'ambient \u00ebd programassion visual", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "V\u00ebdde \u00ebl c\u00f2des JavaScript gener\u00e0.", + "Apps.linkTooltip": "Argistr\u00e9 e lij\u00e9 ai bl\u00f2ch.", + "Apps.runTooltip": "F\u00e9 and\u00e9 \u00ebl programa defin\u00ec dai bl\u00f2ch ant l\u00eb spassi \u00ebd travaj.", + "Apps.runProgram": "F\u00e9 and\u00e9 \u00ebl programa", + "Apps.resetProgram": "But\u00e9 torna coma al prinsipi", + "Apps.dialogOk": "Va bin", + "Apps.dialogCancel": "Anul\u00e9", + "Apps.catLogic": "L\u00f2gica", + "Apps.catLoops": "Liasse", + "Apps.catMath": "Matem\u00e0tica", + "Apps.catText": "Test", + "Apps.catLists": "Liste", + "Apps.catColour": "Color", + "Apps.catVariables": "Vari\u00e0bij", + "Apps.catProcedures": "Procedure", + "Apps.httpRequestError": "A-i \u00e9 staje un problema con l'arcesta.", + "Apps.linkAlert": "Ch'a partagia ij s\u00f2 bl\u00f2ch grassie a sta liura: %1", + "Apps.hashError": "An d\u00ebspias, '%1% a cor\u00ebspond a gnun programa salv\u00e0.", + "Apps.xmlError": "A l'\u00e9 nen podusse cari\u00e9 so archivi salv\u00e0. Miraco a l'\u00e9 st\u00e0it cre\u00e0 con na version diferenta \u00ebd Blockly?", + "Apps.listVariable": "lista", + "Apps.textVariable": "test", + "Code.badXml": "Eror d'an\u00e0lisi dl'XML:\n%1\n\nSelession\u00e9 'Va bin' p\u00ebr lass\u00e9 perde toe mod\u00ecfiche o 'Anul\u00e9' p\u00ebr modifich\u00e9 ancora l'XML.", + "Code.badCode": "Eror d\u00ebl programa:\n%1", + "Code.timeout": "N\u00f9mer m\u00e0ssim d'arpetission d'esecussion sorpass\u00e0.", + "Code.discard": "Scancel\u00e9 tuti ij %1 bl\u00f2ch?", + "Code.title": "C\u00f2des", + "Code.blocks": "Bl\u00f2ch", + "Code.trashTooltip": "Scart\u00e9 tuti ij bl\u00f2ch.", + "Graph.title": "Calculatris gr\u00e0fica", + "Maze.moveForward": "and\u00e9 drit", + "Maze.turnLeft": "voltesse a snistra", + "Maze.turnRight": "voltesse a drita", + "Maze.doCode": "f\u00e9", + "Maze.elseCode": "opura", + "Maze.helpIfElse": "Un bl\u00f2ch si-opura a far\u00e0 na c\u00f2sa u l'\u00e0utra.", + "Maze.pathAhead": "se s\u00ebnt\u00e9 d\u00eb dnans", + "Maze.pathLeft": "se s\u00ebnt\u00e9 a snistra", + "Maze.pathRight": "se s\u00ebnt\u00e9 a drita", + "Maze.repeatUntil": "arpete fin-a a", + "Maze.moveForwardTooltip": "F\u00e0 and\u00e9 \u00ebl giugador anans \u00ebd n\u00eb spassi.", + "Maze.turnTooltip": "F\u00e9 volt\u00e9 \u00ebl giugador a snistra o a drita \u00ebd 90 gr\u00e9.", + "Maze.ifTooltip": "S'a-i \u00e9 na stra ant la diression \u00ebspessific\u00e0, antlora fa ch\u00e8iche assion.", + "Maze.ifelseTooltip": "S'a-i \u00e9 na stra ant la diression \u00ebspessific\u00e0, antlora fa \u00ebl prim bl\u00f2ch d'assion. D\u00ebsn\u00f2, f\u00e0 \u00ebl second bl\u00f2ch d'assion.", + "Maze.whileTooltip": "Arpet j'assion contn\u00f9e fin-a a argionze \u00ebl pont final.", + "Maze.capacity0": "At resto %0 bl\u00f2ch.", + "Maze.capacity1": "At resta %1 bl\u00f2ch.", + "Maze.capacity2": "At resto %2 bl\u00f2ch.", + "Maze.nextLevel": "Brav! T'ses pront p\u00ebr and\u00e9 anans al livel %1?", + "Maze.finalLevel": "Brav! Tl'has livr\u00e0 \u00ebl livel final.", + "Maze.maze": "Labirint", + "Maze.runTooltip": "A f\u00e0 f\u00e9 al giugador l\u00f2n ch'a diso ij block.", + "Maze.resetTooltip": "Buta torna \u00ebl giugador al prinsipi d\u00ebl labirint.", + "Maze.helpStack": "Ambaron-a un p\u00e0ira \u00ebd bl\u00f2ch 'va anans' p\u00ebr giuteme a argionze me but.", + "Maze.helpOneTopBlock": "An cost livel, it deve ambaron\u00e9 ij bl\u00f2ch un ansima a l'\u00e0utr ant la z\u00f2na \u00ebd travaj bianca.", + "Maze.helpRun": "F\u00e0 marc\u00e9 t\u00f2 programa p\u00ebr v\u00ebdde l\u00f2n ch'a-i suced.", + "Maze.helpReset": "T\u00f2 programa a l'ha nen arzolv\u00f9 \u00ebl labirint. Sgnaca 'But\u00e9 torna coma al prinsipi' e preuva torna.", + "Maze.helpRepeat": "J'ordinator a l'han na mem\u00f2ria limit\u00e0. Riva a la fin \u00ebd sa stra dovrand mach doi bl\u00f2ch. Deuvra 'arpet' p\u00ebr esegu\u00ec un bl\u00f2ch pi 'd na vira.", + "Maze.helpCapacity": "It l'has consum\u00e0 tuti ij bl\u00f2ch p\u00ebr cost livel. P\u00ebr cre\u00e9 un bl\u00f2ch neuv, tl'has prima damanca d\u00eb scancel\u00e9 un bl\u00f2ch esistent.", + "Maze.helpRepeatMany": "A peul but\u00e9 pi d'un bl\u00f2ch andrinta a 'n bl\u00f2ch \u00abarpete\u00bb.", + "Maze.helpSkins": "Ch'a serna s\u00f2 giugador prefer\u00ec da s\u00eb mn\u00f9.", + "Maze.helpIf": "Un bl\u00f2ch 'si' a far\u00e0 cheic\u00f2s mach si la condission a l'\u00e9 vera. Preuva a svolt\u00e9 a snistra s'a-i \u00e9 na stra a snistra.", + "Maze.helpMenu": "Sgnaca su %1 ant \u00ebl bl\u00f2ch 'si' p\u00ebr cang\u00e9 soa condission.", + "Maze.helpWallFollow": "Peul\u00ebs-to arz\u00f2lve cost labirint complic\u00e0? S\u00ebrca d'andeje dapress a la muraja a snistra. Mach p\u00ebr programator coj barbis!", + "Plane.rows": "Linie: %1", + "Plane.getRows": "linie (%1)", + "Plane.rows1": "linie \u00ebd prima classa: %1", + "Plane.getRows1": "linie \u00ebd prima classa (%1)", + "Plane.rows2": "linie \u00ebd seconda classa: %1", + "Plane.getRows2": "linie \u00ebd seconda classa (%1)", + "Plane.seats": "Sedij: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "sedij =", + "Plane.plane": "Avion", + "Plane.description1": "N'avion a l'ha un n\u00f9mer \u00ebd file \u00ebd sedij da pass\u00ebg\u00e9. Minca fila a l'ha quatr sedij.", + "Plane.description2": "N'avion a l'ha doi sedij ant la cabin-a \u00ebd pilotage (p\u00ebr \u00ebl pil\u00f2ta e \u00ebl c\u00f2-pil\u00f2ta), e un ch\u00e8ich n\u00f9mer \u00ebd file \u00ebd sedij pr'ij passag\u00e9. Minca fila a conten quatr sedij.", + "Plane.description3": "N'avion a l'ha doi sedij ant la cabin-a \u00ebd pilotage (p\u00ebr \u00ebl pil\u00f2ta e \u00ebl c\u00f2-pil\u00f2ta) e un ch\u00e8ich n\u00f9mer \u00ebd file \u00ebd sedij pr'ij passag\u00e9 \u00ebd prima e sconda classa. Minca fila \u00ebd prima classa a conten quatr sedij. Minca fila \u00ebd seconda classa a conten sinch sedij.", + "Plane.instructions": "Fabrich\u00e9 na f\u00f3rmola (s\u00ec-sota) ch'a fa 'l cont d\u00ebl n\u00f9mer total \u00ebd sedij ant l'avion cand che \u00ebl n\u00f9mer dle file a cangia (s\u00ec-dzora).", + "Puzzle.country1": "Australia", + "Puzzle.country1Language": "Angl\u00e8is", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://pms.wikipedia.org/wiki/Australia", + "Puzzle.country2": "Almagna", + "Puzzle.country2Language": "Alman", + "Puzzle.country2City1": "Berlin", + "Puzzle.country2City2": "M\u00f9nich", + "Puzzle.country2HelpUrl": "http://pms.wikipedia.org/wiki/G\u00ebrmania", + "Puzzle.country3": "Cin-a", + "Puzzle.country3Language": "Cin\u00e8is", + "Puzzle.country3City1": "Pechin", + "Puzzle.country3City2": "Shangai", + "Puzzle.country3HelpUrl": "http://pms.wikipedia.org/wiki/Cin-a", + "Puzzle.country4": "Brasil", + "Puzzle.country4Language": "Portugh\u00e8is", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "San P\u00e0ul", + "Puzzle.country4HelpUrl": "http://pms.wikipedia.org/wiki/Brasil", + "Puzzle.flag": "drap\u00f2:", + "Puzzle.language": "lenga:", + "Puzzle.languageChoose": "sern...", + "Puzzle.cities": "sit\u00e0:", + "Puzzle.error0": "P\u00ebrfet! Tuti ij %1 bl\u00f2ch a son giust.", + "Puzzle.error1": "Scasi! Un bl\u00f2ch a va nen bin.", + "Puzzle.error2": "%1 bl\u00f2ch a van nen bin.", + "Puzzle.tryAgain": "\u00cbl bl\u00f2ch evidensi\u00e0 a va nen bin. Preuva torna.", + "Puzzle.title": "S-ciapatesta", + "Puzzle.help": "Giut\u00e9", + "Puzzle.checkAnswers": "Contr\u00f2la le risp\u00f2ste", + "Puzzle.helpText": "P\u00ebr minca pais (an verd), tachje s\u00f2 drap\u00f2, sern soa lenga, e fa na col\u00f2na \u00ebd soe sit\u00e0.", + "Turtle.moveTooltip": "A bogia la bissa copera anans o andr\u00e9 dla quantit\u00e0 spessific\u00e0.", + "Turtle.moveForward": "and\u00e9 drit \u00ebd", + "Turtle.moveBackward": "and\u00e9 andar\u00e9 \u00ebd", + "Turtle.turnTooltip": "A f\u00e0 volt\u00e9 la bissa copera a snistra o a drita d\u00ebl n\u00f9mer \u00ebd gr\u00e9 spessific\u00e0.", + "Turtle.turnRight": "voltesse a drita \u00ebd", + "Turtle.turnLeft": "voltesse a snistra \u00ebd", + "Turtle.widthTooltip": "Modifich\u00e9 la largh\u00ebssa dla piuma.", + "Turtle.setWidth": "but\u00e9 la largh\u00ebssa a", + "Turtle.colourTooltip": "A cangia \u00ebl color \u00ebd la piuma.", + "Turtle.setColour": "but\u00e9 \u00ebl color a", + "Turtle.penTooltip": "A \u00e0ussa o a sbassa la piuma, p\u00ebr chit\u00e9 o ancamin\u00e9 a dissegn\u00e9.", + "Turtle.penUp": "auss\u00e9 la piuma", + "Turtle.penDown": "pog\u00e9 la piuma", + "Turtle.turtleVisibilityTooltip": "A rend la bissa copera (sercc e flecia) vis\u00ecbil o invis\u00ecbil.", + "Turtle.hideTurtle": "st\u00ebrm\u00e9 la bissa copera", + "Turtle.showTurtle": "mostr\u00e9 la bissa copera", + "Turtle.printHelpUrl": "http://en.wikipedia.org/wiki/Printing", + "Turtle.printTooltip": "A dissegna \u00ebl test ant la diression dla bissa copera a soa posission.", + "Turtle.print": "scrive", + "Turtle.fontHelpUrl": "http://en.wikipedia.org/wiki/Font", + "Turtle.fontTooltip": "A definiss \u00ebl car\u00e0ter dovr\u00e0 dal bl\u00f2ch d\u00eb scritura.", + "Turtle.font": "car\u00e0ter", + "Turtle.fontSize": "dimension dij car\u00e0ter", + "Turtle.fontNormal": "normal", + "Turtle.fontBold": "grass\u00e8t", + "Turtle.fontItalic": "corsiv", + "Turtle.unloadWarning": "Chit\u00e9 sta p\u00e0gina a caus\u00ebr\u00e0 la p\u00e8rdita \u00ebd s\u00f2 travaj.", + "Turtle.title": "Bissa copera dissegnatris", + "Turtle.runTooltip": "A-j fa f\u00e9 a la bissa copera l\u00f2n ch'a diso ij bl\u00f2ch.", + "Turtle.captureTooltip": "Argistr\u00e9 \u00ebl dissegn.", + "Turtle.imgFilename": "dissegn.png", + "Turtle.catTurtle": "Bissa copera" +} \ No newline at end of file diff --git a/apps/json/ps.json b/apps/json/ps.json new file mode 100644 index 000000000..594bbd6e6 --- /dev/null +++ b/apps/json/ps.json @@ -0,0 +1,32 @@ +{ + "Puzzle.country3City2": "شانګهای", + "Puzzle.country3HelpUrl": "http://en.wikipedia.org/wiki/China", + "Puzzle.country3Language": "چينايي", + "Puzzle.checkAnswers": "ځوابونه کره کول", + "Puzzle.language": "ژبه:", + "Apps.dialogOk": "ښه", + "Puzzle.country1HelpUrl": "http://en.wikipedia.org/wiki/Australia", + "Puzzle.languageChoose": "ټاکل...", + "Puzzle.country4City2": "ساو پاولو", + "Puzzle.country4City1": "رايو ډي جېنېرو", + "Puzzle.country4Language": "پارټوګيسي", + "Puzzle.flag": "رپی", + "Puzzle.country4HelpUrl": "http://en.wikipedia.org/wiki/Brazil", + "Puzzle.error1": "نژدې دی! يو بنديز سم نه دی.", + "Puzzle.country3City1": "بيجېنګ", + "Puzzle.country1City1": "مېلبورن", + "Puzzle.country1City2": "سېډني", + "Puzzle.country2Language": "جرمن", + "Puzzle.country3": "چين", + "Puzzle.country2": "جرمني", + "Puzzle.country1": "آسټراليا", + "Puzzle.country2HelpUrl": "http://en.wikipedia.org/wiki/Germany", + "Puzzle.error0": "ډېر ښه!\nټول %1 بنديزونه سم دي.", + "Puzzle.country4": "برازيل", + "Puzzle.error2": "%1 بنديزونه سم نه دي.", + "Puzzle.help": "لارښود", + "Puzzle.country1Language": "انګرېزي", + "Puzzle.country2City1": "برلين", + "Puzzle.cities": "ښارونه", + "Puzzle.country2City2": "ميونيښ" +} diff --git a/apps/json/pt-br.json b/apps/json/pt-br.json new file mode 100644 index 000000000..41cbc2377 --- /dev/null +++ b/apps/json/pt-br.json @@ -0,0 +1,154 @@ +{ + "@metadata": { + "authors": [ + "Cainamarques", + "Leosls", + "Luckas", + "Prilopes", + "Slovato" + ] + }, + "Apps.subtitle": "um ambiente de programa\u00e7\u00e3o visual", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Veja o c\u00f3digo JavaScript gerado.", + "Apps.linkTooltip": "Salvar e gerar link para os blocos.", + "Apps.runTooltip": "Executar o programa definido pelos blocos na \u00e1rea de trabalho.", + "Apps.runProgram": "Executar programa", + "Apps.resetProgram": "Reiniciar", + "Apps.dialogOk": "OK", + "Apps.dialogCancel": "Cancelar", + "Apps.catLogic": "L\u00f3gica", + "Apps.catLoops": "La\u00e7os", + "Apps.catMath": "Matem\u00e1tica", + "Apps.catText": "Texto", + "Apps.catLists": "Listas", + "Apps.catColour": "Cor", + "Apps.catVariables": "Vari\u00e1veis", + "Apps.catProcedures": "Procedimentos", + "Apps.httpRequestError": "Houve um problema com sua requisi\u00e7\u00e3o.", + "Apps.linkAlert": "Compartilhe seus blocos por este link:\n\n%1", + "Apps.hashError": "Desculpe, '%1' n\u00e3o corresponde a um programa salvo.", + "Apps.xmlError": "N\u00e3o foi poss\u00edvel carregar seu arquivo salvo. Talvez ele tenha sido criado com uma vers\u00e3o diferente do Blockly?", + "Apps.listVariable": "lista", + "Apps.textVariable": "texto", + "Code.badXml": "Erro ao analisar o XML:\n%1", + "Code.badCode": "Erro no programa:\n%1", + "Code.timeout": "M\u00e1ximo de itera\u00e7\u00f5es de execu\u00e7\u00e3o excedido.", + "Code.discard": "Apagar todos os %1 blocos?", + "Code.title": "C\u00f3digo", + "Code.blocks": "Blocos", + "Code.trashTooltip": "Descartar todos os blocos.", + "Graph.title": "Calculadora gr\u00e1fica", + "Maze.moveForward": "avan\u00e7ar", + "Maze.turnLeft": "vire \u00e0 esquerda", + "Maze.turnRight": "vire \u00e0 direita", + "Maze.doCode": "fa\u00e7a", + "Maze.elseCode": "sen\u00e3o", + "Maze.helpIfElse": "Blocos se-sen\u00e3o far\u00e3o uma coisa ou a outra.", + "Maze.pathAhead": "se caminho \u00e0 frente", + "Maze.pathLeft": "se caminho \u00e0 esquerda", + "Maze.pathRight": "se caminho \u00e0 direita", + "Maze.repeatUntil": "repetir at\u00e9", + "Maze.moveForwardTooltip": "Move o jogador um espa\u00e7o para frente.", + "Maze.turnTooltip": "Vira o jogador 90 graus para esquerda ou direita.", + "Maze.ifTooltip": "Se h\u00e1 um caminho na dire\u00e7\u00e3o especificada, ent\u00e3o fa\u00e7a algumas a\u00e7\u00f5es.", + "Maze.ifelseTooltip": "Se h\u00e1 um caminho na dire\u00e7\u00e3o especificada, ent\u00e3o fa\u00e7a o primeiro bloco de a\u00e7\u00f5es. Caso contr\u00e1rio, fa\u00e7a o segundo bloco de a\u00e7\u00f5es.", + "Maze.whileTooltip": "Repetir as a\u00e7\u00f5es inclusas at\u00e9 que o ponto final seja alcan\u00e7ado.", + "Maze.capacity0": "Restam %0 blocos.", + "Maze.capacity1": "Resta %1 bloco.", + "Maze.capacity2": "Restam %2 blocos.", + "Maze.nextLevel": "Parab\u00e9ns! Voc\u00ea est\u00e1 pronto para continuar no n\u00edvel %1?", + "Maze.finalLevel": "Parab\u00e9ns! Voc\u00ea resolveu a fase final.", + "Maze.maze": "Maze", + "Maze.runTooltip": "Faz o jogador executar o que os blocos dizem.", + "Maze.resetTooltip": "Coloca o jogador de volta ao in\u00edcio do labirinto.", + "Maze.helpStack": "Empilhe alguns blocos 'avan\u00e7ar' juntos para me ajudar a alcan\u00e7ar o objetivo.", + "Maze.helpOneTopBlock": "Neste n\u00edvel, voc\u00ea deve empilhar todos os blocos na \u00e1rea de trabalho branca.", + "Maze.helpRun": "Execute seu programa para ver o que acontece.", + "Maze.helpReset": "Seu programa n\u00e3o resolveu o labirinto. Aperte 'Reiniciar' e tente novamente.", + "Maze.helpRepeat": "Alcance o fim deste caminho usando apenas dois blocos. Use 'repetir at\u00e9' para executar um bloco mais de uma vez.", + "Maze.helpCapacity": "Voc\u00ea usou todos os blocos para este n\u00edvel. Para criar um novo bloco, voc\u00ea primeiro deve remover um bloco existente.", + "Maze.helpRepeatMany": "Voc\u00ea pode encaixar mais de um bloco dentro de um bloco 'repetir at\u00e9'.", + "Maze.helpSkins": "Escolha o seu jogador favorito neste menu.", + "Maze.helpIf": "Um bloco 'se' far\u00e1 alguma coisa apenas se a condi\u00e7\u00e3o for verdadeira. Tente virar \u00e0 esquerda se houver um caminho para a esquerda.", + "Maze.helpMenu": "Clique em %1 no bloco 'se' para mudar sua condi\u00e7\u00e3o.", + "Maze.helpWallFollow": "Voc\u00ea consegue resolver este labirinto complicado? Tente seguir a parede da m\u00e3o esquerda. Apenas para programadores avan\u00e7ados!", + "Plane.rows": "Fileiras: %1", + "Plane.getRows": "filas (%1)", + "Plane.rows1": "filas na primeira classe: %1", + "Plane.getRows1": "filas na primeira classe: (%1)", + "Plane.rows2": "filas na segunda classe: %1", + "Plane.getRows2": "filas na segunda classe (%1)", + "Plane.seats": "Assentos: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "assentos =", + "Plane.plane": "Avi\u00e3o", + "Plane.description1": "Um avi\u00e3o tem um n\u00famero de filas de assentos para os passageiros. Cada fila cont\u00e9m quatro assentos.", + "Plane.description2": "Um avi\u00e3o tem dois assentos na cabine de comando (para o piloto e o copiloto) e um n\u00famero de filas de assentos para os passageiros. Cada fila cont\u00e9m quatro assentos.", + "Plane.description3": "Um avi\u00e3o tem dois assentos na cabine de comando (para o piloto e o copiloto) e um n\u00famero de filas de assentos na primeira e na segunda classe. Cada fila da primeira classe cont\u00e9m quatro assentos. Cada fila da segunda classe cont\u00e9m cinco assentos.", + "Plane.instructions": "Elabore uma f\u00f3rmula (abaixo) que calcule o n\u00famero total de assentos no avi\u00e3o a medida que as filas s\u00e3o alteradas (acima).", + "Puzzle.country1": "Austr\u00e1lia", + "Puzzle.country1Language": "Ingl\u00eas", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://pt.wikipedia.org/wiki/Austr%C3%A1lia", + "Puzzle.country2": "Alemanha", + "Puzzle.country2Language": "Alem\u00e3o", + "Puzzle.country2City1": "Berlim", + "Puzzle.country2City2": "Munique", + "Puzzle.country2HelpUrl": "http://pt.wikipedia.org/wiki/Alemanha", + "Puzzle.country3": "China", + "Puzzle.country3Language": "Chin\u00eas", + "Puzzle.country3City1": "Pequim", + "Puzzle.country3City2": "Xangai", + "Puzzle.country3HelpUrl": "http://pt.wikipedia.org/wiki/Rep%C3%BAblica_Popular_da_China", + "Puzzle.country4": "Brasil", + "Puzzle.country4Language": "Portugu\u00eas", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "S\u00e3o Paulo", + "Puzzle.country4HelpUrl": "http://pt.wikipedia.org/wiki/Brasil", + "Puzzle.flag": "bandeira:", + "Puzzle.language": "l\u00edngua:", + "Puzzle.languageChoose": "escolha...", + "Puzzle.cities": "cidades:", + "Puzzle.error0": "Perfeito!\nTodos os %1 blocos est\u00e3o corretos.", + "Puzzle.error1": "Quase! Um bloco est\u00e1 incorreto.", + "Puzzle.error2": "%1 blocos est\u00e3o incorretos.", + "Puzzle.tryAgain": "O bloco destacado est\u00e1 incorreto. Continue tentando.", + "Puzzle.title": "Quebra-Cabe\u00e7a", + "Puzzle.help": "Ajuda", + "Puzzle.checkAnswers": "Checar respostas", + "Puzzle.helpText": "Para cada pa\u00eds (verde), anexe sua bandeira, escolha seu idioma e agrupe suas cidades.", + "Turtle.moveTooltip": "Move a tartaruga para frente ou para tr\u00e1s a quantidade especificada.", + "Turtle.moveForward": "avan\u00e7ar", + "Turtle.moveBackward": "mover para tr\u00e1s", + "Turtle.turnTooltip": "Gira a tartaruga para esquerda ou direita de acordo com o n\u00famero de graus especificado.", + "Turtle.turnRight": "vire \u00e0 direita", + "Turtle.turnLeft": "vire \u00e0 esquerda", + "Turtle.widthTooltip": "Muda o tamanho da caneta.", + "Turtle.setWidth": "configurar largura para", + "Turtle.colourTooltip": "Muda a cor da caneta.", + "Turtle.setColour": "Configurar cor para", + "Turtle.penTooltip": "Levanta ou abaixa a caneta, para parar ou voltar a desenhar.", + "Turtle.penUp": "levantar caneta", + "Turtle.penDown": "abaixar caneta", + "Turtle.turtleVisibilityTooltip": "Torna a tartaruga (c\u00edrculo e seta) vis\u00edvel ou invis\u00edvel.", + "Turtle.hideTurtle": "esconder tartaruga", + "Turtle.showTurtle": "mostrar tartaruga", + "Turtle.printHelpUrl": "http://pt.wikipedia.org/wiki/Impress%C3%A3o", + "Turtle.printTooltip": "Desenha texto na dire\u00e7\u00e3o da tartaruga em sua localiza\u00e7\u00e3o.", + "Turtle.print": "imprimir", + "Turtle.fontHelpUrl": "http://pt.wikipedia.org/wiki/Fonte_tipogr%C3%A1fica", + "Turtle.fontTooltip": "Configurar a fonte usada pelo bloco de impress\u00e3o na tela.", + "Turtle.font": "fonte", + "Turtle.fontSize": "tamanho da fonte", + "Turtle.fontNormal": "normal", + "Turtle.fontBold": "negrito", + "Turtle.fontItalic": "it\u00e1lico", + "Turtle.unloadWarning": "Deixar est\u00e1 p\u00e1gina resultar\u00e1 na perda de seu trabalho.", + "Turtle.title": "Gr\u00e1ficos de Tartaruga (LOGO)", + "Turtle.runTooltip": "Faz a tartaruga executar o que os blocos dizem.", + "Turtle.captureTooltip": "Salvar o desenho.", + "Turtle.imgFilename": "desenho.png", + "Turtle.catTurtle": "Turtle" +} \ No newline at end of file diff --git a/apps/json/pt.json b/apps/json/pt.json new file mode 100644 index 000000000..7c425a8c1 --- /dev/null +++ b/apps/json/pt.json @@ -0,0 +1,84 @@ +{ + "@metadata": { + "authors": [ + "Luckas" + ] + }, + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Veja o c\u00f3digo JavaScript gerado.", + "Apps.linkTooltip": "Salva conex\u00e3o com o blockly.", + "Apps.runProgram": "Executar programa", + "Apps.resetProgram": "Reiniciar", + "Apps.dialogOk": "OK", + "Apps.catMath": "Matem\u00e1tica", + "Apps.catText": "Texto", + "Apps.catLists": "Listas", + "Apps.catColour": "Cor", + "Apps.catVariables": "Vari\u00e1veis", + "Apps.catProcedures": "Procedimentos", + "Apps.httpRequestError": "Houve um problema com a solicita\u00e7\u00e3o.", + "Apps.linkAlert": "Compartilhe os seus blocos com este link:\n\n%1", + "Apps.hashError": "Desculpe, '%1' n\u00e3o corresponde a um blockly salvo.", + "Apps.xmlError": "N\u00e3o foi poss\u00edvel ler o seu arquivo salvo. Talvez ele tenha sido gerado por uma vers\u00e3o antiga do Blockly?", + "Apps.listVariable": "lista", + "Apps.textVariable": "texto", + "Code.title": "C\u00f3digo", + "Code.blocks": "Bloqueios", + "Maze.moveForward": "Mover para a frente", + "Maze.turnLeft": "gire para a esquerda", + "Maze.turnRight": "gire para a direita", + "Maze.doCode": "fa\u00e7a", + "Maze.elseCode": "sen\u00e3o", + "Maze.helpIfElse": "O comando 'Se-sen\u00e3o' faz uma coisa ou outra.", + "Maze.pathAhead": "se existe um caminho em frente", + "Maze.pathLeft": "se existe um caminho para a esquerda", + "Maze.pathRight": "se existe um caminho para a direita", + "Maze.repeatUntil": "repita at\u00e9 o", + "Maze.moveForwardTooltip": "Move o Pegman um quadro para frente.", + "Maze.turnTooltip": "Gire o Pegman 90 graus para esquerda ou para a direita.", + "Maze.ifTooltip": "Se existe um caminho na dire\u00e7\u00e3o especificada, entao executa algumas a\u00e7\u00f5es.", + "Maze.ifelseTooltip": "Se n\u00e3o existe um caminho na dire\u00e7\u00e3o especificada, ent\u00e3o execute o primeiro bloco de a\u00e7\u00f5es. Sen\u00e3o, execute o segundo bloco de a\u00e7\u00f5es.", + "Maze.whileTooltip": "Repita as a\u00e7\u00f5es seguintes at\u00e9 que o ponto final seja alcan\u00e7ado.", + "Maze.capacity0": "Voc\u00ea tem mais %0 blocos.", + "Maze.capacity1": "Voc\u00ea tem mais %1 blocos.", + "Maze.capacity2": "Voc\u00ea tem mais %2 blocos.", + "Maze.nextLevel": "Parab\u00e9ns! Voc\u00ea est\u00e1 apto para o n\u00edvel %1?", + "Maze.finalLevel": "Parab\u00e9ns! Voc\u00ea resolveu o n\u00edvel final.", + "Maze.maze": "Quebra-cabe\u00e7a", + "Maze.helpStack": "Empilhe alguns blocos 'Mover para a frente' para ajudar-me a chegar ao destino.", + "Maze.helpOneTopBlock": "Neste n\u00edvel, voc\u00ea precisa empilhar todos os blocos nos espa\u00e7os em branco.", + "Maze.helpRepeat": "Os computadores t\u00eam uma memoria limitada. Chegue ao destino usando apenas dois blocos. Utilize o comando 'repita' para executar um bloco v\u00e1rias vezes.", + "Maze.helpRepeatMany": "Chegue ao destino utilizando apenas cinco blocos.", + "Maze.helpIf": "A condi\u00e7\u00e3o 'se' executa algo apenas se a condi\u00e7\u00e3o for verdadeira. Tente girar \u00e0 esquerda se existe um caminho \u00e0 esquerda", + "Maze.helpWallFollow": "Voc\u00ea consegue resolver este quebra cabe\u00e7as complexo. Tente seguir o muro do lado esquerdo. Para programadores avan\u00e7ados apenas!", + "Plane.plane": "Avi\u00e3o", + "Puzzle.country1": "Austr\u00e1lia", + "Puzzle.country1Language": "Ingl\u00eas", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country2": "Alemanha", + "Puzzle.country2Language": "Alem\u00e3o", + "Puzzle.country2City1": "Berlim", + "Puzzle.country2City2": "Munique", + "Puzzle.country2HelpUrl": "http://pt.wikipedia.org/wiki/Alemanha", + "Puzzle.country3": "China", + "Puzzle.country3Language": "Chin\u00eas", + "Puzzle.country3City1": "Pequim", + "Puzzle.country3City2": "Xangai", + "Puzzle.country4": "Brasil", + "Puzzle.country4Language": "Portugu\u00eas", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "S\u00e3o Paulo", + "Puzzle.country4HelpUrl": "http://pt.wikipedia.org/wiki/Brasil", + "Puzzle.flag": "bandeira:", + "Puzzle.language": "l\u00edngua:", + "Puzzle.languageChoose": "escolha...", + "Puzzle.cities": "cidades:", + "Puzzle.help": "Ajuda", + "Puzzle.checkAnswers": "Verificar respostas", + "Turtle.font": "fonte", + "Turtle.fontSize": "tamanho da fonte", + "Turtle.fontNormal": "normal", + "Turtle.fontBold": "negrito", + "Turtle.fontItalic": "it\u00e1lico" +} \ No newline at end of file diff --git a/apps/json/qqq.json b/apps/json/qqq.json new file mode 100644 index 000000000..68c11724f --- /dev/null +++ b/apps/json/qqq.json @@ -0,0 +1,152 @@ +{ + "@metadata": { + "authors": [ + "Espertus", + "McDutchie", + "Shirayuki" + ] + }, + "Apps.subtitle": "A short description of Blockly.", + "Apps.blocklyMessage": "The project name. If readers of your language would know approximately how to pronounce 'Blockly', leave unchanged. Otherwise, include a transliteration in parentheses, such as the Russian: 'Blockly (\u0411\u043bo\u043a\u043b\u0438)'.", + "Apps.codeTooltip": "tooltip - Pressing the button causes a program in the JavaScript computer language to be displayed, based on the program created by the user.", + "Apps.linkTooltip": "tooltip - Clicking on this button will cause the current program to be saved and for a URL to be shown to later retrieve it.", + "Apps.runTooltip": "tooltip - Pressing this button runs the computer program the user has written.", + "Apps.runProgram": "button label - Pressing the button runs the computer program the user has written.", + "Apps.resetProgram": "button label - Pressing the button causes the output of the program to be erased but does not delete the user's program).", + "Apps.dialogOk": "Label on button for user to press when done reading help information.\n{{Identical|OK}}", + "Apps.dialogCancel": "Label on button for user to press when not wanting to proceed.\n{{Identical|Cancel}}", + "Apps.catLogic": "category - Blocks related to [https://code.google.com/p/blockly/wiki/Logic logic].", + "Apps.catLoops": "category - Blocks related to [http://en.wikipedia.org/wiki/Control_flow#Loops loops].", + "Apps.catMath": "category - Blocks related to mathematics.", + "Apps.catText": "category - Blocks related to [https://code.google.com/p/blockly/wiki/Text text processing].", + "Apps.catLists": "category - Blocks related to [https://code.google.com/p/blockly/wiki/Lists lists].", + "Apps.catColour": "category - Blocks related to [https://code.google.com/p/blockly/wiki/Colour colour].", + "Apps.catVariables": "category - Blocks related to [https://code.google.com/p/blockly/wiki/Variables variables].", + "Apps.catProcedures": "category - Blocks related to [http://en.wikipedia.org/wiki/Subroutine defining or using procedures/functions].", + "Apps.httpRequestError": "alert - The URL is invalid or a server error occurred. This message will be followed by technical information useful to engineers trying to understand the problem.", + "Apps.linkAlert": "alert - After the user has pressed a button to save his/her program, this provides the URL (%1) to retrieve the program. The characters '\n\n' indicate that a blank line will be displayed before the URL (in English). Leave those in unless you move %1 to the beginning or middle of the text, in which case you should use your judgment about where blank lines would be most useful.\n\nParameters:\n* %1 - URL of saved program.", + "Apps.hashError": "alert - A request to retrieve a stored program does not have a valid URL. %1 is the invalid portion of the URL.", + "Apps.xmlError": "alert - There was a problem loading a file previously saved by the user. The most likely reason for the problem is that it was created with an earlier, incompatible version of Blockly. This message will be followed by technical information useful to engineers trying to understand the problem.", + "Apps.listVariable": "variable name - Default [https://code.google.com/p/blockly/wiki/Variables variable] representing a [https://code.google.com/p/blockly/wiki/Lists list]. This should be a single word, preferably short.", + "Apps.textVariable": "variable name - Default [https://code.google.com/p/blockly/wiki/Variables variable] representing a [https://code.google.com/p/blockly/wiki/Text piece of text]. This should be a single word, preferably short.", + "Code.badXml": "alert - Message shown when the user tries switching from the XML tab after entering XML text that could not be parsed. This asks whether they wish to abandon the XML they added. If they select 'OK' (or the translated equivalent), the XML is cleared, and the other tab is shown. If they select 'Cancel', they remain on the XML tab with the bad XML.\n\nUsed in JavaScript \u003Ccode\u003Ewindow.confirm()\u003C/code\u003E.", + "Code.badCode": "alert - Message shown if an error occurs while interpreting the user program. The error description follows.", + "Code.timeout": "alert - Message shown if the program has run for more than the permitted number of steps. This exists so that programs with infinite loops do not run forever.", + "Code.discard": "alert - Message shown after the user clicks on the 'discard all' icon. Selecting 'OK' (or the translated equivalent) causes all of the blocks to be discarded. Selecting 'Cancel' prevents blocks from being deleted.\n\nParameters:\n* %1 - number of blocks to be deleted. It is always an integer greater than or equal to 2.", + "Code.title": "title - Title of this application, indicating that it is for writing arbitrary programs.", + "Code.blocks": "tab text - Displays and allows editing of the user's program as blocks.", + "Code.trashTooltip": "tooltip - Clicking on this causes the user program to be discarded.", + "Graph.title": "title - Brief title for this graphic calculator application.", + "Maze.moveForward": "block text - Imperative or infinitive of a verb for a person moving (walking) in the direction he/she is facing.", + "Maze.turnLeft": "[[Translating:Blockly#Drop-Down_Menus dropdown]] - Imperative or infinitive of a verb for a person turning his head and body one quarter rotation counter-clockwise. Prefer a translation that has text in common with the translation of 'turn right'. See [[Translating:Blockly#Drop-Down_Menus]].", + "Maze.turnRight": "[[Translating:Blockly#Drop-Down_Menus dropdown]] - Imperative or infinitive of a verb for a person turning his head and body one quarter rotation clockwise. Prefer a translation that has text in common with the translation of 'turn left'. See [[Translating:Blockly#Drop-Down_Menus]].", + "Maze.doCode": "block text - Imperative or infinitive of a verb preceding one or more commands to a person. This is part of [https://code.google.com/p/blockly/wiki/Loops#repeat repeat] and [https://code.google.com/p/blockly/wiki/IfElse#If_blocks if] blocks.", + "Maze.elseCode": "block text - Conjunction meaning 'otherwise', introducing commands to be performed if a previous condition was not true, as in 'if x\u003E3, do this, else do that'. See [https://code.google.com/p/blockly/wiki/IfElse#If-Else_blocks].", + "Maze.helpIfElse": "callout - This is shown when the 'if-else' block is introduced. For 'if-else' concatenate the words for 'if' and 'else/otherwise'.", + "Maze.pathAhead": "[[Translating:Blockly#Drop-Down_Menus dropdown]] - Condensed form of 'if there is a path ahead', as in: 'if path ahead, go forward'. Prefer translation that has text in common with 'if path to the left' and 'if path to the right'.", + "Maze.pathLeft": "[[Translating:Blockly#Drop-Down_Menus dropdown]] - Condensed form of 'if there is a path to the left', as in: 'if path to the left, turn left'.", + "Maze.pathRight": "[[Translating:Blockly#Drop-Down_Menus dropdown]] - Condensed form of 'if there is a path to the right', as in: 'if path to the right, turn right'.", + "Maze.repeatUntil": "block text - Imperative or infinitive of a verb to repeat the following commands. The phrase is followed by the symbol denoting the end of the maze.\n\nSee also:\n* {{msg-blockly|Maze.helpRepeatMany}}.", + "Maze.moveForwardTooltip": "tooltip - Moves the icon on the screen representing the player forward one square on the maze board.", + "Maze.turnTooltip": "tooltip - Turns the icon on the screen representing the player 90 degrees counter-clockwise (left) or clockwise (right).", + "Maze.ifTooltip": "tooltip - 'path' refers to a path through a maze.", + "Maze.ifelseTooltip": "tooltip - 'path' refers to a path through a maze.", + "Maze.whileTooltip": "tooltip - Repeat the enclosed commands until the maze has been successfully completed (the end point reached).", + "Maze.capacity0": "warning - No more blocks may be added until some are removed. Please include '%0' in the translated string. It will be replaced with '0' and made bold.", + "Maze.capacity1": "warning - Only one more block may be added. Please include '%1' in the translated string. It will be replaced with '1' and made bold.\n\nSee also:\n* {{msg-blockly|Maze.capacity2}}", + "Maze.capacity2": "warning - Only %2 more blocks may be used, where %2 is an integer greater than 1.\n\nSee also:\n* {{msg-blockly|Maze.capacity1}}", + "Maze.nextLevel": "alert - This is displayed when the user solves the maze, inviting them to precede to the next level of difficulty.\n\nParameters:\n* %1 - the number of the next level, which is always an integer greater than 1.", + "Maze.finalLevel": "alert - This is displayed when the user solves the most difficult level.", + "Maze.maze": "title - Specifies that this is Blockly's '''Maze''' tutorial.", + "Maze.runTooltip": "tooltip - Pressing this button runs the computer program the user has written to move the player through the maze.", + "Maze.resetTooltip": "tooltip - Pressing this button restores the player to the start position and enables the user's program to be run again.", + "Maze.helpStack": "callout - The words for 'stack' and 'blocks' should be the same as for stacking children's blocks. Use the imperative verb form appropriate for speaking to a child, gender unspecified. If no gender-neutral singular/familiar form exists but a gender-neutral plural/formal form exists, use that instead. Be sure to use the same translation of 'move forward' as above.\n\n'move forward' refers to {{msg-blockly|Maze.moveForward}}.", + "Maze.helpOneTopBlock": "callout - This is displayed if a user attempts to run a program composed of multiple stacks of blocks, letting them know they need to create a single stack.", + "Maze.helpRun": "callout - This is shown after the user has created a program on the first level.", + "Maze.helpReset": "callout - This is shown after the user has run a program that does not solve the maze.\n\n'Reset' refers to {{msg-blockly|Apps.resetProgram}}.", + "Maze.helpRepeat": "callout - This is shown when the 'repeat' block is introduced. The word 'path' refers to a path through a maze, and 'block' refers to a child's building block.", + "Maze.helpCapacity": "callout - This is shown after the user has used all the blocks permitted on this level.", + "Maze.helpRepeatMany": "callout - This is a hint that the user should place a second block inside of a 'repeat' block.\n\n'repeat' should be consistent with {{msg-blockly|Maze.repeatUntil}}.", + "Maze.helpSkins": "callout - This is a hint that the user can change the appearance of the player that moves within the maze.", + "Maze.helpIf": "callout - This is shown when the 'if' block is introduced. An example of an 'if' block is: 'if there is a path to the left, turn left'.", + "Maze.helpMenu": "callout - %1 will be replaced with an image of the dropdown menu that the user needs to click.", + "Maze.helpWallFollow": "callout - This advises the user to solve a maze by keeping his/her left hand in contact with the wall while proceding through it. The final sentence is a warning that only advanced programmers should attempt this problem, as beginners tend to get frustrated.", + "Plane.rows": "page text - Total number of rows of seats on an airplane.\n\nParameters:\n* %1 - number of rows of seats on an airplane. It is always an integer greater than or equal to zero.", + "Plane.getRows": "block text - The number of rows on the airplane, to be used in a mathematical equation, such as: \u0026quot;seats = 4 x '''rows (5)'''\u0026quot;.\n\nParameters:\n* %1 - number of rows of seats on an airplane. It is always an integer greater than or equal to zero.", + "Plane.rows1": "page text - The number of rows of first-class seats on the airplane. You can see the block at [http://blockly-share.appspot.com/static/apps/plane/plane.html?lang=en\u0026level=3].\n\nParameters:\n* %1 - number of rows of first-class seats on an airplane. It is always an integer greater than or equal to zero.", + "Plane.getRows1": "block text - The number of rows of first-class seats on the, to be used in a mathematical equation. See [http://blockly-share.appspot.com/static/apps/plane/plane.html?lang=en\u0026level=3].\n\nParameters:\n* %1 - number of rows of first-class seats on an airplane. It is always an integer greater than or equal to zero.", + "Plane.rows2": "page text - The number of rows of second-class seats on the airplane. %1 is an integer greater or equal to zero. See [http://blockly-share.appspot.com/static/apps/plane/plane.html?lang=en\u0026level=3].\n\nParameters:\n* %1 - number of rows of second-class seats on an airplane. It is always an integer greater than or equal to zero.", + "Plane.getRows2": "block text - The number of rows of second-class (also called 'economy class') seats on the airplane, to be used in a mathematical expression.\n\nParameters:\n* %1 - number of rows of second-class seats on an airplane. It is always an integer greater than or equal to zero.", + "Plane.seats": "page text - The total number of seats on the airplane.\n\nParameters:\n* %1 - number of seats on an airplane. It is always either the next message or an integer greater than or equal to zero.", + "Plane.placeholder": "page text - A word or symbol indicating that this numeric value has not yet been determined.", + "Plane.setSeats": "block text - The first half of a mathematical equation determining the number of seats in an airplane, such as: \u0026quot;'''seats =''' 4 x rows\u0026quot;.", + "Plane.plane": "title - Specifies that this is Blockly's '''Plane''' (airplane) tutorial. The word \u0026quot;plane\u0026quot; was chosen over \u0026quot;airplane\u0026quot; in English because it is shorter and less formal.", + "Plane.description1": "instructions - Note that in [http://blockly-share.appspot.com/static/apps/plane/plane.html?lang=en\u0026level=1 this level], there is only one type of seat on the plane.", + "Plane.description2": "instructions - Note that in [http://blockly-share.appspot.com/static/apps/plane/plane.html?lang=en\u0026level=2 this level], there are two types of seats on this plane.", + "Plane.description3": "instructions - Note that in [http://blockly-share.appspot.com/static/apps/plane/plane.html?lang=en\u0026level=3 this level], there are three types of seats on this plane. Be sure to use the same terms for \u0026quot;1st class\u0026quot; and \u0026quot;2nd class\u0026quot; as you did for the earlier messages.", + "Plane.instructions": "page text - This text appears below the airplane graphic and above the space for the user to create the formula. The number of rows an the graphic may be changed by the user with a slider. See [http://blockly-share.appspot.com/static/apps/plane/plane.html?lang=en\u0026level=1] for a picture.", + "Puzzle.country1": "The name of the country Australia\n{{Identical|Australia}}", + "Puzzle.country1Language": "The English language.{{Identical|English}}", + "Puzzle.country1City1": "The city Melbourne in Australia.", + "Puzzle.country1City2": "The city Sydney in Australia.", + "Puzzle.country1HelpUrl": "The URL of a page with basic information about Australia.", + "Puzzle.country2": "The country Germany.\n{{Identical|Germany}}", + "Puzzle.country2Language": "The German language.\n{{Identical|German}}", + "Puzzle.country2City1": "The city Berlin in Germany.", + "Puzzle.country2City2": "The city Munich (M\u00fcnchen) in Germany.", + "Puzzle.country2HelpUrl": "The URL of a page with basic information about Germany.", + "Puzzle.country3": "The People's Republic of China.", + "Puzzle.country3Language": "The Chinese language.\n{{Identical|Chinese}}", + "Puzzle.country3City1": "The capital city of China (also known as Peking).", + "Puzzle.country3City2": "The city Shanghai in China.", + "Puzzle.country3HelpUrl": "The URL of a page with basic information about China.", + "Puzzle.country4": "The name of the country Brazil.", + "Puzzle.country4Language": "The Portuguese language.\n{{Identical|Portuguese}}", + "Puzzle.country4City1": "The city Rio de Janeiro in Brazil.", + "Puzzle.country4City2": "The city S\u00e3o Paulo in Brazil.", + "Puzzle.country4HelpUrl": "The URL of a page with basic information about Brazil.", + "Puzzle.flag": "[[File:Config-language.png|left||32px]]\nnoun the official flag representing a country (the national flag).\n{{Identical|Flag}}", + "Puzzle.language": "Prompt for the user to provide the official language of a country.\n{{Identical|Language}}", + "Puzzle.languageChoose": "Initial text displayed in a dropdown menu from which the user should choose the language spoken in the indicated country.\n{{Identical|Choose}}", + "Puzzle.cities": "A label preceding a list of cities.\n{{Identical|City}}", + "Puzzle.error0": "A congratulatory message displayed if the user placed all of the blocks correctly.\n\nParameters:\n* %1 - number of blocks correctly placed. It is always an integer greater than 1.\n\nThe use of a new line character is optional.", + "Puzzle.error1": "An encouraging error message displayed if the user placed all blocks except 1 correctly.\n\nIf the number of incorrect blocks is 2 or more, Puzzle.error2 is used instead.", + "Puzzle.error2": "An error message displayed if the user misplaced multiple blocks.\n\nParameters:\n* %1 - number of blocks incorrectly placed, which is always greater than 1 (or the message Puzzle.error1 would be used).", + "Puzzle.tryAgain": "A message indicating that a visually distinguished block is incorrect and that the user should try to fix it.\n\nThe use of a new line character is optional.", + "Puzzle.title": "A brief title for page, not including the word for Blockly. Use the word for a jigsaw puzzle.", + "Puzzle.help": "The label on a button the user can press for help.\n{{Identical|Help}}", + "Puzzle.checkAnswers": "A label on a button the user can press to check his/her answers.", + "Puzzle.helpText": "Instructions for the puzzle. For context, see [http://blockly-demo.appspot.com/static/apps/puzzle/index.html Blockly Puzzle].", + "Turtle.moveTooltip": "tooltip - In this and subsequent messages, 'turtle' refers to a stylized turtle on the screen to represent a position and direction. This imaginary turtle is carrying a pen in its tail, so moving the turtle draws a line (or curve, etc.). You are encouraged to play with the [https://blockly-demo.appspot.com/static/apps/turtle/index.html Turtle application] before doing this translation.", + "Turtle.moveForward": "[[Translating:Blockly#Drop-Down_Menus dropdown]] - Infinitive or imperative of a verb telling a turtle to move (walk) in the direction he/she is facing. This is followed by a number indicating how far (how many pixels) to go. Prefer a translation that has text in common with the translation of 'move backward'. See [[Translating:Blockly#Drop-Down_Menus]].", + "Turtle.moveBackward": "[[Translating:Blockly#Drop-Down_Menus dropdown]] - Infinitive or imperative of a verb telling a turtle to move (walk) in the direction opposite to where he/she is facing. This is followed by a number indicating how far (how many pixels) to go. Prefer a translation that has text in common with the translation of 'move forward'.", + "Turtle.turnTooltip": "'Left' means counter-clockwise/anti-clockwise, and 'right' means clockwise.", + "Turtle.turnRight": "[[Translating:Blockly#Drop-Down_Menus dropdown]] - Infinitive or imperative of verb telling a turtle to rotate clockwise. This is followed by a number indicating how far (how many degrees) to turn. Prefer a translation that has text in common with the translation of 'turn left by'.", + "Turtle.turnLeft": "[[Translating:Blockly#Drop-Down_Menus dropdown]] - Infinitive or imperative of verb telling a turtle to rotate counter-clockwise (anti-clockwise). This is followed by a number indicating how far (how many degrees) to turn. Prefer a translation that has text in common with the translation of 'turn right by'.", + "Turtle.widthTooltip": "tooltip", + "Turtle.setWidth": "block text - Infinitive or imperative of a verb to set the width of the lines that should be drawn in the future by an imaginary pen. This is followed by a number indicating the width in pixels (1 or greater).", + "Turtle.colourTooltip": "tooltip - Changes the colour of ink in the pen carried by the turtle.", + "Turtle.setColour": "block text - Infinitive or imperative of a verb to specify the colour of the lines that should be drawn in the future by an imaginary pen. This is followed by a block showing the colour", + "Turtle.penTooltip": "tooltip - Lifting the pen off the writing surface prevents anything from being drawn. Lowering it (after it has been lifted) enables it to draw again.", + "Turtle.penUp": "block text - Infinitive or imperative of a verb to lift up a pen so that moving it leaves no mark on the writing surface.", + "Turtle.penDown": "block text - Infinitive or imperative of a verb to lower a raised pen so that moving it leaves a mark on the writing surface.", + "Turtle.turtleVisibilityTooltip": "tooltip", + "Turtle.hideTurtle": "block text - Infinitive or imperative of a verb telling a turtle to hide itself (become invisible).", + "Turtle.showTurtle": "block text - Infinitive or imperative of a verb telling a turtle to show itself (become visible after having been invisible).", + "Turtle.printHelpUrl": "URL - Information about printing or typography.", + "Turtle.printTooltip": "tooltip - Note that 'print' refers to displaying text on the screen, not on an external printer.", + "Turtle.print": "block text - Infinitive or imperative of a verb telling a turtle to display text on the screen. This is always followed by a block indicating what should be printed.", + "Turtle.fontHelpUrl": "URL - Information about typographic fonts.", + "Turtle.fontTooltip": "tooltip - This is shown on the block that lets the user specify the font [family], size, and style that should be used for subsequent displays of text.", + "Turtle.font": "block text - This precedes a dropdown menu specifying the typographic font [family] that should be used when displaying text.", + "Turtle.fontSize": "block text - This precedes a number specifying the size of the typographic font that should be used when displaying text. This appears in the same block as 'font', so that word should not be repeated.", + "Turtle.fontNormal": "[[Translating:Blockly#Drop-Down_Menus dropdown]] - Specifies that a typographic font should be normal (neither in italics or bold).", + "Turtle.fontBold": "[[Translating:Blockly#Drop-Down_Menus dropdown]] - Specifies that a typographic font should be [http://en.wikipedia.org/wiki/Emphasis_(typography) bold].", + "Turtle.fontItalic": "[[Translating:Blockly#Drop-Down_Menus dropdown]] - Specifies that a typographic font should be [http://en.wikipedia.org/wiki/Italics italic].", + "Turtle.unloadWarning": "alert - This is shown if the user attempts to close the browser tab containing the page or navigate to a different page to prevent them from accidentally losing their program in progress.", + "Turtle.title": "title - Specifies that this is Blockly's '''Turtle Graphics''' application. Should you wish to, you can read more about [http://en.wikipedia.org/wiki/Turtle_graphics turtle graphics].", + "Turtle.runTooltip": "tooltip - Pressing this button runs the computer program the user has written to move the turtle on the canvas.", + "Turtle.captureTooltip": "tooltip - Pressing this button causes the drawing created by the user's program to be saved as an image on the user's computer. The button icon looks like a camera.", + "Turtle.imgFilename": "filename - The name of the image file containing the user's drawing. It must end with '.png'.", + "Turtle.catTurtle": "category - Blocks related to Turtle commands." +} \ No newline at end of file diff --git a/apps/json/ro.json b/apps/json/ro.json new file mode 100644 index 000000000..b24a1d020 --- /dev/null +++ b/apps/json/ro.json @@ -0,0 +1,145 @@ +{ + "@metadata": { + "authors": [ + "Costin PIETRARU", + "Minisarm", + "Oana" + ] + }, + "Apps.subtitle": "un mediu de programare vizual", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Vizualizeaz\u0103 codul JavaScript generat.", + "Apps.linkTooltip": "Salveaz\u0103 \u0219i adaug\u0103 la blocuri.", + "Apps.runTooltip": "Execut\u0103 programul definit de c\u0103tre blocuri \u00een spa\u021biul de lucru.", + "Apps.runProgram": "Ruleaz\u0103 programul", + "Apps.resetProgram": "Reseteaz\u0103", + "Apps.dialogOk": "OK", + "Apps.dialogCancel": "Revocare", + "Apps.catLogic": "Logic", + "Apps.catLoops": "Bucle", + "Apps.catMath": "Matematic\u0103", + "Apps.catText": "Text", + "Apps.catLists": "Liste", + "Apps.catColour": "Culoare", + "Apps.catVariables": "Variabile", + "Apps.catProcedures": "Proceduri", + "Apps.httpRequestError": "A ap\u0103rut o problem\u0103 la solicitare.", + "Apps.linkAlert": "Distribuie-\u021bi blocurile folosind aceast\u0103 leg\u0103tur\u0103:\n\n%1", + "Apps.hashError": "Scuze, \u201e%1\u201d nu corespunde nici unui program salvat.", + "Apps.xmlError": "Sistemul nu a putut \u00eenc\u0103rca fi\u0219ierul salvat. Poate c\u0103 a fost creat cu o alt\u0103 versiune de Blockly?", + "Apps.listVariable": "list\u0103", + "Apps.textVariable": "text", + "Code.badXml": "Eroare de parsare XML:\n%1\n\nAlege \u201eOK\u201d pentru a renun\u021ba la modific\u0103rile efectuate sau \u201eRevocare\u201d pentru a modifica \u00een continuare fi\u0219ierul XML.", + "Code.badCode": "Eroare de program:\n%1", + "Code.timeout": "Num\u0103rul maxim de itera\u021bii a fost dep\u0103\u0219it.", + "Code.discard": "\u0218tergi toate cele %1 (de) blocuri?", + "Code.title": "Cod", + "Code.blocks": "Blocuri", + "Code.trashTooltip": "\u0218terge toate blocurile.", + "Graph.title": "Calculator grafic", + "Maze.moveForward": "merge \u00eenainte", + "Maze.turnLeft": "\u00eentoarce la st\u00e2nga", + "Maze.turnRight": "\u00eentoarce la dreapta", + "Maze.doCode": "execut\u0103", + "Maze.elseCode": "altfel", + "Maze.helpIfElse": "Blocurile \u201edac\u0103-altfel\u201d vor efectua fie o anumit\u0103 ac\u021biune, fie pe cealalt\u0103.", + "Maze.pathAhead": "dac\u0103 o cale \u00eenainte", + "Maze.pathLeft": "dac\u0103 o cale spre st\u00e2nga", + "Maze.pathRight": "dac\u0103 o cale spre dreapta", + "Maze.repeatUntil": "repet\u0103 p\u00e2n\u0103 c\u00e2nd", + "Maze.moveForwardTooltip": "Mut\u0103 juc\u0103torul \u00eenainte cu un singur spa\u021biu.", + "Maze.turnTooltip": "Rote\u0219te personajul la st\u00e2nga sau la dreapta cu 90 de grade.", + "Maze.ifTooltip": "Dac\u0103 exist\u0103 o cale liber\u0103 \u00een direc\u021bia aleas\u0103, atunci execut\u0103 c\u00e2teva ac\u021biuni.", + "Maze.ifelseTooltip": "Dac\u0103 exist\u0103 o cale \u00een direc\u021bia specificat\u0103, atunci execut\u0103 primul bloc de ac\u021biuni. \u00cen caz contrar, execut\u0103 al doilea bloc de ac\u021biuni.", + "Maze.whileTooltip": "Repet\u0103 comenzile incluse p\u00e2n\u0103 c\u00e2nd atinge punctul de final.", + "Maze.capacity0": "Mai ai %0 blocuri r\u0103mase.", + "Maze.capacity1": "Mai ai %1 bloc r\u0103mas.", + "Maze.capacity2": "Mai ai %2 (de) blocuri r\u0103mase.", + "Maze.nextLevel": "Felicit\u0103ri! E\u0219ti preg\u0103tit s\u0103 treci la nivelul %1?", + "Maze.finalLevel": "Felicit\u0103ri! Ai rezolvat ultimul nivel.", + "Maze.maze": "Labirint", + "Maze.runTooltip": "Face ca personajul s\u0103 execute comenzile blocurilor.", + "Maze.resetTooltip": "Trimite personajul la punctul de \u00eenceput al labirintului.", + "Maze.helpStack": "Alipe\u0219te mai multe blocuri de \u201emerge \u00eenainte\u201d pentru a m\u0103 ajuta s\u0103-mi ating obiectivul.", + "Maze.helpOneTopBlock": "La acest nivel trebuie s\u0103 alipe\u0219ti toate blocurile \u00een spa\u021biul de lucru alb.", + "Maze.helpRun": "Ruleaz\u0103-\u021bi programul pentru a vedea ce se \u00eent\u00e2mpl\u0103.", + "Maze.helpReset": "Programul t\u0103u nu a rezolvat labirintul. Apas\u0103 \u201eReseteaz\u0103\u201d \u0219i mai \u00eencearc\u0103 o dat\u0103.", + "Maze.helpRepeatMany": "Po\u021bi include mai mult de un bloc \u00een interiorul unui bloc \u201erepet\u0103 p\u00e2n\u0103 c\u00e2nd\u201d.", + "Maze.helpSkins": "Alege-\u021bi personajul favorit din acest meniu.", + "Plane.rows": "R\u00e2nduri: %1", + "Plane.getRows": "r\u00e2nduri (%1)", + "Plane.rows1": "r\u00e2nduri de clasa I: %1", + "Plane.getRows1": "r\u00e2nduri de clasa I (%1)", + "Plane.rows2": "r\u00e2nduri de clasa a II-a: %1", + "Plane.getRows2": "r\u00e2nduri de clasa a II-a (%1)", + "Plane.seats": "Scaune: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "scaune =", + "Plane.plane": "Avion", + "Plane.description1": "Un avion are un num\u0103r de r\u00e2nduri cu scaune pentru pasageri. Fiecare r\u00e2nd con\u021bine patru scaune.", + "Plane.description2": "Un avion are dou\u0103 scaune \u00een carling\u0103 (pentru pilot \u0219i copilot) \u0219i un num\u0103r de r\u00e2nduri cu scaune pentru pasageri. Fiecare r\u00e2nd con\u021bine patru scaune.", + "Plane.description3": "Un avion are dou\u0103 scaune \u00een carling\u0103 (pentru pilot \u0219i copilot) \u0219i un num\u0103r de r\u00e2nduri cu scaune de clasa I \u0219i clasa a II-a pentru pasageri. Fiecare r\u00e2nd de clasa I con\u021bine patru scaune. Fiecare r\u00e2nd de clasa a II-a con\u021bine cinci scaune.", + "Puzzle.country1": "Australia", + "Puzzle.country1Language": "englez\u0103", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://ro.wikipedia.org/wiki/Australia", + "Puzzle.country2": "Germania", + "Puzzle.country2Language": "german\u0103", + "Puzzle.country2City1": "Berlin", + "Puzzle.country2City2": "M\u00fcnchen", + "Puzzle.country2HelpUrl": "http://ro.wikipedia.org/wiki/Germania", + "Puzzle.country3": "China", + "Puzzle.country3Language": "chinez\u0103", + "Puzzle.country3City1": "Beijing", + "Puzzle.country3City2": "Shanghai", + "Puzzle.country3HelpUrl": "http://ro.wikipedia.org/wiki/China", + "Puzzle.country4": "Brazilia", + "Puzzle.country4Language": "portughez\u0103", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "S\u00e3o Paulo", + "Puzzle.country4HelpUrl": "http://ro.wikipedia.org/wiki/Brazilia", + "Puzzle.flag": "drapel:", + "Puzzle.language": "limb\u0103:", + "Puzzle.languageChoose": "alege...", + "Puzzle.cities": "ora\u0219e:", + "Puzzle.error0": "Perfect!\nToate cele %1 (de) blocuri sunt corecte.", + "Puzzle.error1": "Aproape! Un bloc este incorect.", + "Puzzle.error2": "%1 (de) blocuri sunt incorecte.", + "Puzzle.tryAgain": "Blocul eviden\u021biat nu este corect.\nMai \u00eencearc\u0103.", + "Puzzle.title": "Puzzle", + "Puzzle.help": "Ajutor", + "Puzzle.checkAnswers": "Verific\u0103 r\u0103spunsurile", + "Puzzle.helpText": "Pentru fiecare \u021bar\u0103 (verde) ata\u0219eaz\u0103 drapelul, alege-i limba \u0219i f\u0103 un grup cu ora\u0219ele sale.", + "Turtle.moveTooltip": "Deplaseaz\u0103 \u021bestoasa \u00eenainte sau \u00eenapoi cu valoarea specificat\u0103.", + "Turtle.moveForward": "deplaseaz\u0103 \u00eenainte cu", + "Turtle.moveBackward": "deplaseaz\u0103 \u00eenapoi cu", + "Turtle.turnTooltip": "\u00centoarce \u021bestoasa la st\u00e2nga sau la dreapta cu num\u0103rul de grade specificat.", + "Turtle.turnRight": "\u00eentoarce la dreapta cu", + "Turtle.turnLeft": "\u00eentoarce la st\u00e2nga cu", + "Turtle.widthTooltip": "Modific\u0103 l\u0103\u021bimea stiloului.", + "Turtle.setWidth": "seteaz\u0103 l\u0103\u021bimea la", + "Turtle.colourTooltip": "Schimb\u0103 culoarea stiloului.", + "Turtle.setColour": "seteaz\u0103 culoarea la", + "Turtle.penTooltip": "Ridic\u0103 sau coboar\u0103 stiloul pentru a opri sau \u00eencepe desenarea.", + "Turtle.penUp": "ridic\u0103 stiloul", + "Turtle.penDown": "coboar\u0103 stiloul", + "Turtle.turtleVisibilityTooltip": "Face \u021bestoasa (cercul \u0219i s\u0103geata) vizibil\u0103 sau invizibil\u0103.", + "Turtle.hideTurtle": "ascunde \u021bestoasa", + "Turtle.showTurtle": "arat\u0103 \u021bestoasa", + "Turtle.printHelpUrl": "http://ro.wikipedia.org/wiki/Tip\u0103rire", + "Turtle.printTooltip": "Deseneaz\u0103 textul pe direc\u021bia \u021bestoasei \u0219i \u00een pozi\u021bia acesteia.", + "Turtle.print": "afi\u0219eaz\u0103", + "Turtle.fontHelpUrl": "http://ro.wikipedia.org/wiki/Font", + "Turtle.fontTooltip": "Seteaz\u0103 fontul utilizat de blocul de afi\u0219are.", + "Turtle.font": "font", + "Turtle.fontSize": "dimensiunea fontului", + "Turtle.fontNormal": "normal\u0103", + "Turtle.fontBold": "aldin", + "Turtle.fontItalic": "cursiv", + "Turtle.unloadWarning": "P\u0103r\u0103sirea acestei pagini va duce la pierderea muncii tale.", + "Turtle.runTooltip": "Face ca \u021bestoasa s\u0103 execute comenzile blocurilor.", + "Turtle.captureTooltip": "Salveaz\u0103 desenul.", + "Turtle.imgFilename": "drawing.png", + "Turtle.catTurtle": "\u021aestoas\u0103" +} \ No newline at end of file diff --git a/apps/json/ru.json b/apps/json/ru.json new file mode 100644 index 000000000..0640dc50b --- /dev/null +++ b/apps/json/ru.json @@ -0,0 +1,153 @@ +{ + "@metadata": { + "authors": [ + "Eleferen", + "Lockal", + "MS", + "Okras" + ] + }, + "Apps.subtitle": "\u0441\u0440\u0435\u0434\u0430 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f", + "Apps.blocklyMessage": "Blockly (\u0411\u043bo\u043a\u043b\u0438)", + "Apps.codeTooltip": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u0434 JavaScript.", + "Apps.linkTooltip": "\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0431\u043b\u043e\u043a\u0438.", + "Apps.runTooltip": "\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443, \u0437\u0430\u0434\u0430\u043d\u043d\u0443\u044e \u0431\u043b\u043e\u043a\u0430\u043c\u0438 \u0432 \u0440\u0430\u0431\u043e\u0447\u0435\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438.", + "Apps.runProgram": "\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443", + "Apps.resetProgram": "\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c", + "Apps.dialogOk": "OK", + "Apps.dialogCancel": "\u041e\u0442\u043c\u0435\u043d\u0430", + "Apps.catLogic": "\u041b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0435", + "Apps.catLoops": "\u0426\u0438\u043a\u043b\u044b", + "Apps.catMath": "\u041c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0430", + "Apps.catText": "\u0422\u0435\u043a\u0441\u0442", + "Apps.catLists": "\u0421\u043f\u0438\u0441\u043a\u0438", + "Apps.catColour": "\u0426\u0432\u0435\u0442", + "Apps.catVariables": "\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435", + "Apps.catProcedures": "\u041f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u044b", + "Apps.httpRequestError": "\u041f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u043f\u0440\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0435.", + "Apps.linkAlert": "\u041f\u043e\u0434\u0435\u043b\u0438\u0442\u0435\u0441\u044c \u0441\u0432\u043e\u0438\u043c\u0438 \u0431\u043b\u043e\u043a\u0430\u043c\u0438 \u043f\u043e \u044d\u0442\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0435:\n\n%1", + "Apps.hashError": "\u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u00ab%1\u00bb \u043d\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0438 \u043e\u0434\u043d\u043e\u043c\u0443 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043d\u043e\u043c\u0443 \u0444\u0430\u0439\u043b\u0443 \u0411\u043b\u043e\u043a\u043b\u0438.", + "Apps.xmlError": "\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0432\u0430\u0448 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043e\u043d \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d \u0432 \u0434\u0440\u0443\u0433\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0411\u043b\u043e\u043a\u043b\u0438?", + "Apps.listVariable": "\u0441\u043f\u0438\u0441\u043e\u043a", + "Apps.textVariable": "\u0442\u0435\u043a\u0441\u0442", + "Code.badXml": "\u041e\u0448\u0438\u0431\u043a\u0430 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0430\u043d\u0430\u043b\u0438\u0437\u0430 XML:\n%1\n\n\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 '\u041e\u041a', \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0438\u043b\u0438 'Cancel' \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0433\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f XML.", + "Code.badCode": "\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b:\n%1", + "Code.timeout": "\u041f\u0440\u0435\u0432\u044b\u0448\u0435\u043d\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0439.", + "Code.discard": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0432\u0441\u0435 \u0431\u043b\u043e\u043a\u0438 (%1)?", + "Code.title": "\u041a\u043e\u0434", + "Code.blocks": "\u0411\u043b\u043e\u043a\u0438", + "Code.trashTooltip": "\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0432\u0441\u0435 \u0431\u043b\u043e\u043a\u0438.", + "Graph.title": "\u0413\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440", + "Maze.moveForward": "\u0448\u0430\u0433\u043d\u0443\u0442\u044c \u0432\u043f\u0435\u0440\u0435\u0434", + "Maze.turnLeft": "\u043f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043d\u0430\u043b\u0435\u0432\u043e", + "Maze.turnRight": "\u043f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043d\u0430\u043f\u0440\u0430\u0432\u043e", + "Maze.doCode": "\u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c", + "Maze.elseCode": "\u0438\u043d\u0430\u0447\u0435", + "Maze.helpIfElse": "\u041a\u043e\u043c\u0430\u043d\u0434\u0430 '\u0435\u0441\u043b\u0438-\u0438\u043d\u0430\u0447\u0435' \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442 \u043e\u0434\u043d\u043e \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435.", + "Maze.pathAhead": "\u0435\u0441\u043b\u0438 \u043f\u0443\u0442\u044c \u0432\u043f\u0435\u0440\u0435\u0434\u0438", + "Maze.pathLeft": "\u0435\u0441\u043b\u0438 \u043f\u0443\u0442\u044c c\u043b\u0435\u0432\u0430", + "Maze.pathRight": "\u0435\u0441\u043b\u0438 \u043f\u0443\u0442\u044c c\u043f\u0440\u0430\u0432\u0430", + "Maze.repeatUntil": "\u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c, \u043f\u043e\u043a\u0430 \u043d\u0435", + "Maze.moveForwardTooltip": "\u041f\u0440\u043e\u0434\u0432\u0438\u0433\u0430\u0435\u0442 \u043f\u0443\u0442\u043d\u0438\u043a\u0430 \u0432\u043f\u0435\u0440\u0451\u0434 \u043d\u0430 \u043e\u0434\u0438\u043d \u0448\u0430\u0433.", + "Maze.turnTooltip": "\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u0443\u0442\u043d\u0438\u043a\u0430 \u043d\u0430 90 \u0433\u0440\u0430\u0434\u0443\u0441\u043e\u0432 \u0432\u043b\u0435\u0432\u043e \u0438\u043b\u0438 \u0432\u043f\u0440\u0430\u0432\u043e.", + "Maze.ifTooltip": "\u0415\u0441\u043b\u0438 \u043f\u0443\u0442\u044c \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u043c \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u0435\u043d, \u0442\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u043a\u0430\u043a\u0438\u0435-\u043d\u0438\u0431\u0443\u0434\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f.", + "Maze.ifelseTooltip": "\u0415\u0441\u043b\u0438 \u043f\u0443\u0442\u044c \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u043c \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u0435\u043d, \u0442\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u043f\u0435\u0440\u0432\u044b\u0439 \u0431\u043b\u043e\u043a \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439. \u0418\u043d\u0430\u0447\u0435, \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u0432\u0442\u043e\u0440\u043e\u0439 \u0431\u043b\u043e\u043a \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439.", + "Maze.whileTooltip": "\u041f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f, \u0437\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u0435 \u0432 \u0441\u043a\u043e\u0431\u043a\u0430\u0445, \u0434\u043e \u0434\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0438.", + "Maze.capacity0": "\u0423 \u0432\u0430\u0441 \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c %0 \u0431\u043b\u043e\u043a\u043e\u0432.", + "Maze.capacity1": "\u0423 \u0432\u0430\u0441 \u043e\u0441\u0442\u0430\u043b\u0441\u044f %1 \u0431\u043b\u043e\u043a.", + "Maze.capacity2": "\u0423 \u0432\u0430\u0441 \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c %2 \u0431\u043b\u043e\u043a\u043e\u0432.", + "Maze.nextLevel": "\u041f\u043e\u0437\u0434\u0440\u0430\u0432\u043b\u044f\u0435\u043c! \u0412\u044b \u0433\u043e\u0442\u043e\u0432\u044b \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043d\u0430 \u0443\u0440\u043e\u0432\u0435\u043d\u044c %1?", + "Maze.finalLevel": "\u041f\u043e\u0437\u0434\u0440\u0430\u0432\u043b\u044f\u0435\u043c! \u0412\u044b \u043f\u0440\u043e\u0448\u043b\u0438 \u0437\u0430\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c.", + "Maze.maze": "\u041b\u0430\u0431\u0438\u0440\u0438\u043d\u0442", + "Maze.runTooltip": "\u041f\u0443\u0442\u043d\u0438\u043a \u0441\u0434\u0435\u043b\u0430\u0435\u0442 \u0432\u0441\u0451, \u0447\u0442\u043e \u0441\u043a\u0430\u0436\u0443\u0442 \u0435\u043c\u0443 \u0431\u043b\u043e\u043a\u0438.", + "Maze.resetTooltip": "\u0412\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u0443\u0442\u043d\u0438\u043a\u0430 \u0432 \u043d\u0430\u0447\u0430\u043b\u043e \u043b\u0430\u0431\u0438\u0440\u0438\u043d\u0442\u0430.", + "Maze.helpStack": "\u0421\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u0443\u0439\u0442\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u043b\u043e\u043a\u043e\u0432 '\u0438\u0434\u0438\u0442\u0435 \u0432\u043f\u0435\u0440\u0451\u0434', \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043c\u043e\u0447\u044c \u043c\u043d\u0435 \u0434\u043e\u0441\u0442\u0438\u0447\u044c \u0446\u0435\u043b\u0438.", + "Maze.helpOneTopBlock": "\u041d\u0430 \u0434\u0430\u043d\u043d\u043e\u043c \u0443\u0440\u043e\u0432\u043d\u0435 \u0432\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043b\u043e\u0436\u0438\u0442\u044c \u0432\u043c\u0435\u0441\u0442\u0435 \u0432\u0441\u0435 \u0431\u043b\u043e\u043a\u0438 \u043d\u0430 \u0431\u0435\u043b\u043e\u043c \u0440\u0430\u0431\u043e\u0447\u0435\u043c \u043f\u043e\u043b\u0435.", + "Maze.helpRun": "\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442.", + "Maze.helpReset": "\u0412\u0430\u0448\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u043d\u0435 \u0440\u0435\u0448\u0438\u043b\u0430 \u0437\u0430\u0434\u0430\u0447\u0443. \u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c\u00bb \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0441\u043d\u043e\u0432\u0430.", + "Maze.helpRepeat": "\u041f\u0440\u043e\u0439\u0434\u0438\u0442\u0435 \u0434\u043e \u043a\u043e\u043d\u0446\u0430 \u044d\u0442\u043e\u0433\u043e \u043f\u0443\u0442\u0438, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u0432\u0430 \u0431\u043b\u043e\u043a\u0430. \u0414\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0431\u043b\u043e\u043a\u0430 \u0431\u043e\u043b\u0435\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \"\u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c\".", + "Maze.helpCapacity": "\u0412\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0432\u0441\u0435 \u0431\u043b\u043e\u043a\u0438 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f. \u0427\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u0431\u043b\u043e\u043a, \u0432\u043d\u0430\u0447\u0430\u043b\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439.", + "Maze.helpRepeatMany": "\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0431\u043b\u043e\u043a\u0430 \u0432\u043d\u0443\u0442\u0440\u0438 \u0431\u043b\u043e\u043a\u0430 \u00ab\u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c\u00bb.", + "Maze.helpSkins": "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0432 \u044d\u0442\u043e\u043c \u043c\u0435\u043d\u044e \u0441\u0432\u043e\u0435\u0433\u043e \u043b\u044e\u0431\u0438\u043c\u043e\u0433\u043e \u0438\u0433\u0440\u043e\u043a\u0430.", + "Maze.helpIf": "\u0411\u043b\u043e\u043a \"\u0435\u0441\u043b\u0438\" \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442 \u0447\u0442\u043e-\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u044f. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u043f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043d\u0430\u043b\u0435\u0432\u043e, \u0435\u0441\u043b\u0438 \u043f\u0443\u0442\u044c \u0432\u043b\u0435\u0432\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d.", + "Maze.helpMenu": "\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043d\u0430 %1 \u0432 \u0431\u043b\u043e\u043a\u0435 \"\u0435\u0441\u043b\u0438\" \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0435\u0433\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u044f.", + "Maze.helpWallFollow": "\u041c\u043e\u0436\u0435\u0442\u0435 \u043b\u0438 \u0432\u044b \u0440\u0435\u0448\u0438\u0442\u044c \u044d\u0442\u043e\u0442 \u0441\u043b\u043e\u0436\u043d\u044b\u0439 \u043b\u0430\u0431\u0438\u0440\u0438\u043d\u0442? \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u043f\u0440\u0438\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043b\u0435\u0432\u043e\u0439 \u0441\u0442\u0435\u043d\u044b.", + "Plane.rows": "\u0420\u044f\u0434\u043e\u0432: %1", + "Plane.getRows": "\u0440\u044f\u0434\u044b (%1)", + "Plane.rows1": "\u0420\u044f\u0434\u043e\u0432 1-\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430: %1", + "Plane.getRows1": "\u0440\u044f\u0434\u044b 1-\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 (%1)", + "Plane.rows2": "\u0420\u044f\u0434\u043e\u0432 2-\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430: %1", + "Plane.getRows2": "\u0440\u044f\u0434\u044b 2-\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 (%1)", + "Plane.seats": "\u041c\u0435\u0441\u0442: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "\u043c\u0435\u0441\u0442\u0430 =", + "Plane.plane": "\u0421\u0430\u043c\u043e\u043b\u0451\u0442", + "Plane.description1": "\u0412 \u0441\u0430\u043c\u043e\u043b\u0451\u0442\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u044f\u0434\u043e\u0432 \u0441 \u043f\u0430\u0441\u0441\u0430\u0436\u0438\u0440\u0441\u043a\u0438\u043c\u0438 \u043c\u0435\u0441\u0442\u0430\u043c\u0438. \u0412 \u043a\u0430\u0436\u0434\u043e\u043c \u0440\u044f\u0434\u0443 4 \u043c\u0435\u0441\u0442\u0430.", + "Plane.description2": "\u0412 \u0441\u0430\u043c\u043e\u043b\u0451\u0442\u0435 2 \u043c\u0435\u0441\u0442\u0430 \u0434\u043b\u044f \u043f\u0438\u043b\u043e\u0442\u0430 \u0438 \u0435\u0433\u043e \u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u044f\u0434\u043e\u0432 \u0441 \u043f\u0430\u0441\u0441\u0430\u0436\u0438\u0440\u0441\u043a\u0438\u043c\u0438 \u043c\u0435\u0441\u0442\u0430\u043c\u0438. \u0412 \u043a\u0430\u0436\u0434\u043e\u043c \u0440\u044f\u0434\u0443 4 \u043c\u0435\u0441\u0442\u0430.", + "Plane.description3": "\u0412 \u0441\u0430\u043c\u043e\u043b\u0451\u0442\u0435 2 \u043c\u0435\u0441\u0442\u0430 \u0434\u043b\u044f \u043f\u0438\u043b\u043e\u0442\u0430 \u0438 \u0435\u0433\u043e \u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a\u0430, \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u044f\u0434\u043e\u0432 \u0441 \u043f\u0430\u0441\u0441\u0430\u0436\u0438\u0440\u0441\u043a\u0438\u043c\u0438 \u043c\u0435\u0441\u0442\u0430\u043c\u0438 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u044f\u0434\u043e\u0432 \u0441 \u043f\u0430\u0441\u0441\u0430\u0436\u0438\u0440\u0441\u043a\u0438\u043c\u0438 \u043c\u0435\u0441\u0442\u0430\u043c\u0438 \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430. \u0412 \u043a\u0430\u0436\u0434\u043e\u043c \u0440\u044f\u0434\u0443 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 4 \u043c\u0435\u0441\u0442\u0430. \u0412 \u043a\u0430\u0436\u0434\u043e\u043c \u0440\u044f\u0434\u0443 \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 5 \u043c\u0435\u0441\u0442.", + "Plane.instructions": "\u041f\u043e\u0441\u0442\u0440\u043e\u0439\u0442\u0435 \u0444\u043e\u0440\u043c\u0443\u043b\u0443 \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043d\u0438\u0436\u0435, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0435\u0441\u0442 \u0432 \u0441\u0430\u043c\u043e\u043b\u0451\u0442\u0435 (\u043a\u0430\u043a \u043d\u0430 \u0440\u0438\u0441\u0443\u043d\u043a\u0435 \u0432\u044b\u0448\u0435).", + "Puzzle.country1": "\u0410\u0432\u0441\u0442\u0440\u0430\u043b\u0438\u044f", + "Puzzle.country1Language": "\u0410\u043d\u0433\u043b\u0438\u0439\u0441\u043a\u0438\u0439", + "Puzzle.country1City1": "\u041c\u0435\u043b\u044c\u0431\u0443\u0440\u043d", + "Puzzle.country1City2": "\u0421\u0438\u0434\u043d\u0435\u0439", + "Puzzle.country1HelpUrl": "http://ru.wikipedia.org/wiki/\u0410\u0432\u0441\u0442\u0440\u0430\u043b\u0438\u044f", + "Puzzle.country2": "\u0413\u0435\u0440\u043c\u0430\u043d\u0438\u044f", + "Puzzle.country2Language": "\u041d\u0435\u043c\u0435\u0446\u043a\u0438\u0439", + "Puzzle.country2City1": "\u0411\u0435\u0440\u043b\u0438\u043d", + "Puzzle.country2City2": "\u041c\u044e\u043d\u0445\u0435\u043d", + "Puzzle.country2HelpUrl": "http://ru.wikipedia.org/wiki/\u0413\u0435\u0440\u043c\u0430\u043d\u0438\u044f", + "Puzzle.country3": "\u041a\u0438\u0442\u0430\u0439", + "Puzzle.country3Language": "\u041a\u0438\u0442\u0430\u0439\u0441\u043a\u0438\u0439", + "Puzzle.country3City1": "\u041f\u0435\u043a\u0438\u043d", + "Puzzle.country3City2": "\u0428\u0430\u043d\u0445\u0430\u0439", + "Puzzle.country3HelpUrl": "http://ru.wikipedia.org/wiki/\u041a\u0438\u0442\u0430\u0439", + "Puzzle.country4": "\u0411\u0440\u0430\u0437\u0438\u043b\u0438\u044f", + "Puzzle.country4Language": "\u041f\u043e\u0440\u0442\u0443\u0433\u0430\u043b\u044c\u0441\u043a\u0438\u0439", + "Puzzle.country4City1": "\u0420\u0438\u043e-\u0434\u0435-\u0416\u0430\u043d\u0435\u0439\u0440\u043e", + "Puzzle.country4City2": "\u0421\u0430\u043d-\u041f\u0430\u0443\u043b\u0443", + "Puzzle.country4HelpUrl": "http://ru.wikipedia.org/wiki/\u0411\u0440\u0430\u0437\u0438\u043b\u0438\u044f", + "Puzzle.flag": "\u0444\u043b\u0430\u0433:", + "Puzzle.language": "\u044f\u0437\u044b\u043a:", + "Puzzle.languageChoose": "\u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435...", + "Puzzle.cities": "\u0433\u043e\u0440\u043e\u0434\u0430:", + "Puzzle.error0": "\u0418\u0434\u0435\u0430\u043b\u044c\u043d\u043e!\n\u0412\u0441\u0435 \u0431\u043b\u043e\u043a\u0438 (%1) \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u044b \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e.", + "Puzzle.error1": "\u041f\u043e\u0447\u0442\u0438! \u041e\u0434\u0438\u043d \u0431\u043b\u043e\u043a \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e.", + "Puzzle.error2": "\u041d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u043b\u043e\u043a\u043e\u0432 (%1) \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u044b \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e.", + "Puzzle.tryAgain": "\u0412\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u0431\u043b\u043e\u043a \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e.\n\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0435\u0449\u0451.", + "Puzzle.title": "\u0413\u043e\u043b\u043e\u0432\u043e\u043b\u043e\u043c\u043a\u0430", + "Puzzle.help": "\u041f\u043e\u043c\u043e\u0449\u044c", + "Puzzle.checkAnswers": "\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043e\u0442\u0432\u0435\u0442\u044b", + "Puzzle.helpText": "\u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u044b (\u0437\u0435\u043b\u0435\u043d\u044b\u0439), \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u0438\u0442\u0435 \u0435\u0451 \u0444\u043b\u0430\u0433, \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u044f\u0437\u044b\u043a, \u0438 \u0443\u043a\u0430\u0436\u0438\u0442\u0435 \u0433\u043e\u0440\u043e\u0434\u0430, \u043d\u0430\u0445\u043e\u0434\u044f\u0449\u0438\u0435\u0441\u044f \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0435.", + "Turtle.moveTooltip": "\u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0447\u0435\u0440\u0435\u043f\u0430\u0445\u0443 \u0432\u043f\u0435\u0440\u0451\u0434 \u0438\u043b\u0438 \u043d\u0430\u0437\u0430\u0434 \u043d\u0430 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0435 \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435.", + "Turtle.moveForward": "\u043f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432\u043f\u0435\u0440\u0451\u0434 \u043d\u0430", + "Turtle.moveBackward": "\u043f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u043d\u0430\u0437\u0430\u0434 \u043d\u0430", + "Turtle.turnTooltip": "\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0447\u0435\u0440\u0435\u043f\u0430\u0445\u0443 \u043d\u0430\u043b\u0435\u0432\u043e \u0438\u043b\u0438 \u043d\u0430\u043f\u0440\u0430\u0432\u043e \u043d\u0430 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u0439 \u0443\u0433\u043e\u043b \u0432 \u0433\u0440\u0430\u0434\u0443\u0441\u0430\u0445.", + "Turtle.turnRight": "\u043f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043d\u0430\u043f\u0440\u0430\u0432\u043e \u043d\u0430", + "Turtle.turnLeft": "\u043f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043d\u0430\u043b\u0435\u0432\u043e \u043d\u0430", + "Turtle.widthTooltip": "\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0448\u0438\u0440\u0438\u043d\u0443 \u043f\u0435\u0440\u0430.", + "Turtle.setWidth": "\u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0448\u0438\u0440\u0438\u043d\u0443", + "Turtle.colourTooltip": "\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0446\u0432\u0435\u0442 \u043f\u0435\u0440\u0430.", + "Turtle.setColour": "\u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0446\u0432\u0435\u0442", + "Turtle.penTooltip": "\u041f\u043e\u0434\u043d\u044f\u0442\u044c \u0438\u043b\u0438 \u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u0435\u0440\u043e \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0438\u043b\u0438 \u043f\u0440\u0438\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f.", + "Turtle.penUp": "\u043f\u043e\u0434\u043d\u044f\u0442\u044c \u043f\u0435\u0440\u043e", + "Turtle.penDown": "\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u0435\u0440\u043e", + "Turtle.turtleVisibilityTooltip": "\u0421\u0434\u0435\u043b\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u043f\u0430\u0445\u0443 (\u043e\u043a\u0440\u0443\u0436\u043d\u043e\u0441\u0442\u044c \u0438 \u0441\u0442\u0440\u0435\u043b\u043a\u0443) \u0432\u0438\u0434\u0438\u043c\u043e\u0439 \u0438\u043b\u0438 \u043d\u0435\u0432\u0438\u0434\u0438\u043c\u043e\u0439.", + "Turtle.hideTurtle": "\u0441\u043a\u0440\u044b\u0442\u044c \u0447\u0435\u0440\u0435\u043f\u0430\u0445\u0443", + "Turtle.showTurtle": "\u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u043f\u0430\u0445\u0443", + "Turtle.printHelpUrl": "http://ru.wikipedia.org/wiki/\u041a\u043d\u0438\u0433\u043e\u043f\u0435\u0447\u0430\u0442\u0430\u043d\u0438\u0435", + "Turtle.printTooltip": "\u041d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442 \u0432 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0438 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u0447\u0435\u0440\u0435\u043f\u0430\u0445\u0438.", + "Turtle.print": "\u043d\u0430\u043f\u0435\u0447\u0430\u0442\u0430\u0442\u044c", + "Turtle.fontHelpUrl": "http://ru.wikipedia.org/wiki/\u0428\u0440\u0438\u0444\u0442", + "Turtle.fontTooltip": "\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0448\u0440\u0438\u0444\u0442 \u0434\u043b\u044f \u0431\u043b\u043e\u043a\u0430 \u043f\u0435\u0447\u0430\u0442\u0438.", + "Turtle.font": "\u0448\u0440\u0438\u0444\u0442", + "Turtle.fontSize": "\u0440\u0430\u0437\u043c\u0435\u0440 \u0448\u0440\u0438\u0444\u0442\u0430", + "Turtle.fontNormal": "\u043e\u0431\u044b\u0447\u043d\u044b\u0439", + "Turtle.fontBold": "\u0436\u0438\u0440\u043d\u044b\u0439", + "Turtle.fontItalic": "\u043a\u0443\u0440\u0441\u0438\u0432", + "Turtle.unloadWarning": "\u0417\u0430\u043a\u0440\u044b\u0442\u0438\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u0442 \u043a \u043f\u043e\u0442\u0435\u0440\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0445\u0435\u043c.", + "Turtle.title": "\u0427\u0435\u0440\u0435\u043f\u0430\u0448\u044c\u044f \u0433\u0440\u0430\u0444\u0438\u043a\u0430", + "Turtle.runTooltip": "\u0427\u0435\u0440\u0435\u043f\u0430\u0445\u0430 \u0441\u0434\u0435\u043b\u0430\u0435\u0442 \u0432\u0441\u0451, \u0447\u0442\u043e \u0441\u043a\u0430\u0436\u0443\u0442 \u0435\u0439 \u0431\u043b\u043e\u043a\u0438.", + "Turtle.captureTooltip": "\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0440\u0438\u0441\u0443\u043d\u043e\u043a.", + "Turtle.imgFilename": "drawing.png", + "Turtle.catTurtle": "\u0427\u0435\u0440\u0435\u043f\u0430\u0445\u0430" +} \ No newline at end of file diff --git a/apps/json/sk.json b/apps/json/sk.json new file mode 100644 index 000000000..fef212dc8 --- /dev/null +++ b/apps/json/sk.json @@ -0,0 +1,151 @@ +{ + "@metadata": { + "authors": [ + "Kusavica", + "Marian.stano", + "Rudko" + ] + }, + "Apps.subtitle": "vizu\u00e1lne programovacie prostredie", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Prezrie\u0165 vygenerovan\u00fd javascriptov\u00fd k\u00f3d.", + "Apps.linkTooltip": "Ulo\u017ei\u0165 a zdie\u013ea\u0165 odkaz na tento program.", + "Apps.runTooltip": "Spusti\u0165 program, zlo\u017een\u00fd z dielcov na pracovnej ploche.", + "Apps.runProgram": "Spusti\u0165 program", + "Apps.resetProgram": "Odznova", + "Apps.dialogOk": "OK", + "Apps.dialogCancel": "Zru\u0161i\u0165", + "Apps.catLogic": "Logika", + "Apps.catLoops": "Cykly", + "Apps.catMath": "Matematick\u00e9", + "Apps.catText": "Text", + "Apps.catLists": "Zoznamy", + "Apps.catColour": "Farby", + "Apps.catVariables": "Premenn\u00e9", + "Apps.catProcedures": "Proced\u00fary", + "Apps.httpRequestError": "Probl\u00e9m so spracovan\u00edm po\u017eiadavky.", + "Apps.linkAlert": "Zdie\u013ea\u0165 tento program skop\u00edrovan\u00edm odkazu\n\n%1", + "Apps.hashError": "Prep\u00e1\u010d, '%1' nie je meno \u017eiadnemu ulo\u017een\u00e9mu programu.", + "Apps.xmlError": "Nebolo mo\u017en\u00e9 na\u010d\u00edta\u0165 ulo\u017een\u00fd s\u00fabor. Mo\u017eno bol vytvoren\u00fd v inej verzii Blocky.", + "Apps.listVariable": "zoznam", + "Apps.textVariable": "text", + "Code.badXml": "Chyba pri parsovan\u00ed XML:\n%1\n\nStla\u010dte 'OK' ak chcete zru\u0161i\u0165 zmeny alebo 'Zru\u0161i\u0165' pre pokra\u010dovanie v \u00faprav\u00e1ch XML.", + "Code.badCode": "Chyba v programe:\n%1", + "Code.timeout": "Bol prekro\u010den\u00fd maxim\u00e1lny po\u010det opakovan\u00ed.", + "Code.discard": "Zmaza\u0165 v\u0161etk\u00fdch %1 dielcov?", + "Code.title": "K\u00f3d", + "Code.blocks": "Bloky", + "Code.trashTooltip": "Zahodi\u0165 v\u0161etky dielce.", + "Graph.title": "Grafick\u00e1 kalkula\u010dka", + "Maze.moveForward": "cho\u010f dopredu", + "Maze.turnLeft": "oto\u010d sa v\u013eavo", + "Maze.turnRight": "oto\u010d sa vpravo", + "Maze.doCode": "urob", + "Maze.elseCode": "inak", + "Maze.helpIfElse": "Pr\u00edkaz ak-tak urob\u00ed bu\u010f jedno, alebo druh\u00e9.", + "Maze.pathAhead": "ak je cesta pred", + "Maze.pathLeft": "ak je cesta v\u013eavo", + "Maze.pathRight": "ak je cesta vpravo", + "Maze.repeatUntil": "opakuj a\u017e do", + "Maze.moveForwardTooltip": "Posun hr\u00e1\u010da o jednu d\u013a\u017eku dopredu.", + "Maze.turnTooltip": "Oto\u010di\u0165 hr\u00e1\u010da o 90 stup\u0148ov v\u013eavo \u010di vpravo.", + "Maze.ifTooltip": "Ak je t\u00fdm smerom cesta, vykonaj pr\u00edkazy.", + "Maze.ifelseTooltip": "Ak je t\u00fdm smerom cesta, vykonaj prv\u00fd blok pr\u00edkazov. Inak vykonaj druh\u00fd blok pr\u00edkazov.", + "Maze.whileTooltip": "Opakuj pr\u00edkazy vo vn\u00fatri a\u017e k\u00fdm nepr\u00edde\u0161 do cie\u013ea.", + "Maze.capacity0": "Zostalo ti %0 dielcov.", + "Maze.capacity1": "M\u00e1\u0161 u\u017e iba %1 diel.", + "Maze.capacity2": "Zostalo ti e\u0161te %2 dielcov.", + "Maze.nextLevel": "Gratulujeme! Priprav sa na na vstup do levelu %2!", + "Maze.finalLevel": "Gratulujeme! Posledn\u00fd level je \u0161\u0165astne vyrie\u0161en\u00fd!", + "Maze.maze": "Bludisko", + "Maze.runTooltip": "Postavi\u010dka urob\u00ed to, \u010do je nap\u00edsan\u00e9 na dielci.", + "Maze.resetTooltip": "Presun\u00fa\u0165 postavi\u010dku sp\u00e4\u0165 na za\u010diatok bludiska.", + "Maze.helpStack": "Program je postupnos\u0165 dielcov. Spoj dokopy nieko\u013eko dielcov 'pohyb vpred' a pom\u00f4\u017e mi pr\u00eds\u0165 do cie\u013ea.", + "Maze.helpOneTopBlock": "Na tejto \u00farovni mus\u00ed\u0161 na bielej ploche posklada\u0165 v\u0161etky diely sklada\u010dky.", + "Maze.helpRun": "Spusti svoj program, aby si videl \u010do sa stane.", + "Maze.helpReset": "V\u00e1\u0161 program nepre\u0161iel cez bludisko. Stla\u010dte tla\u010didlo \"Obnovi\u0165\" a sk\u00faste to znova.", + "Maze.helpRepeat": "Pam\u00e4te v po\u010d\u00edta\u010doch nikdy nie je dos\u0165. Dosiahni cie\u013e len pou\u017e\u00edt\u00edm dvoch blokov. Na zopakovanie pr\u00edkazu pou\u017ei pr\u00edkaz 'opakuj'.", + "Maze.helpCapacity": "Pou\u017eili ste v\u0161etky bloky dostupn\u00e9 pre t\u00fato \u00farove\u0148. Ak chcete vytvori\u0165 nov\u00fd blok, mus\u00edte najprv odstr\u00e1ni\u0165 existuj\u00faci.", + "Maze.helpRepeatMany": "Mo\u017ete upravi\u0165 viac ako jeden blok v r\u00e1mci 'repeat' bloku.", + "Maze.helpIf": "Dielec 'ak' urob\u00ed nie\u010do len vtedy, ak je splnen\u00e1 podmienka. Sk\u00fas oto\u010denie v\u013eavo, ak je cesta na\u013eavo.", + "Maze.helpMenu": "Klikni na %1 v 'ak' bloku pre zmenu jeho stavu.", + "Maze.helpWallFollow": "A zvl\u00e1dne\u0161 aj toto komplikovan\u00e9 bludisko? Sk\u00fas \u00eds\u0165 popri \u013eavej stene. Len pre pokro\u010dil\u00fdch program\u00e1torov!", + "Plane.rows": "Rady: %1", + "Plane.getRows": "rady (%1)", + "Plane.rows1": "rady 1. trieda: %1", + "Plane.getRows1": "rady 1. trieda (%1)", + "Plane.rows2": "rady 2. trieda: %1", + "Plane.getRows2": "rady 2. trieda (%1)", + "Plane.seats": "Sedadiel: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "sedadl\u00e1 =", + "Plane.plane": "Lietadlo", + "Plane.description1": "Lietadlo m\u00e1 nieko\u013eko radov sedadiel. Ka\u017ed\u00fd rad obsahuje \u0161tyri sedadl\u00e1.", + "Plane.description2": "Lietadlo m\u00e1 dve sedadl\u00e1 v kab\u00edne pilota (pre kapit\u00e1na a kopilota), a ve\u013ea radov sedadiel pre cestuj\u00facich. Ka\u017ed\u00fd rad obsahuje \u0161tyri sedadl\u00e1.", + "Plane.description3": "Lietadlo m\u00e1 dve sedadl\u00e1 v kab\u00edne pilota (pre kapit\u00e1na a kopilota), a ve\u013ea radov sedadiel pre cestuj\u00facich v 1. a 2. triede. Ka\u017ed\u00fd rad 1. triedy m\u00e1 \u0161tyri sedadl\u00e1. Ka\u017ed\u00fd rad 2. triedy m\u00e1 p\u00e4\u0165 sedadiel.", + "Plane.instructions": "Nap\u00ed\u0161 vzorec (dole), ktor\u00fd vypo\u010d\u00edta celkov\u00fd po\u010det sedadiel v lietadle po zmene radov (hore).", + "Puzzle.country1": "Austr\u00e1lia", + "Puzzle.country1Language": "Angli\u010dtina", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://sk.wikipedia.org/wiki/Austr%C3%A1lia_%28%C5%A1t%C3%A1t%29", + "Puzzle.country2": "Nemecko", + "Puzzle.country2Language": "Nem\u010dina", + "Puzzle.country2City1": "Berl\u00edn", + "Puzzle.country2City2": "Mn\u00edchov", + "Puzzle.country2HelpUrl": "http://sk.wikipedia.org/wiki/Nemecko", + "Puzzle.country3": "\u010c\u00edna", + "Puzzle.country3Language": "\u010c\u00edn\u0161tina", + "Puzzle.country3City1": "Peking", + "Puzzle.country3City2": "\u0160anghaj", + "Puzzle.country3HelpUrl": "http://sk.wikipedia.org/wiki/%C4%8C%C3%ADna", + "Puzzle.country4": "Braz\u00edlia", + "Puzzle.country4Language": "Portugal\u010dina", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "S\u00e3o Paulo", + "Puzzle.country4HelpUrl": "http://sk.wikipedia.org/wiki/Braz%C3%ADlia", + "Puzzle.flag": "vlajka:", + "Puzzle.language": "jazyk:", + "Puzzle.languageChoose": "zvoli\u0165...", + "Puzzle.cities": "mest\u00e1:", + "Puzzle.error0": "V\u00fdborne!\nV\u0161etk\u00fdch %1 blokov je na svojom mieste.", + "Puzzle.error1": "Takmer! Jeden blok je nespr\u00e1vne.", + "Puzzle.error2": "%1 blokov je nespr\u00e1vne.", + "Puzzle.tryAgain": "Zv\u00fdraznen\u00fd blok je nespr\u00e1vne.\nSk\u00fa\u0161aj \u010falej.", + "Puzzle.title": "Sklada\u010dka", + "Puzzle.help": "Pomoc", + "Puzzle.checkAnswers": "Skontrolova\u0165 odpovede", + "Puzzle.helpText": "Ku ka\u017edej krajine (zelen\u00e1) prira\u010f jej vlajku, jazyk a mest\u00e1.", + "Turtle.moveTooltip": "Presunie korytna\u010dku dopredu alebo dozadu o ur\u010dit\u00fd po\u010det krokov.", + "Turtle.moveForward": "posun\u00fa\u0165 dopredu o", + "Turtle.moveBackward": "posun\u00fa\u0165 vzad o", + "Turtle.turnTooltip": "Korytna\u010dka sa oto\u010d\u00ed v\u013eavo alebo vpravo o zadan\u00fd po\u010det stup\u0148ov.", + "Turtle.turnRight": "oto\u010di\u0165 v\u013eavo o", + "Turtle.turnLeft": "oto\u010di\u0165 v\u013eavo o", + "Turtle.widthTooltip": "Zmeni\u0165 hr\u00fabku pera.", + "Turtle.setWidth": "nastavi\u0165 \u0161\u00edrku", + "Turtle.colourTooltip": "Zmeni\u0165 farbu pera.", + "Turtle.setColour": "nastavi\u0165 farbu", + "Turtle.penTooltip": "Pero hore alebo dole, skon\u010d\u00ed alebo za\u010dne kresli\u0165.", + "Turtle.penUp": "pero hore", + "Turtle.penDown": "pero dole", + "Turtle.turtleVisibilityTooltip": "Urob\u00ed korytna\u010dku(kr\u00fa\u017eok so \u0161\u00edpkou) vidite\u013en\u00fa alebo nevidite\u013en\u00fa.", + "Turtle.hideTurtle": "skry\u0165 korytna\u010dku", + "Turtle.showTurtle": "uk\u00e1za\u0165 korytna\u010dku", + "Turtle.printHelpUrl": "http://sk.wikipedia.org/wiki/Kn%C3%ADhtla%C4%8D", + "Turtle.printTooltip": "Vyp\u00ed\u0161e text na poz\u00edcii korytna\u010dky v smere jej nato\u010denia.", + "Turtle.print": "tla\u010di\u0165", + "Turtle.fontHelpUrl": "http://sk.wikipedia.org/wiki/Font_%28po%C4%8D%C3%ADta%C4%8De%29", + "Turtle.fontTooltip": "Nastav\u00ed p\u00edsmo, ktor\u00e9 pou\u017e\u00edva tla\u010dov\u00fd dielec.", + "Turtle.font": "p\u00edsmo", + "Turtle.fontSize": "ve\u013ekos\u0165 p\u00edsma", + "Turtle.fontNormal": "norm\u00e1lne", + "Turtle.fontBold": "tu\u010dn\u00e9", + "Turtle.fontItalic": "kurz\u00edva", + "Turtle.unloadWarning": "Ak opust\u00ed\u0161 teraz t\u00fato str\u00e1nku, strat\u00ed\u0161 v\u0161etku vykonan\u00fa pr\u00e1cu.", + "Turtle.title": "Korytna\u010dia grafika", + "Turtle.runTooltip": "Korytna\u010dka vykon\u00e1 to, \u010do je nap\u00edsan\u00e9 na dielci.", + "Turtle.captureTooltip": "Ulo\u017ei\u0165 kresbu.", + "Turtle.imgFilename": "kresba.png", + "Turtle.catTurtle": "Korytna\u010dka" +} \ No newline at end of file diff --git a/apps/json/sr-ec.json b/apps/json/sr-ec.json new file mode 100644 index 000000000..bd38bc611 --- /dev/null +++ b/apps/json/sr-ec.json @@ -0,0 +1,32 @@ +{ + "Puzzle.country3City2": "Шангај", + "Puzzle.country3HelpUrl": "http://sr.wikipedia.org/wiki/Кина", + "Puzzle.country3Language": "кинески", + "Puzzle.language": "језик:", + "Apps.dialogOk": "У реду", + "Puzzle.title": "Слагалица", + "Puzzle.country1HelpUrl": "http://sr.wikipedia.org/wiki/Аустралија", + "Puzzle.languageChoose": "изаберите...", + "Puzzle.country4City2": "Сао Пауло", + "Puzzle.country4City1": "Рио де Жанеиро", + "Puzzle.country4Language": "португалски", + "Puzzle.flag": "ознака:", + "Puzzle.country4HelpUrl": "http://sr.wikipedia.org/wiki/Бразил", + "Puzzle.error1": "Умало! Један блок је неисправно постављен.", + "Puzzle.country3City1": "Пекинг", + "Puzzle.country1City1": "Мелбурн", + "Puzzle.country1City2": "Сиднеј", + "Puzzle.country2Language": "немачки", + "Puzzle.country3": "Кина", + "Puzzle.country2": "Немачка", + "Puzzle.country1": "Аустралија", + "Puzzle.country2HelpUrl": "http://sr.wikipedia.org/wiki/Немачка", + "Puzzle.error0": "Савршено!\nСвих %1 блокова је исправно постављено.", + "Puzzle.country4": "Бразил", + "Puzzle.error2": "%1 блокова је неисправно постављено.", + "Puzzle.help": "Помоћ", + "Puzzle.country1Language": "енглески", + "Puzzle.country2City1": "Берлин", + "Puzzle.cities": "градови:", + "Puzzle.country2City2": "Минхен" +} diff --git a/apps/json/sr.json b/apps/json/sr.json new file mode 100644 index 000000000..05dc12b0a --- /dev/null +++ b/apps/json/sr.json @@ -0,0 +1,38 @@ +{ + "Maze.pathAhead": "ако постоји пут напред", + "Maze.maze": "Лавиринт", + "Apps.hashError": "Жао нам је, '%1' не одговара ни једној сачуваној Блокли датотеци.", + "Apps.xmlError": "Не могу да учитам датотеку коју сте сачували. Можда је направљена другом верзијом Блоклија?", + "Maze.doCode": "ради", + "Maze.helpOneTopBlock": "На овом нивоу, потребно је да поређаш све блокове у бели радни простор.", + "Apps.blocklyMessage": "Blockly (Блоклијев)", + "Maze.ifTooltip": "Ако постоји пут у датом правцу, онда уради следеће.", + "Apps.httpRequestError": "Настао је проблем при извршењу траженог.", + "Maze.turnTooltip": "Окреће Штипаљка лево или десно за 90 степени.", + "Maze.whileTooltip": "Понављај следеће акције док не комплетираш задатак.", + "Maze.helpWallFollow": "Можеш ли да решиш овај сложени лавиринт? Покшај да се крећеш уз леви зид.", + "Maze.turnRight": "окрени се десно", + "Maze.finalLevel": "Честитамо! Решили сте последњи ниво.", + "Apps.linkAlert": "Делите своје блокове употребом ове везе:\n\n%1", + "Maze.capacity0": "Број блокова који ти је остао је %0.", + "Maze.capacity1": "Број блокова који ти је остао је %1.", + "Maze.capacity2": "Број блокова који ти је остао је %2.", + "Maze.repeatUntil": "понављај док не", + "Maze.moveForward": "иди напред", + "Apps.codeTooltip": "Погледај генерисани JavaScript код.", + "Maze.pathRight": "ако постоји пут десно", + "Maze.nextLevel": "Честитамо! Да ли сте спремни да пређете на ниво %1?", + "Maze.helpStack": "Наређај неколико 'иди напред' блокова да би ми помогао да достигнем циљ.", + "Maze.helpRepeat": "Рачунари имају ограничену меморију. Дођи до краја пута употребивши само два блока. Искористи 'понављај' да би извршио блок бише пута.", + "Maze.helpRepeatMany": "Достигни циљ употребом само пет блокова.", + "Maze.helpIf": "'ако' блок ће урадити нешто једино ако је услов испуњен. Покушај окрет у лево ако постоји пут са леве стране.", + "Maze.helpIfElse": "Ако-у-супротмом блок урадиће једно или друго.", + "Apps.runProgram": "Покрени програм", + "Apps.resetProgram": "Поново постави", + "Maze.pathLeft": "ако постоји пут лово", + "Maze.turnLeft": "окрени се лево", + "Apps.linkTooltip": "Сачувај и повежи са блоковима.", + "Maze.ifelseTooltip": "Ако постоји пут у датом правцу, онда изврши прву групу акција. У супротном, уради другу групу акција.", + "Maze.elseCode": "у супротном", + "Maze.moveForwardTooltip": "Помера Штипаљка једну позицију напред." +} diff --git a/apps/json/sv.json b/apps/json/sv.json new file mode 100644 index 000000000..b90092950 --- /dev/null +++ b/apps/json/sv.json @@ -0,0 +1,151 @@ +{ + "@metadata": { + "authors": [ + "Jopparn", + "WikiPhoenix" + ] + }, + "Apps.subtitle": "en visuell programmeringsmilj\u00f6", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Se genererad JavaScript-kod.", + "Apps.linkTooltip": "Spara och l\u00e4nka till block.", + "Apps.runTooltip": "K\u00f6r programmet definierat av blocken i arbetsytan.", + "Apps.runProgram": "K\u00f6r program", + "Apps.resetProgram": "\u00c5terst\u00e4ll", + "Apps.dialogOk": "OK", + "Apps.dialogCancel": "Avbryt", + "Apps.catLogic": "Logisk", + "Apps.catLoops": "Loopar", + "Apps.catMath": "Matematik", + "Apps.catText": "Text", + "Apps.catLists": "Listor", + "Apps.catColour": "F\u00e4rg", + "Apps.catVariables": "Variabler", + "Apps.catProcedures": "Procedurer", + "Apps.httpRequestError": "Det uppstod ett problem med beg\u00e4ran.", + "Apps.linkAlert": "Dela dina block med denna l\u00e4nk: \n\n%1", + "Apps.hashError": "Tyv\u00e4rr, '%1' \u00f6verensst\u00e4mmer inte med n\u00e5got sparat program.", + "Apps.xmlError": "Kunde inte l\u00e4sa din sparade fil. Den skapades kanske med en annan version av Blockly?", + "Apps.listVariable": "lista", + "Apps.textVariable": "text", + "Code.badXml": "Fel vid parsning av XML:\n%1\n\nKlicka p\u00e5 'OK' f\u00f6r att avst\u00e5 fr\u00e5n dina \u00e4ndringar eller 'Avbryt' f\u00f6r att forts\u00e4tta redigera XML-koden.", + "Code.badCode": "Programfel:\n%1", + "Code.timeout": "Maximala antalet utf\u00f6rda loopar \u00f6verskred.", + "Code.discard": "Radera alla %1 block?", + "Code.title": "Kod", + "Code.blocks": "Block", + "Code.trashTooltip": "Sl\u00e4ng alla block.", + "Graph.title": "Grafritande minir\u00e4knare", + "Maze.moveForward": "g\u00e5 fram\u00e5t", + "Maze.turnLeft": "sv\u00e4ng v\u00e4nster", + "Maze.turnRight": "sv\u00e4ng h\u00f6ger", + "Maze.doCode": "utf\u00f6r", + "Maze.elseCode": "annars", + "Maze.helpIfElse": "Om-annars-block kommer att g\u00f6ra det ena eller det andra.", + "Maze.pathAhead": "om det \u00e4r en v\u00e4g fram\u00e5t", + "Maze.pathLeft": "om det \u00e4r en v\u00e4g till v\u00e4nster", + "Maze.pathRight": "om det \u00e4r en v\u00e4g till h\u00f6ger", + "Maze.repeatUntil": "upprepa tills", + "Maze.moveForwardTooltip": "Flyttar spelaren fram\u00e5t en ruta.", + "Maze.turnTooltip": "Sv\u00e4nger spelaren 90 grader till v\u00e4nster eller h\u00f6ger.", + "Maze.ifTooltip": "Om det finns en v\u00e4g i angiven riktning, g\u00f6r vissa handlingar.", + "Maze.ifelseTooltip": "Om det finns en v\u00e4g i angiven riktning, g\u00f6r d\u00e5 det f\u00f6rsta blocket av \u00e5tg\u00e4rder. Annars, g\u00f6r den andra blocket av \u00e5tg\u00e4rder.", + "Maze.whileTooltip": "Upprepa de slutna kommandonen till dess att slutpunkten n\u00e5s.", + "Maze.capacity0": "Du har %0 block kvar.", + "Maze.capacity1": "Du har %1 block kvar.", + "Maze.capacity2": "Du har %2 block kvar.", + "Maze.nextLevel": "Grattis! \u00c4r du redo att g\u00e5 vidare till niv\u00e5 %1?", + "Maze.finalLevel": "Grattis! Du har l\u00f6st den sista niv\u00e5n.", + "Maze.maze": "Labyrint", + "Maze.runTooltip": "F\u00e5r spelaren att g\u00f6ra vad blocken s\u00e4ger.", + "Maze.resetTooltip": "L\u00e4gger tillbaka spelaren till labyrintens b\u00f6rjan.", + "Maze.helpStack": "Stapla ett par 'g\u00e5 fram\u00e5t'-block f\u00f6r att hj\u00e4lpa mig att n\u00e5 m\u00e5let.", + "Maze.helpOneTopBlock": "P\u00e5 den h\u00e4r niv\u00e5n m\u00e5ste du stapla alla block tillsammans i det vita arbetsomr\u00e5det.", + "Maze.helpRun": "K\u00f6r ditt program f\u00f6r att se vad som h\u00e4nder.", + "Maze.helpReset": "Ditt program l\u00f6ste inte labyrinten. Tryck p\u00e5 '\u00c5terst\u00e4ll' och f\u00f6rs\u00f6k igen.", + "Maze.helpRepeat": "N\u00e5 slutet av denna v\u00e4g med endast tv\u00e5 block. Anv\u00e4nd 'upprepa' f\u00f6r att anv\u00e4nda ett block mer \u00e4n en g\u00e5ng.", + "Maze.helpCapacity": "Du har anv\u00e4nt alla block f\u00f6r denna niv\u00e5. F\u00f6r att skapa ett nytt block m\u00e5ste du f\u00f6rst radera ett befintligt block.", + "Maze.helpRepeatMany": "Du f\u00e5r plats med mer \u00e4n ett block i ett upprepningsblock.", + "Maze.helpSkins": "V\u00e4lj din favoritspelare fr\u00e5n denna meny.", + "Maze.helpIf": "Ett 'om'-block kommer endast att g\u00f6ra n\u00e5gonting om villkoret \u00e4r sant. Pr\u00f6va att sv\u00e4nga v\u00e4nster om det finns en v\u00e4g till v\u00e4nster.", + "Maze.helpMenu": "Klicka p\u00e5 %1 i blocket \"om\" f\u00f6r att \u00e4ndra dess tillst\u00e5nd.", + "Maze.helpWallFollow": "Kan du l\u00f6sa denna komplicerade labyrint? F\u00f6rs\u00f6k att f\u00f6lja den v\u00e4nstra v\u00e4ggen. Endast f\u00f6r avancerade programmerare!", + "Plane.rows": "Rader: %1", + "Plane.getRows": "rader (%1)", + "Plane.rows1": "1:a klassens rader: %1", + "Plane.getRows1": "1:a klassens rader (%1)", + "Plane.rows2": "2:a klassens rader: %1", + "Plane.getRows2": "1:a klassens rader (%1)", + "Plane.seats": "S\u00e4ten: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "sittplatser =", + "Plane.plane": "Plan", + "Plane.description1": "Ett flygplan har ett antal rader med passagerars\u00e4ten. Varje rad inneh\u00e5ller fyra s\u00e4ten.", + "Plane.description2": "Ett flygplan har tv\u00e5 s\u00e4ten i cockpiten (f\u00f6r piloten och andrepiloten) och ett antal rader med passagerars\u00e4ten. Varje rad inneh\u00e5ller fyra s\u00e4ten.", + "Plane.description3": "Ett flygplan har tv\u00e5 s\u00e4ten i cockpiten (f\u00f6r piloten och andrepiloten) och ett antal rader med f\u00f6rsta och andra klassens passagerars\u00e4ten. Varje rad i f\u00f6rsta klass inneh\u00e5ller fyra s\u00e4ten. Varje rad i andra klass inneh\u00e5ller fem s\u00e4ten.", + "Plane.instructions": "Bygg en formel (nedan) som ber\u00e4knar det totala antalet s\u00e4ten p\u00e5 flygplanet n\u00e4r raderna \u00e4ndras (ovan).", + "Puzzle.country1": "Australien", + "Puzzle.country1Language": "Engelska", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://sv.wikipedia.org/wiki/Australien", + "Puzzle.country2": "Tyskland", + "Puzzle.country2Language": "Tyska", + "Puzzle.country2City1": "Berlin", + "Puzzle.country2City2": "M\u00fcnchen", + "Puzzle.country2HelpUrl": "http://sv.wikipedia.org/wiki/Tyskland", + "Puzzle.country3": "Kina", + "Puzzle.country3Language": "Kinesiska", + "Puzzle.country3City1": "Beijing", + "Puzzle.country3City2": "Shanghai", + "Puzzle.country3HelpUrl": "http://sv.wikipedia.org/wiki/Kina", + "Puzzle.country4": "Brasilien", + "Puzzle.country4Language": "Portugisiska", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "S\u00e3o Paulo", + "Puzzle.country4HelpUrl": "http://sv.wikipedia.org/wiki/Brasilien", + "Puzzle.flag": "flagga:", + "Puzzle.language": "spr\u00e5k:", + "Puzzle.languageChoose": "v\u00e4lj...", + "Puzzle.cities": "st\u00e4der:", + "Puzzle.error0": "Perfekt!\nAlla %1 block \u00e4r r\u00e4tt.", + "Puzzle.error1": "N\u00e4stan! Ett block \u00e4r fel.", + "Puzzle.error2": "%1 block \u00e4r fel.", + "Puzzle.tryAgain": "Det markerade blocket \u00e4r inte r\u00e4tt.\nForts\u00e4tt att prova.", + "Puzzle.title": "Pussel", + "Puzzle.help": "Hj\u00e4lp", + "Puzzle.checkAnswers": "Kontrollera svar", + "Puzzle.helpText": "F\u00f6r varje land (gr\u00f6n), s\u00e4tt ut dess flagga, v\u00e4lj dess spr\u00e5k och g\u00f6ra en grupp av dess st\u00e4der.", + "Turtle.moveTooltip": "Flyttar sk\u00f6ldpaddan fram\u00e5t eller bak\u00e5t enligt den angivna summan.", + "Turtle.moveForward": "flytta fram\u00e5t", + "Turtle.moveBackward": "flytta bak\u00e5t", + "Turtle.turnTooltip": "Vrider sk\u00f6ldpaddan v\u00e4nster eller h\u00f6ger enligt det angivna antalet grader.", + "Turtle.turnRight": "sv\u00e4ng h\u00f6ger", + "Turtle.turnLeft": "sv\u00e4ng v\u00e4nster", + "Turtle.widthTooltip": "\u00c4ndrar bredden p\u00e5 pennan.", + "Turtle.setWidth": "anger bredd till", + "Turtle.colourTooltip": "\u00c4ndrar f\u00e4rgen p\u00e5 pennan.", + "Turtle.setColour": "anger f\u00e4rg till", + "Turtle.penTooltip": "Lyfter eller s\u00e4nker pennan, f\u00f6r att sluta eller b\u00f6rja rita.", + "Turtle.penUp": "penna upp", + "Turtle.penDown": "penna ned", + "Turtle.turtleVisibilityTooltip": "G\u00f6r sk\u00f6ldpaddan (cirkel och pil) synlig eller osynlig.", + "Turtle.hideTurtle": "d\u00f6lj sk\u00f6ldpadda", + "Turtle.showTurtle": "visa sk\u00f6ldpadda", + "Turtle.printHelpUrl": "http://sv.wikipedia.org/wiki/Tryckteknik", + "Turtle.printTooltip": "Ritar text i sk\u00f6ldpaddans riktning p\u00e5 dess plats.", + "Turtle.print": "visa", + "Turtle.fontHelpUrl": "http://sv.wikipedia.org/wiki/Vikt_%28typografi%29", + "Turtle.fontTooltip": "Anger typsnitten som anv\u00e4nds av textblocket.", + "Turtle.font": "typsnitt", + "Turtle.fontSize": "teckenstorlek", + "Turtle.fontNormal": "normal", + "Turtle.fontBold": "fet", + "Turtle.fontItalic": "kursiv", + "Turtle.unloadWarning": "Om du l\u00e4mnar denna sida kommer ditt arbete f\u00f6rloras.", + "Turtle.title": "Sk\u00f6ldpaddans grafik", + "Turtle.runTooltip": "F\u00e5r sk\u00f6ldpaddan att g\u00f6ra vad blocken s\u00e4ger.", + "Turtle.captureTooltip": "Spara ritningen.", + "Turtle.imgFilename": "ritning.png", + "Turtle.catTurtle": "Sk\u00f6ldpadda" +} \ No newline at end of file diff --git a/apps/json/sw.json b/apps/json/sw.json new file mode 100644 index 000000000..975fd59dc --- /dev/null +++ b/apps/json/sw.json @@ -0,0 +1,73 @@ +{ + "@metadata": [], + "Apps.subtitle": "mazingira ya programu ya kuona", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Tazama mwandiko wa JavaScript inayotokana.", + "Apps.linkTooltip": "Hifadhi na kiungo cha vishiku.", + "Apps.runProgram": "Endesha Programu", + "Apps.resetProgram": "Seti upya", + "Apps.dialogOk": "Sawa", + "Apps.httpRequestError": "Kuna shida na amri.", + "Apps.linkAlert": "Sambaza vishiku vyako na kiungo hiki: \n\n%1", + "Apps.hashError": "Samahani, '%1' haiendani na faili yoyote ya Blockly.", + "Apps.xmlError": "Upakiaji wa faili yako iliyohifadhiwa haiwezekani. Labda iliundwa na toleo tofauti ya Blockly?", + "Maze.moveForward": "songa mbele", + "Maze.turnLeft": "geuka kushoto", + "Maze.turnRight": "geuka kulia", + "Maze.doCode": "fanya", + "Maze.elseCode": "vingenevyo", + "Maze.helpIfElse": "Hifadhi na kiungo cha vishiku.", + "Maze.pathAhead": "kama kuna njia mbele", + "Maze.pathLeft": "kama kuna njia kusoto", + "Maze.pathRight": "kama kuna njia kulia", + "Maze.repeatUntil": "rudia mpaka", + "Maze.moveForwardTooltip": "Kusogeza Bw. Banzi mbele nafasi moja.", + "Maze.turnTooltip": "Kugeuza Bw. Banzi kushoto au kulia kwa digrii 90.", + "Maze.ifTooltip": "Iwapo mwelekeo uliobainishwa una njia, kisha fanya matendo fulani.", + "Maze.ifelseTooltip": "Iwapo mwelekeo uliobainishwa una njia, kisha fanya seti ya kwanza ya matendo. Vingenevyo, fanya seti ya pili ya matendo.", + "Maze.whileTooltip": "Rudia matendo yalioambatanishwa mpaka mwisho.", + "Maze.capacity0": "Unavyo bado vishiku vi%0.", + "Maze.capacity1": "Unacho bado kishiku kimoja.", + "Maze.capacity2": "Unavyo bado vishiku vi%1.", + "Maze.nextLevel": "Hongera! Uko tayari kuendelea na sehemu ya %1?", + "Maze.finalLevel": "Hongera! Umetatua sehemu ya mwisho.", + "Maze.maze": "Mzingile", + "Maze.helpStack": "Panganya vishiku vichache vya 'songa mbele' ili kunisaidia kufikia lengo.", + "Maze.helpOneTopBlock": "Katika sehemu hii, itabidi upanganye vishiku vyote ndani ya eneo ya kazi nyeupe.", + "Maze.helpRepeat": "Kompyuta ina kumbukumbu ndogo. Fikia mwisho wa njia hii kwa kutumia vishiku viwili tu. Tumia 'rudia' kusudi vishiku viende zaidi ya mara moja.", + "Maze.helpRepeatMany": "Fikia lengo kwa kutumia vishiku vitano tu.", + "Maze.helpIf": "Vishiku vya 'iwapo' vitatenda kama masharti yake ni kweli tu. Jaribu kugeuka kushota kama kuna njia kwenda kushoto.", + "Maze.helpWallFollow": "Je, unaweza kutatua mzingile mgumu huu? Jaribu kufuatia ukuta wa kushoto. Wanaprogramu wa juu tu!", + "Puzzle.country1": "Australia", + "Puzzle.country1Language": "Kingereza", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://sw.wikipedia.org/wiki/Australia", + "Puzzle.country2": "Ujerumani", + "Puzzle.country2Language": "Kijerumani", + "Puzzle.country2City1": "Berlin", + "Puzzle.country2City2": "Munich", + "Puzzle.country2HelpUrl": "http://sw.wikipedia.org/wiki/Ujerumani", + "Puzzle.country3": "China", + "Puzzle.country3Language": "Kichina", + "Puzzle.country3City1": "Beijing", + "Puzzle.country3City2": "Shanghai", + "Puzzle.country3HelpUrl": "http://sw.wikipedia.org/wiki/China", + "Puzzle.country4": "Brazil", + "Puzzle.country4Language": "Kireno", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "Sao Paulo", + "Puzzle.country4HelpUrl": "http://sw.wikipedia.org/wiki/Brazil", + "Puzzle.flag": "bendera:", + "Puzzle.language": "lugha:", + "Puzzle.languageChoose": "chagua...", + "Puzzle.cities": "miji:", + "Puzzle.error0": "Hongera!\nVishiku vyote %1 ni sahihi.", + "Puzzle.error1": "Uko karibu! Kishiku kimoja ni kosefu.", + "Puzzle.error2": "Vishiku vi%1 ni kosefu.", + "Puzzle.tryAgain": "Kishiku kinachobainishwa ni kosefu.", + "Puzzle.title": "Fumbo", + "Puzzle.help": "Huduma", + "Puzzle.checkAnswers": "Kuangalia Majibu", + "Puzzle.helpText": "Kwa kila nchi (kijani), ambatisha bendera yake, kuchagua lugha yake, na kupanganya miji yake." +} \ No newline at end of file diff --git a/apps/json/ta.json b/apps/json/ta.json new file mode 100644 index 000000000..2c4e1280f --- /dev/null +++ b/apps/json/ta.json @@ -0,0 +1,25 @@ +{ + "Puzzle.country3City2": "ஷாங்கை", + "Puzzle.country3City1": "பீஜிங்", + "Puzzle.country3Language": "சீனர்", + "Puzzle.checkAnswers": "விடைகளைச் சோதிக்கவும்", + "Puzzle.language": "மொழி:", + "Apps.dialogOk": "சரி", + "Puzzle.country1Language": "ஆங்கிலம்", + "Puzzle.languageChoose": "தேர்க...", + "Puzzle.country4City1": "ரியோ டி ஜெனிரோ", + "Puzzle.country4Language": "போர்ச்சுகீஸ்", + "Puzzle.flag": "கொடி:", + "Puzzle.country1City1": "மெல்போர்ன்", + "Puzzle.country1City2": "சிட்னி", + "Puzzle.country2Language": "இடாய்ச்சுமொழி (செருமன்)", + "Puzzle.country3": "சீனா", + "Puzzle.country2": "ஜெர்மனி", + "Puzzle.country1": "ஆத்திரேலியா", + "Puzzle.country4": "பிரேசில்", + "Puzzle.help": "உதவி", + "Puzzle.title": "புதிர்", + "Puzzle.country2City1": "பெர்லின்", + "Puzzle.cities": "நகரங்கள்:", + "Puzzle.country2City2": "மூனிச்" +} diff --git a/apps/json/te.json b/apps/json/te.json new file mode 100644 index 000000000..21177308d --- /dev/null +++ b/apps/json/te.json @@ -0,0 +1,24 @@ +{ + "Puzzle.country3City2": "షాంఘై", + "Puzzle.country3City1": "బీజింగ్", + "Puzzle.country3Language": "చైనీ", + "Puzzle.checkAnswers": "జవాబులను సరిచూడు", + "Puzzle.language": "భాష:", + "Apps.dialogOk": "సరే", + "Puzzle.languageChoose": "ఎంచుకోండి...", + "Puzzle.country4City1": "రియో డి జనీరో", + "Puzzle.country4Language": "పోర్చుగీసు", + "Puzzle.flag": "జెండా:", + "Puzzle.country1City1": "మెల్‌బోర్న్", + "Puzzle.country1City2": "సిడ్నీ", + "Puzzle.country2Language": "జర్మన్", + "Puzzle.country3": "చైనా", + "Puzzle.country2": "జర్మనీ", + "Puzzle.country1": "ఆష్ట్రేలియా", + "Puzzle.country4": "బ్రెజిల్", + "Puzzle.help": "సహాయం", + "Puzzle.country1Language": "ఆంగ్లం", + "Puzzle.country2City1": "బెర్లిన్", + "Puzzle.cities": "నగరాలు:", + "Puzzle.country2City2": "మ్యూనిక్" +} diff --git a/apps/json/th.json b/apps/json/th.json new file mode 100644 index 000000000..3e48ea4b2 --- /dev/null +++ b/apps/json/th.json @@ -0,0 +1,38 @@ +{ + "Maze.pathAhead": "ถ้า เส้นทาง ไปข้างหน้า", + "Maze.maze": "เขาวงกต", + "Apps.hashError": "ขอโทษด้วย, '%1' ไม่สอดคล้องกับไฟล์ Blockly ที่บันทึกไว้", + "Apps.xmlError": "ไม่สามารถโหลดไฟล์ที่บันทึกไว้ของคุณได้\nบางทีมันอาจจะถูกสร้างขึ้นด้วย Blockly เวอร์ชันที่แตกต่างกัน?", + "Maze.doCode": "ทำ", + "Maze.helpOneTopBlock": "ในระดับนี้ คุณต้องต่อทุกบล็อคเข้าด้วยกันบนพื้นที่ว่างสีขาว", + "Apps.blocklyMessage": "Blockly (บล็อค-ลี่)", + "Maze.ifTooltip": "ถ้ามีเส้นทางไปทางทิศทางที่กำหนด แล้วให้กระทำการบางอย่าง", + "Apps.httpRequestError": "มีปัญหาเกี่ยวกับการร้องขอ", + "Maze.turnTooltip": "หัน Pegman ไปทางซ้ายหรือขวา 90 องศา", + "Maze.whileTooltip": "ทำซ้ำทุกการกระทำภายใน จนกว่าจะถึงจุดสิ้นสุด", + "Maze.helpWallFollow": "คุณสามารถไขปัญหาเขาวงกตที่ซับซ้อนนี้ได้หรือไม่? -> ลองตามผนังด้านซ้ายมือดู", + "Maze.turnRight": "หัน ขวา", + "Maze.finalLevel": "ยินดีด้วย! คุณได้ไขปัญหาในระดับสุดท้ายสำเร็จแล้ว", + "Apps.linkAlert": "แบ่งปันบล็อคต่างๆของคุณด้วยลิงก์นี้:\n\n%1", + "Maze.capacity0": "คุณมีบล็อคเหลือ %0", + "Maze.capacity1": "คุณมีบล็อคเหลือ %1", + "Maze.capacity2": "คุณมีบล็อคเหลือ %2", + "Maze.repeatUntil": "ทำซ้ำจนกว่าจะ", + "Maze.moveForward": "เคลื่อน ไปข้างหน้า", + "Apps.codeTooltip": "ดูโค้ด JavaScript ที่ถูกสร้างขึ้น", + "Maze.pathRight": "ถ้า เส้นทาง ไปทางขวา", + "Maze.nextLevel": "ยินดีด้วย! คุณพร้อมที่จะไปต่อที่ระดับ %1 แล้วหรือยัง?", + "Maze.helpStack": "ต่อบล็อค 'เคลื่อน ไปข้างหน้า' สองอันเข้าด้วยกัน เพื่อช่วยให้ฉันถึงจุดหมายปลายทาง", + "Maze.helpRepeat": "คอมพิวเตอร์มีหน่วยความจำที่จำกัด -> ไปให้ถึงปลายทางนี้โดยใช้เพียงสองบล็อค -> ใช้ 'ทำซ้ำ' เพื่อเรียกใช้บล็อคมากกว่าหนึ่งครั้ง", + "Maze.helpRepeatMany": "ถึงจุดหมายปลายทางโดยใช้เพียงห้าบล็อค", + "Maze.helpIf": "เงื่อนไข 'ถ้า' จะทำอะไรบางอย่างก็ต่อเมื่อเงื่อนไขเป็นจริงเท่านั้น -> ลองหันซ้ายถ้ามีเส้นทางไปทางซ้าย", + "Maze.helpIfElse": "คำสั่ง 'ถ้า-นอกเหนือจากนี้' จะทำสิ่งหนึ่ง หรือ อื่นๆ", + "Apps.runProgram": "เรียกใช้โปรแกรม", + "Apps.resetProgram": " ตั้งค่าใหม่", + "Maze.pathLeft": "ถ้า เส้นทาง ไปทางซ้าย", + "Maze.turnLeft": "หัน ซ้าย", + "Apps.linkTooltip": "บันทึกและเชื่อมโยงไปยังบล็อค", + "Maze.ifelseTooltip": "ถ้ามีเส้นทางไปทางทิศทางที่ระบุ แล้วให้ทำการกระทำต่างๆภายในบล็อคแรก ไม่เช่นนั้น ให้ทำการกระทำต่างๆภายในบล็อคที่สอง", + "Maze.elseCode": "นอกเหนือจากนี้", + "Maze.moveForwardTooltip": "เคลื่อน Pegman ไปข้างหน้า หนึ่งช่อง" +} diff --git a/apps/json/tr.json b/apps/json/tr.json new file mode 100644 index 000000000..e5062f0f6 --- /dev/null +++ b/apps/json/tr.json @@ -0,0 +1,100 @@ +{ + "@metadata": { + "authors": [ + "Bahadir", + "Trockya" + ] + }, + "Apps.subtitle": "g\u00f6rsel bir programlama ortam\u0131", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Olu\u015fturulan JavaScript kodunu g\u00f6r\u00fcnt\u00fcle.", + "Apps.linkTooltip": "Bloklar\u0131 ve ba\u011flant\u0131 adresini kaydet.", + "Apps.runTooltip": "\u00c7al\u0131\u015fma alan\u0131nda bloklar taraf\u0131ndan tan\u0131mlanan program\u0131n\u0131 \u00e7al\u0131\u015ft\u0131r\u0131n.", + "Apps.runProgram": "Program\u0131 \u00c7al\u0131\u015ft\u0131r", + "Apps.resetProgram": "Tekrar", + "Apps.dialogOk": "TAMAM", + "Apps.dialogCancel": "\u0130ptal", + "Apps.catLogic": "Mant\u0131k", + "Apps.catLoops": "D\u00f6ng\u00fcler", + "Apps.catMath": "Matematik", + "Apps.catText": "Metin", + "Apps.catLists": "Listeler", + "Apps.catColour": "Renk", + "Apps.catVariables": "De\u011fi\u015fkenler", + "Apps.catProcedures": "Prosed\u00fcrler", + "Apps.httpRequestError": "\u0130stek ile ilgili bir problem var.", + "Apps.linkAlert": "Bloklar\u0131n\u0131 bu link ile payla\u015f:\n\n%1", + "Apps.hashError": "\u00dczg\u00fcn\u00fcz, '%1' herhangi bir blok kayd\u0131 ile uyu\u015fmuyor", + "Apps.xmlError": "Kaydedilen dosyan\u0131z y\u00fcklenemiyor\nBlockly'nin \u00f6nceki s\u00fcr\u00fcm\u00fc ile kaydedilmi\u015f olabilir mi?", + "Apps.listVariable": "liste", + "Apps.textVariable": "metin", + "Code.badXml": "XML ayr\u0131\u015ft\u0131rma hatas\u0131:\n%1\n\nDe\u011fi\u015fikliklerden vazge\u00e7mek i\u00e7in 'Tamam'\u0131, d\u00fczenlemeye devam etmek i\u00e7in '\u0130ptal' se\u00e7ene\u011fini se\u00e7iniz.", + "Code.badCode": "Program hatas\u0131:\n %1", + "Code.timeout": "Maksimum y\u00fcr\u00fctme yinelemeleri a\u015f\u0131ld\u0131.", + "Code.discard": "T\u00fcm %1 blok silinsin mi?", + "Code.title": "Kod", + "Code.blocks": "Bloklar", + "Code.trashTooltip": "B\u00fct\u00fcn bloklar\u0131 at.", + "Graph.title": "Grafik Hesap Makinesi", + "Maze.moveForward": "ileri git", + "Maze.turnLeft": "sola d\u00f6n", + "Maze.turnRight": "sa\u011fa d\u00f6n", + "Maze.doCode": "yap", + "Maze.elseCode": "yoksa", + "Maze.helpIfElse": "E\u011fer-de\u011filse ifadeleri ya bir \u015feyi ya da di\u011ferini yapar.", + "Maze.pathAhead": "e\u011fer \u00f6nde yol varsa", + "Maze.pathLeft": "e\u011fer solda yol varsa", + "Maze.pathRight": "e\u011fer sa\u011fda yol varsa", + "Maze.repeatUntil": "kadar tekrar et", + "Maze.moveForwardTooltip": "Pegman'i bir bo\u015fluk ileri g\u00f6t\u00fcr\u00fcr.", + "Maze.turnTooltip": "Pegman'i sola veya sa\u011fa d\u00f6nd\u00fcr\u00fcr.", + "Maze.ifTooltip": "E\u011fer belirtilen y\u00f6nde yol varsa, belirtilen hareketleri yap.", + "Maze.ifelseTooltip": "E\u011fer belirtilen y\u00f6nde yol varsa, belirtilen hareketleri ilk blo\u011funu yap, yoksa ikinci blo\u011fu yap.", + "Maze.whileTooltip": "Biti\u015f noktas\u0131na ula\u015fana kadar kapsanan hareketleri yap.", + "Maze.capacity0": "%0 adet blo\u011fun kald\u0131.", + "Maze.capacity1": "%1 adet blo\u011fun kald\u0131.", + "Maze.capacity2": "%2 adet blo\u011fun kald\u0131.", + "Maze.nextLevel": "Tebrikler! %1. seviyeye ge\u00e7meye haz\u0131r m\u0131s\u0131n?", + "Maze.finalLevel": "Tebrikler! Son seviyeyi de tamamlad\u0131n!", + "Maze.maze": "Labirent", + "Maze.runTooltip": "Oyuncuya bloklar ne diyorsa onu yapt\u0131r\u0131r.", + "Maze.resetTooltip": "Oyuncuyu labirentin ba\u015flang\u0131c\u0131na geri koy.", + "Maze.helpStack": "Bir ka\u00e7 'ileri git' blo\u011funu bir araya getirerek beni hedefe ula\u015ft\u0131r.", + "Maze.helpOneTopBlock": "Bu b\u00f6l\u00fcmde beyaz \u00e7al\u0131\u015fma alan\u0131ndaki b\u00fct\u00fcn bloklar\u0131 bir araya getirmelisin.", + "Maze.helpRun": "Ne olaca\u011f\u0131n\u0131 g\u00f6rmek i\u00e7in program\u0131n\u0131z\u0131 \u00e7al\u0131\u015ft\u0131r\u0131n.", + "Maze.helpReset": "Program\u0131n\u0131z labirenti \u00e7\u00f6zemedi. 'Tekrar' butonuna bas\u0131n ve yeniden deneyin.", + "Plane.setSeats": "koltuklar =", + "Plane.plane": "U\u00e7ak", + "Puzzle.country1": "Avustralya", + "Puzzle.country1Language": "\u0130ngilizce", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sidney", + "Puzzle.country1HelpUrl": "http://tr.wikipedia.org/wiki/Avustralya", + "Puzzle.country2": "Almanya", + "Puzzle.country2Language": "Almanca", + "Puzzle.country2City1": "Berlin", + "Puzzle.country2City2": "M\u00fcnih", + "Puzzle.country2HelpUrl": "http://tr.wikipedia.org/wiki/Almanya", + "Puzzle.country3": "\u00c7in", + "Puzzle.country3Language": "\u00c7ince", + "Puzzle.country3City1": "Pekin", + "Puzzle.country3City2": "\u015eangay", + "Puzzle.country3HelpUrl": "http://tr.wikipedia.org/wiki/\u00c7in_Halk_Cumhuriyeti", + "Puzzle.country4": "Brezilya", + "Puzzle.country4Language": "Portekizce", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "S\u00e3o Paulo", + "Puzzle.country4HelpUrl": "http://tr.wikipedia.org/wiki/Brezilya", + "Puzzle.flag": "bayrak:", + "Puzzle.language": "dil:", + "Puzzle.languageChoose": "se\u00e7im yap\u0131n...", + "Puzzle.cities": "\u015fehirler:", + "Puzzle.error0": "Muhte\u015fem!\n%1 blo\u011fun hepsi de do\u011fru.", + "Puzzle.error1": "Neredeyse oluyordu! Bir blok yanl\u0131\u015f.", + "Puzzle.error2": "%1 blok yanl\u0131\u015f.", + "Puzzle.tryAgain": "Vurgulanan blok yanl\u0131\u015f.\nDenemeye devam.", + "Puzzle.title": "Bulmaca", + "Puzzle.help": "Yard\u0131m", + "Puzzle.checkAnswers": "Yan\u0131tlar\u0131 Kontrol Et", + "Puzzle.helpText": "Her \u00fclkenin (ye\u015fil), bayra\u011f\u0131n\u0131 ekle, dilini se\u00e7 ve \u015fehirlerinden bir y\u0131\u011f\u0131n olu\u015ftur." +} \ No newline at end of file diff --git a/apps/json/tzm.json b/apps/json/tzm.json new file mode 100644 index 000000000..fdeb2d4ac --- /dev/null +++ b/apps/json/tzm.json @@ -0,0 +1,15 @@ +{ + "Puzzle.country3": "ⵛⵛⵉⵏⵡⴰ", + "Puzzle.country2": "ⵍⴰⵍⵎⴰⵏ", + "Puzzle.country1": "ⵓⵙⵜⵔⴰⵍⵢⴰ", + "Puzzle.language": "ⵜⵓⵜⵍⴰⵢⵜ:", + "Puzzle.flag": "ⴰⵛⵏⵢⴰⵍ", + "Puzzle.country3City2": "ⵛⴰⵏⴳⵀⴰⵢ", + "Puzzle.country3City1": "ⴱⵉⴽⵉⵏ", + "Puzzle.country1Language": "ⵜⵉⵏⴳⵍⵉⵣⵉⵜ", + "Puzzle.country3Language": "ⵜⴰⵛⵉⵏⵡⵉⵜ", + "Puzzle.country2City1": "ⴱⵉⵔⵍⵉⵏ", + "Puzzle.country2City2": "ⵎⵢⵓⵏⵉⵅ", + "Puzzle.country1City2": "ⵙⵉⴷⵏⵉ", + "Puzzle.country2Language": "ⵍⴰⵍⵎⴰⵏ" +} diff --git a/apps/json/uk.json b/apps/json/uk.json new file mode 100644 index 000000000..7304395aa --- /dev/null +++ b/apps/json/uk.json @@ -0,0 +1,150 @@ +{ + "@metadata": { + "authors": [ + "Andriykopanytsia" + ] + }, + "Apps.subtitle": "\u0432\u0456\u0437\u0443\u0430\u043b\u044c\u043d\u0435 \u0441\u0435\u0440\u0435\u0434\u043e\u0432\u0438\u0449\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0443\u0432\u0430\u043d\u043d\u044f", + "Apps.blocklyMessage": "Blockly (\u0411\u043b\u043e\u043a\u043b\u0456)", + "Apps.codeTooltip": "\u0414\u0438\u0432. \u0437\u0433\u0435\u043d\u0435\u0440\u043e\u0432\u0430\u043d\u0438\u0439 \u043a\u043e\u0434 JavaScript.", + "Apps.linkTooltip": "\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u0456 \u043f\u043e\u0432'\u044f\u0437\u0430\u0442\u0438 \u0437 \u0431\u043b\u043e\u043a\u0430\u043c\u0438.", + "Apps.runTooltip": "\u0417\u0430\u043f\u0443\u0441\u0442\u0456\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0443, \u0432\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u0443 \u0431\u043b\u043e\u043a\u0430\u043c\u0438 \u0443 \u0440\u043e\u0431\u043e\u0447\u0456\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0456.", + "Apps.runProgram": "\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0443", + "Apps.resetProgram": "\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438", + "Apps.dialogOk": "OK", + "Apps.dialogCancel": "\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438", + "Apps.catLogic": "\u041b\u043e\u0433\u0456\u043a\u0430", + "Apps.catLoops": "\u041f\u0435\u0442\u043b\u0456", + "Apps.catMath": "\u041c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0430", + "Apps.catText": "\u0422\u0435\u043a\u0441\u0442", + "Apps.catLists": "\u0421\u043f\u0438\u0441\u043a\u0438", + "Apps.catColour": "\u041a\u043e\u043b\u0456\u0440", + "Apps.catVariables": "\u0417\u043c\u0456\u043d\u043d\u0456", + "Apps.catProcedures": "\u041f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0438", + "Apps.httpRequestError": "\u0412\u0438\u043d\u0438\u043a\u043b\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0456\u0437 \u0437\u0430\u043f\u0438\u0442\u043e\u043c.", + "Apps.linkAlert": "\u041f\u043e\u0434\u0456\u043b\u0438\u0442\u0438\u0441\u044f \u0432\u0430\u0448\u0438\u043c \u0431\u043b\u043e\u043a\u0430\u043c\u0438 \u0447\u0435\u0440\u0435\u0437 \u043f\u043e\u0441\u0438\u043b\u0430\u043d\u043d\u044f:\n\n%1", + "Apps.hashError": "\u041d\u0430 \u0436\u0430\u043b\u044c, \"%1\" \u043d\u0435 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u0430\u0454 \u0436\u043e\u0434\u043d\u0456\u0439 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0456\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0456.", + "Apps.xmlError": "\u041d\u0435 \u0432\u0434\u0430\u043b\u043e\u0441\u044f \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0432\u0430\u0448 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u0438\u0439 \u0444\u0430\u0439\u043b. \u041c\u043e\u0436\u043b\u0438\u0432\u043e, \u0432\u0456\u043d \u0431\u0443\u0432 \u0441\u0442\u0432\u043e\u0440\u0435\u043d\u0438\u0439 \u0437 \u0456\u043d\u0448\u043e\u0457 \u0432\u0435\u0440\u0441\u0456\u0457 Blockly?", + "Apps.listVariable": "\u0441\u043f\u0438\u0441\u043e\u043a", + "Apps.textVariable": "\u0442\u0435\u043a\u0441\u0442", + "Code.badXml": "\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u043d\u043e\u0433\u043e \u0430\u043d\u0430\u043b\u0456\u0437\u0443 XML:\n%1\n\n\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \"\u0413\u0430\u0440\u0430\u0437\u0434\", \u0449\u043e\u0431 \u0432\u0456\u0434\u043c\u043e\u0432\u0438\u0442\u0438\u0441\u044f \u0432\u0456\u0434 \u0437\u043c\u0456\u043d \u0430\u0431\u043e '\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438' \u0434\u043b\u044f \u043f\u043e\u0434\u0430\u043b\u044c\u0448\u043e\u0433\u043e \u0440\u0435\u0434\u0430\u0433\u0443\u0432\u0430\u043d\u043d\u044f XML.", + "Code.badCode": "\u041f\u043e\u043c\u0438\u043b\u043a\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0438:\n%1", + "Code.timeout": "\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0435 \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u043d\u044f \u0456\u0442\u0435\u0440\u0430\u0446\u0456\u0439 \u043f\u0435\u0440\u0435\u0432\u0438\u0449\u0435\u043d\u043e.", + "Code.discard": "\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0432\u0441\u0456 \u0431\u043b\u043e\u043a\u0438 %1?", + "Code.title": "\u041a\u043e\u0434", + "Code.blocks": "\u0411\u043b\u043e\u043a\u0438", + "Code.trashTooltip": "\u0412\u0456\u0434\u043a\u0438\u043d\u0443\u0442\u0438 \u0432\u0441\u0456 \u0431\u043b\u043e\u043a\u0438.", + "Graph.title": "\u0413\u0440\u0430\u0444\u0456\u0447\u043d\u0438\u0439 \u043a\u0430\u043b\u044c\u043a\u0443\u043b\u044f\u0442\u043e\u0440", + "Maze.moveForward": "\u0440\u0443\u0445 \u0432\u043f\u0435\u0440\u0435\u0434", + "Maze.turnLeft": "\u043f\u043e\u0432\u043e\u0440\u043e\u0442 \u0432\u043b\u0456\u0432\u043e", + "Maze.turnRight": "\u043f\u043e\u0432\u043e\u0440\u043e\u0442 \u0432\u043f\u0440\u0430\u0432\u043e", + "Maze.doCode": "\u0437\u0440\u043e\u0431\u0438\u0442\u0438", + "Maze.elseCode": "\u0456\u043d\u0448\u0435", + "Maze.helpIfElse": "\u0411\u043b\u043e\u043a\u0438 \u201e\u044f\u043a\u0449\u043e-\u0456\u043d\u0430\u043a\u0448\u0435\u201c \u0431\u0443\u0434\u0443\u0442\u044c \u0440\u043e\u0431\u0438\u0442\u0438 \u043e\u0434\u043d\u0435 \u0430\u0431\u043e \u0456\u043d\u0448\u0435.", + "Maze.pathAhead": "\u044f\u043a\u0449\u043e \u0448\u043b\u044f\u0445 \u043f\u043e\u043f\u0435\u0440\u0435\u0434\u0443", + "Maze.pathLeft": "\u044f\u043a\u0449\u043e \u0448\u043b\u044f\u0445 \u043d\u0430\u043b\u0456\u0432\u043e", + "Maze.pathRight": "\u044f\u043a\u0449\u043e \u0448\u043b\u044f\u0445 \u043f\u0440\u0430\u0432\u043e\u0440\u0443\u0447", + "Maze.repeatUntil": "\u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0438, \u043f\u043e\u043a\u0438", + "Maze.moveForwardTooltip": "\u041f\u0435\u0440\u0435\u043c\u0456\u0449\u0443\u0454 \u0433\u0440\u0430\u0432\u0446\u044f \u0432\u043f\u0435\u0440\u0435\u0434 \u043d\u0430 \u043e\u0434\u043d\u0435 \u043c\u0456\u0441\u0446\u0435.", + "Maze.turnTooltip": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0433\u0440\u0430\u0432\u0446\u044f \u043b\u0456\u0432\u043e\u0440\u0443\u0447 \u0430\u0431\u043e \u043f\u0440\u0430\u0432\u043e\u0440\u0443\u0447 \u043d\u0430 90 \u0433\u0440\u0430\u0434\u0443\u0441\u0456\u0432.", + "Maze.ifTooltip": "\u042f\u043a\u0449\u043e \u0456\u0441\u043d\u0443\u0454 \u0448\u043b\u044f\u0445 \u0443 \u0432\u043a\u0430\u0437\u0430\u043d\u043e\u043c\u0443 \u043d\u0430\u043f\u0440\u044f\u043c\u043a\u0443, \u043f\u043e\u0442\u0456\u043c \u0432\u0438\u043a\u043e\u043d\u0430\u0442\u0438 \u043f\u0435\u0432\u043d\u0456 \u0434\u0456\u0457.", + "Maze.ifelseTooltip": "\u042f\u043a\u0449\u043e \u0456\u0441\u043d\u0443\u0454 \u0448\u043b\u044f\u0445 \u0443 \u0432\u043a\u0430\u0437\u0430\u043d\u043e\u043c\u0443 \u043d\u0430\u043f\u0440\u044f\u043c\u043a\u0443, \u043f\u043e\u0442\u0456\u043c \u0437\u0440\u043e\u0431\u0456\u0442\u044c \u043f\u0435\u0440\u0448\u0438\u0439 \u0431\u043b\u043e\u043a \u0437\u0430\u0445\u043e\u0434\u0456\u0432. \u0412 \u0456\u043d\u0448\u043e\u043c\u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443, \u0437\u0440\u043e\u0431\u0456\u0442\u044c \u0434\u0440\u0443\u0433\u0438\u0439 \u0431\u043b\u043e\u043a \u0437\u0430\u0445\u043e\u0434\u0456\u0432.", + "Maze.whileTooltip": "\u041f\u043e\u0432\u0442\u043e\u0440\u044e\u0432\u0430\u0442\u0438 \u0437\u0430\u043a\u0440\u0438\u0442\u0456 \u0434\u0456\u0457, \u043f\u043e\u043a\u0438 \u043a\u0456\u043d\u0446\u0435\u0432\u0430 \u0442\u043e\u0447\u043a\u0430 \u043d\u0435 \u0434\u043e\u0441\u044f\u0433\u043d\u0435\u0442\u044c\u0441\u044f.", + "Maze.capacity0": "\u0423 \u0432\u0430\u0441 \u043b\u0438\u0448\u0438\u043b\u043e\u0441\u044f %0 \u0431\u043b\u043e\u043a\u0456\u0432.", + "Maze.capacity1": "\u0423 \u0432\u0430\u0441 \u043b\u0438\u0448\u0438\u0432\u0441\u044f %1 \u0431\u043b\u043e\u043a.", + "Maze.capacity2": "\u0423 \u0432\u0430\u0441 \u043b\u0438\u0448\u0438\u043b\u043e\u0441\u044f %2 \u0431\u043b\u043e\u043a\u0438(\u0456\u0432).", + "Maze.nextLevel": "\u0412\u0456\u0442\u0430\u0454\u043c\u043e! \u0412\u0438 \u0433\u043e\u0442\u043e\u0432\u0456 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u0438 \u0434\u043e \u0440\u0456\u0432\u043d\u044f %1?", + "Maze.finalLevel": "\u0412\u0456\u0442\u0430\u0454\u043c\u043e! \u0412\u0438 \u0440\u043e\u0437\u0432'\u044f\u0437\u0430\u043b\u0438 \u0444\u0456\u043d\u0430\u043b\u044c\u043d\u0438\u0439 \u0440\u0456\u0432\u0435\u043d\u044c.", + "Maze.maze": "\u041b\u0430\u0431\u0456\u0440\u0438\u043d\u0442", + "Maze.runTooltip": "\u0413\u0440\u0430\u0432\u0435\u0446\u044c \u0440\u043e\u0431\u0438\u0442\u044c \u0443\u0441\u0435, \u0449\u043e \u043a\u0430\u0436\u0443\u0442\u044c \u0431\u043b\u043e\u043a\u0438.", + "Maze.resetTooltip": "\u041f\u043e\u043a\u043b\u0430\u0434\u0456\u0442\u044c \u0433\u0440\u0430\u0432\u0446\u044f \u043d\u0430\u0437\u0430\u0434 \u0432 \u043f\u043e\u0447\u0430\u0442\u043e\u043a \u043b\u0430\u0431\u0456\u0440\u0438\u043d\u0442\u0443.", + "Maze.helpStack": "\u0421\u043a\u043b\u0430\u0434\u0430\u0439\u0442\u0435 \u043a\u0456\u043b\u044c\u043a\u0430 \u0431\u043b\u043e\u043a\u0456\u0432 \u0440\u0443\u0445\u043e\u043c \u0432\u043f\u0435\u0440\u0435\u0434 \u0440\u0430\u0437\u043e\u043c, \u0449\u043e\u0431 \u0434\u043e\u043f\u043e\u043c\u043e\u0433\u0442\u0438 \u043c\u0435\u043d\u0456 \u0434\u043e\u0441\u044f\u0433\u0442\u0438 \u043c\u0435\u0442\u0438.", + "Maze.helpOneTopBlock": "\u041d\u0430 \u0446\u044c\u043e\u043c\u0443 \u0440\u0456\u0432\u043d\u0456, \u0432\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u043e \u0441\u043a\u043b\u0430\u0441\u0442\u0438 \u0440\u0430\u0437\u043e\u043c \u0432\u0441\u0456 \u0431\u043b\u043e\u043a\u0438 \u0432 \u0431\u0456\u043b\u0456\u0439 \u0440\u043e\u0431\u043e\u0447\u0456\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0456.", + "Maze.helpRun": "\u0417\u0430\u043f\u0443\u0441\u0442\u0456\u0442\u044c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0443, \u0449\u043e\u0431 \u043f\u043e\u0434\u0438\u0432\u0438\u0442\u0438\u0441\u044f, \u0449\u043e \u0432\u0456\u0434\u0431\u0443\u0432\u0430\u0454\u0442\u044c\u0441\u044f.", + "Maze.helpReset": "\u0412\u0430\u0448\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430 \u043d\u0435 \u0440\u043e\u0437\u0432'\u044f\u0437\u0430\u043b\u0430 \u043b\u0430\u0431\u0456\u0440\u0438\u043d\u0442. \u041d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0443 '\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438' \u0456 \u0441\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0437\u043d\u043e\u0432\u0443.", + "Maze.helpRepeat": "\u041f\u0430\u043c'\u044f\u0442\u044c \u043a\u043e\u043c\u043f'\u044e\u0442\u0435\u0440\u0456\u0432 \u043e\u0431\u043c\u0435\u0436\u0435\u043d\u0430. \u041f\u0440\u043e\u0439\u0434\u0456\u0442\u044c \u0434\u043e \u043a\u0456\u043d\u0446\u044f \u0446\u044c\u043e\u0433\u043e \u0448\u043b\u044f\u0445\u0443, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u044e\u0447\u0438 \u0442\u0456\u043b\u044c\u043a\u0438 \u0434\u0432\u0430 \u0431\u043b\u043e\u043a\u0438. \u0414\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0443 \u0431\u043b\u043e\u043a\u0443 \u0431\u0456\u043b\u044c\u0448\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0443, \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0439\u0442\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 '\u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0438'.", + "Maze.helpCapacity": "\u0412\u0438 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u0435 \u0432\u0441\u0456 \u0431\u043b\u043e\u043a\u0438 \u043d\u0430 \u0446\u044c\u043e\u043c\u0443 \u0440\u0456\u0432\u043d\u0456. \u0429\u043e\u0431 \u0441\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u043d\u043e\u0432\u0438\u0439 \u0431\u043b\u043e\u043a, \u0441\u043f\u043e\u0447\u0430\u0442\u043a\u0443 \u043d\u0435\u043e\u0431\u0445\u0456\u0434\u043d\u043e \u0432\u0438\u0434\u0430\u043b\u0438\u0442\u0438 \u0456\u0441\u043d\u0443\u044e\u0447\u0438\u0439 \u0431\u043b\u043e\u043a.", + "Maze.helpRepeatMany": "\u0412\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u0431\u0456\u043b\u044c\u0448\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0431\u043b\u043e\u043a\u0443 \u0443\u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0456 \u0431\u043b\u043e\u043a\u0443 '\u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0438'.", + "Maze.helpSkins": "\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0432\u0430\u0448\u043e\u0433\u043e \u0443\u043b\u044e\u0431\u043b\u0435\u043d\u043e\u0433\u043e \u0433\u0440\u0430\u0432\u0446\u044f \u0443 \u0446\u044c\u043e\u043c\u0443 \u043c\u0435\u043d\u044e.", + "Maze.helpIf": "\u0411\u043b\u043e\u043a \u201e\u044f\u043a\u0449\u043e\u201c \u0431\u0443\u0434\u0435 \u0440\u043e\u0431\u0438\u0442\u0438 \u0449\u043e\u0441\u044c, \u043b\u0438\u0448\u0435 \u044f\u043a\u0449\u043e \u0446\u044f \u0443\u043c\u043e\u0432\u0430 \u0454 \u0456\u0441\u0442\u0438\u043d\u043d\u043e\u044e. \u0421\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u043f\u043e\u0432\u043e\u0440\u043e\u0442 \u0432\u043b\u0456\u0432\u043e, \u044f\u043a\u0449\u043e \u0456\u0441\u043d\u0443\u0454 \u0448\u043b\u044f\u0445 \u043b\u0456\u0432\u043e\u0440\u0443\u0447.", + "Maze.helpMenu": "\u041d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u043d\u0430 %1 \u0443 \u0431\u043b\u043e\u043a \"\u042f\u043a\u0449\u043e\" \u0437\u043c\u0456\u043d\u0438\u0442\u0438 \u0441\u0432\u0456\u0439 \u0441\u0442\u0430\u043d.", + "Maze.helpWallFollow": "\u0412\u0438 \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u0438\u0440\u0456\u0448\u0438\u0442\u0438 \u0446\u0435\u0439 \u0441\u043a\u043b\u0430\u0434\u043d\u0438\u0439 \u043b\u0430\u0431\u0456\u0440\u0438\u043d\u0442? \u0421\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0441\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u0442\u0438\u0441\u044f \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u043e\u044e \u043b\u0456\u0432\u043e\u0441\u0442\u043e\u0440\u043e\u043d\u043d\u044c\u043e\u044e \u0441\u0442\u0456\u043d\u043e\u044e. \u0422\u0456\u043b\u044c\u043a\u0438 \u0434\u043b\u044f \u0434\u043e\u0441\u0432\u0456\u0434\u0447\u0435\u043d\u0438\u0445 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0456\u0441\u0442\u0456\u0432!", + "Plane.rows": "\u0420\u044f\u0434\u043a\u0438: %1", + "Plane.getRows": "\u0440\u044f\u0434\u043a\u0438 (%1)", + "Plane.rows1": "\u0440\u044f\u0434\u0456\u0432 1-\u0433\u043e \u043a\u043b\u0430\u0441\u0443: %1", + "Plane.getRows1": "\u0440\u044f\u0434\u0456\u0432 1-\u0433\u043e \u043a\u043b\u0430\u0441\u0443 (%1)", + "Plane.rows2": "\u0440\u044f\u0434\u0456\u0432 2-\u0433\u043e \u043a\u043b\u0430\u0441\u0443: %1", + "Plane.getRows2": "\u0440\u044f\u0434\u0456\u0432 2-\u0433\u043e \u043a\u043b\u0430\u0441\u0443 (%1)", + "Plane.seats": "\u041c\u0456\u0441\u0446\u044c: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "\u043c\u0456\u0441\u0446\u044c=", + "Plane.plane": "\u041b\u0456\u0442\u0430\u043a", + "Plane.description1": "\u041b\u0456\u0442\u0430\u043a \u043c\u0430\u0454 \u043a\u0456\u043b\u044c\u043a\u0430 \u0440\u044f\u0434\u0456\u0432 \u043f\u0430\u0441\u0430\u0436\u0438\u0440\u0441\u044c\u043a\u0438\u0445 \u0441\u0438\u0434\u0456\u043d\u044c. \u041a\u043e\u0436\u0435\u043d \u0440\u044f\u0434 \u043c\u0456\u0441\u0442\u0438\u0442\u044c \u0447\u043e\u0442\u0438\u0440\u0438 \u043c\u0456\u0441\u0446\u044f.", + "Plane.description2": "\u041b\u0456\u0442\u0430\u043a \u043c\u0430\u0454 \u0434\u0432\u0430 \u043c\u0456\u0441\u0446\u044f \u0432 \u043a\u0430\u0431\u0456\u043d\u0456 \u0435\u043a\u0456\u043f\u0430\u0436\u0443 (\u043f\u0456\u043b\u043e\u0442 \u0456 \u0434\u0440\u0443\u0433\u0438\u0439 \u043f\u0456\u043b\u043e\u0442), \u0456 \u043a\u0456\u043b\u044c\u043a\u0430 \u0440\u044f\u0434\u0456\u0432 \u043f\u0430\u0441\u0430\u0436\u0438\u0440\u0441\u044c\u043a\u0438\u0445 \u0441\u0438\u0434\u0456\u043d\u044c. \u041a\u043e\u0436\u0435\u043d \u0440\u044f\u0434\u043e\u043a \u043c\u0456\u0441\u0442\u0438\u0442\u044c \u0447\u043e\u0442\u0438\u0440\u0438 \u043c\u0456\u0441\u0446\u044f.", + "Plane.description3": "\u041b\u0456\u0442\u0430\u043a \u043c\u0430\u0454 \u0434\u0432\u0430 \u043c\u0456\u0441\u0446\u044f \u0432 \u043a\u0430\u0431\u0456\u043d\u0456 \u0435\u043a\u0456\u043f\u0430\u0436\u0443 (\u043f\u0456\u043b\u043e\u0442 \u0456 \u0434\u0440\u0443\u0433\u0438\u0439 \u043f\u0456\u043b\u043e\u0442), \u0456 \u043a\u0456\u043b\u044c\u043a\u0430 \u0440\u044f\u0434\u0456\u0432 1-\u0433\u043e \u043a\u043b\u0430\u0441\u0443 2-\u0433\u043e \u043a\u043b\u0430\u0441\u0443 \u043f\u0430\u0441\u0430\u0436\u0438\u0440\u0441\u044c\u043a\u0438\u0445 \u043c\u0456\u0441\u0446\u044c. \u041a\u043e\u0436\u043d\u0438\u0439 \u0440\u044f\u0434 1-\u0433\u043e \u043a\u043b\u0430\u0441\u0443 \u043c\u0456\u0441\u0442\u0438\u0442\u044c \u0447\u043e\u0442\u0438\u0440\u0438 \u043c\u0456\u0441\u0446\u044f. \u041a\u043e\u0436\u0435\u043d \u0440\u044f\u0434 2-\u0433\u043e \u043a\u043b\u0430\u0441\u0443 \u043c\u0456\u0441\u0442\u0438\u0442\u044c \u043f'\u044f\u0442\u044c \u043c\u0456\u0441\u0446\u044c.", + "Plane.instructions": "\u041f\u043e\u0431\u0443\u0434\u0443\u0432\u0430\u0442\u0438 \u0444\u043e\u0440\u043c\u0443\u043b\u0443 (\u043d\u0438\u0436\u0447\u0435), \u044f\u043a\u0430 \u043e\u0431\u0447\u0438\u0441\u043b\u044e\u0454 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043c\u0456\u0441\u0446\u044c \u043d\u0430 \u043b\u0456\u0442\u0430\u043a\u0443 \u043f\u0440\u0438 \u0437\u043c\u0456\u043d\u0456 \u0440\u044f\u0434\u043a\u0456\u0432 (\u0434\u0438\u0432. \u0432\u0438\u0449\u0435).", + "Puzzle.country1": "\u0410\u0432\u0441\u0442\u0440\u0430\u043b\u0456\u044f", + "Puzzle.country1Language": "\u0410\u043d\u0433\u043b\u0456\u0439\u0441\u044c\u043a\u0430", + "Puzzle.country1City1": "\u041c\u0435\u043b\u044c\u0431\u0443\u0440\u043d", + "Puzzle.country1City2": "\u0421\u0456\u0434\u043d\u0435\u0439", + "Puzzle.country1HelpUrl": "http://uk.wikipedia.org/wiki/\u0410\u0432\u0441\u0442\u0440\u0430\u043b\u0456\u044f", + "Puzzle.country2": "\u041d\u0456\u043c\u0435\u0447\u0447\u0438\u043d\u0430", + "Puzzle.country2Language": "\u041d\u0456\u043c\u0435\u0446\u044c\u043a\u0430", + "Puzzle.country2City1": "\u0411\u0435\u0440\u043b\u0456\u043d", + "Puzzle.country2City2": "\u041c\u044e\u043d\u0445\u0435\u043d", + "Puzzle.country2HelpUrl": "http://uk.wikipedia.org/wiki/\u041d\u0456\u043c\u0435\u0447\u0447\u0438\u043d\u0430", + "Puzzle.country3": "\u041a\u0438\u0442\u0430\u0439", + "Puzzle.country3Language": "\u041a\u0438\u0442\u0430\u0439\u0441\u044c\u043a\u0430", + "Puzzle.country3City1": "\u041f\u0435\u043a\u0456\u043d", + "Puzzle.country3City2": "\u0428\u0430\u043d\u0445\u0430\u0439", + "Puzzle.country3HelpUrl": "http://uk.wikipedia.org/wiki/\u041a\u0438\u0442\u0430\u0439\u0441\u044c\u043a\u0430_\u041d\u0430\u0440\u043e\u0434\u043d\u0430_\u0420\u0435\u0441\u043f\u0443\u0431\u043b\u0456\u043a\u0430", + "Puzzle.country4": "\u0411\u0440\u0430\u0437\u0438\u043b\u0456\u044f", + "Puzzle.country4Language": "\u041f\u043e\u0440\u0442\u0443\u0433\u0430\u043b\u044c\u0441\u044c\u043a\u0430", + "Puzzle.country4City1": "\u0420\u0456\u043e-\u0434\u0435-\u0416\u0430\u043d\u0435\u0439\u0440\u043e", + "Puzzle.country4City2": "\u0421\u0430\u043d-\u041f\u0430\u0443\u043b\u0443", + "Puzzle.country4HelpUrl": "http://uk.wikipedia.org/wiki/\u0411\u0440\u0430\u0437\u0438\u043b\u0456\u044f", + "Puzzle.flag": "\u043f\u0440\u0430\u043f\u043e\u0440:", + "Puzzle.language": "\u043c\u043e\u0432\u0430:", + "Puzzle.languageChoose": "\u0432\u0438\u0431\u0435\u0440\u0456\u0442\u044c...", + "Puzzle.cities": "\u043c\u0456\u0441\u0442\u0430:", + "Puzzle.error0": "\u0412\u0456\u0434\u043c\u0456\u043d\u043d\u043e!\n\n\u0412\u0441\u0456 \u0431\u043b\u043e\u043a\u0438 (%1) \u0440\u043e\u0437\u043c\u0456\u0449\u0435\u043d\u0456 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e!", + "Puzzle.error1": "\u041c\u0430\u0439\u0436\u0435! \u041e\u0434\u0438\u043d \u0431\u043b\u043e\u043a \u0440\u043e\u0437\u043c\u0456\u0449\u0435\u043d\u0438\u0439 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e.", + "Puzzle.error2": "\u0414\u0435\u043a\u0456\u043b\u044c\u043a\u0430 \u0431\u043b\u043e\u043a\u0456\u0432 (%1) \u0440\u043e\u0437\u043c\u0456\u0449\u0435\u043d\u043e \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e.", + "Puzzle.tryAgain": "\u0412\u0438\u0434\u0456\u043b\u0435\u043d\u0438\u0439 \u0431\u043b\u043e\u043a \u0440\u043e\u0437\u043c\u0456\u0449\u0435\u043d\u0438\u0439 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e.\n\u0421\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0449\u0435.", + "Puzzle.title": "\u0413\u043e\u043b\u043e\u0432\u043e\u043b\u043e\u043c\u043a\u0430", + "Puzzle.help": "\u0414\u043e\u0432\u0456\u0434\u043a\u0430", + "Puzzle.checkAnswers": "\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0438\u0442\u0438 \u0432\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u0456", + "Puzzle.helpText": "\u0414\u043e \u043a\u043e\u0436\u043d\u043e\u0457 \u043a\u0440\u0430\u0457\u043d\u0438 (\u0437\u0435\u043b\u0435\u043d\u0438\u0439 \u043a\u043e\u043b\u0456\u0440) \u043f\u0440\u0438\u043a\u0440\u0456\u043f\u0456\u0442\u044c \u043f\u0440\u0430\u043f\u043e\u0440, \u0432\u0438\u0431\u0435\u0440\u0456\u0442\u044c \u0434\u0435\u0440\u0436\u0430\u0432\u043d\u0443 \u043c\u043e\u0432\u0443 \u0442\u0430 \u0432\u043a\u0430\u0436\u0456\u0442\u044c \u043c\u0456\u0441\u0442\u0430, \u0440\u043e\u0437\u0442\u0430\u0448\u043e\u0432\u0430\u043d\u0456 \u0432 \u0446\u0456\u0439 \u043a\u0440\u0430\u0457\u043d\u0456.", + "Turtle.moveTooltip": "\u041f\u0435\u0440\u0435\u043c\u0456\u0449\u0443\u0454 \u0447\u0435\u0440\u0435\u043f\u0430\u0445\u0443 \u0432\u043f\u0435\u0440\u0435\u0434 \u0430\u0431\u043e \u043d\u0430\u0437\u0430\u0434 \u043d\u0430 \u0437\u0430\u0434\u0430\u043d\u0443 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c.", + "Turtle.moveForward": "\u0440\u0443\u0445\u0430\u0442\u0438\u0441\u044f \u0432\u043f\u0435\u0440\u0435\u0434 \u043d\u0430", + "Turtle.moveBackward": "\u0440\u0443\u0445\u0430\u0442\u0438\u0441\u044f \u043d\u0430\u0437\u0430\u0434 \u043d\u0430", + "Turtle.turnTooltip": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0447\u0435\u0440\u0435\u043f\u0430\u0445\u0443 \u0432\u043b\u0456\u0432\u043e \u0430\u0431\u043e \u0432\u043f\u0440\u0430\u0432\u043e \u043d\u0430 \u0432\u043a\u0430\u0437\u0430\u043d\u0443 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0433\u0440\u0430\u0434\u0443\u0441\u0456\u0432.", + "Turtle.turnRight": "\u043f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438 \u0432\u043f\u0440\u0430\u0432\u043e \u043d\u0430", + "Turtle.turnLeft": "\u043f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438 \u043b\u0456\u0432\u043e\u0440\u0443\u0447 \u043d\u0430", + "Turtle.widthTooltip": "\u0417\u043c\u0456\u043d\u044e\u0454 \u0448\u0438\u0440\u0438\u043d\u0443 \u043f\u0435\u0440\u0430.", + "Turtle.setWidth": "\u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u0448\u0438\u0440\u0438\u043d\u0443", + "Turtle.colourTooltip": "\u0417\u043c\u0456\u043d\u044e\u0454 \u043a\u043e\u043b\u0456\u0440 \u043f\u0435\u0440\u0430.", + "Turtle.setColour": "\u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u043a\u043e\u043b\u0456\u0440", + "Turtle.penTooltip": "\u041f\u0456\u0434\u043d\u0456\u043c\u0430\u0454 \u0430\u0431\u043e \u043e\u043f\u0443\u0441\u043a\u0430\u0454 \u043f\u0435\u0440\u0430, \u0449\u043e\u0431 \u0437\u0443\u043f\u0438\u043d\u0438\u0442\u0438 \u0430\u0431\u043e \u043f\u043e\u0447\u0430\u0442\u0438 \u043c\u0430\u043b\u044e\u0432\u0430\u0442\u0438.", + "Turtle.penUp": "\u0440\u0443\u043a\u0443 \u0432\u0433\u043e\u0440\u0443", + "Turtle.penDown": "\u0440\u0443\u043a\u0443 \u0432\u043d\u0438\u0437", + "Turtle.turtleVisibilityTooltip": "\u0420\u043e\u0431\u0438\u0442\u044c \u0447\u0435\u0440\u0435\u043f\u0430\u0445\u0443 (\u043a\u043e\u043b\u043e \u0456 \u0441\u0442\u0440\u0456\u043b\u043a\u0443) \u0432\u0438\u0434\u0438\u043c\u0438\u043c \u0430\u0431\u043e \u043d\u0435\u0432\u0438\u0434\u0438\u043c\u0438\u043c.", + "Turtle.hideTurtle": "\u043f\u0440\u0438\u0445\u043e\u0432\u0430\u0442\u0438 \u0447\u0435\u0440\u0435\u043f\u0430\u0445\u0443", + "Turtle.showTurtle": "\u043f\u043e\u043a\u0430\u0437\u0430\u0442\u0438 \u0447\u0435\u0440\u0435\u043f\u0430\u0445\u0443", + "Turtle.printHelpUrl": "http://uk.wikipedia.org/wiki/\u0414\u0440\u0443\u043a\u0430\u0440\u0441\u0442\u0432\u043e", + "Turtle.printTooltip": "\u041c\u0430\u043b\u044e\u0454 \u0442\u0435\u043a\u0441\u0442\u0443 \u0432 \u043d\u0430\u043f\u0440\u044f\u043c\u043a\u0443 \u0440\u0443\u0445\u0443 \u0447\u0435\u0440\u0435\u043f\u0430\u0445\u0438 \u043d\u0430 \u0439\u043e\u0433\u043e \u043c\u0456\u0441\u0446\u0435 \u0440\u043e\u0437\u0442\u0430\u0448\u0443\u0432\u0430\u043d\u043d\u044f.", + "Turtle.print": "\u0434\u0440\u0443\u043a", + "Turtle.fontHelpUrl": "http://uk.wikipedia.org/wiki/\u0428\u0440\u0438\u0444\u0442", + "Turtle.fontTooltip": "\u0412\u0438\u0437\u043d\u0430\u0447\u0430\u0454 \u0448\u0440\u0438\u0444\u0442, \u0449\u043e \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0454\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0434\u0440\u0443\u043a\u0443 \u0431\u043b\u043e\u043a\u0443.", + "Turtle.font": "\u0448\u0440\u0438\u0444\u0442", + "Turtle.fontSize": "\u0440\u043e\u0437\u043c\u0456\u0440 \u0448\u0440\u0438\u0444\u0442\u0443", + "Turtle.fontNormal": "\u0437\u0432\u0438\u0447\u0430\u0439\u043d\u0438\u0439", + "Turtle.fontBold": "\u0436\u0438\u0440\u043d\u0438\u0439", + "Turtle.fontItalic": "\u043a\u0443\u0440\u0441\u0438\u0432", + "Turtle.unloadWarning": "\u0412\u0438\u0439\u0448\u043e\u0432\u0448\u0438 \u0437 \u0446\u0456\u0454\u0457 \u0441\u0442\u043e\u0440\u0456\u043d\u043a\u0438, \u0432\u0438 \u0432\u0442\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u0430\u0448\u0443 \u0440\u043e\u0431\u043e\u0442\u0443.", + "Turtle.title": "\u0413\u0440\u0430\u0444\u0456\u043a\u0430 \u0427\u0435\u0440\u0435\u043f\u0430\u0445\u0438", + "Turtle.runTooltip": "\u0427\u0435\u0440\u0435\u043f\u0430\u0445\u0430 \u0440\u043e\u0431\u0438\u0442\u0438 \u0442\u0435, \u0449\u043e \u0433\u043e\u0432\u043e\u0440\u044f\u0442\u044c \u0431\u043b\u043e\u043a\u0438.", + "Turtle.captureTooltip": "\u0417\u0431\u0435\u0440\u0435\u0433\u0442\u0438 \u043c\u0430\u043b\u044e\u043d\u043e\u043a.", + "Turtle.imgFilename": "drawing.png", + "Turtle.catTurtle": "\u0427\u0435\u0440\u0435\u043f\u0430\u0445\u0430" +} \ No newline at end of file diff --git a/apps/json/vi.json b/apps/json/vi.json new file mode 100644 index 000000000..bcdab4dc9 --- /dev/null +++ b/apps/json/vi.json @@ -0,0 +1,150 @@ +{ + "@metadata": { + "authors": [ + "Qneutron" + ] + }, + "Apps.subtitle": "m\u00f4i tr\u01b0\u1eddng l\u1eadp tr\u00ecnh tr\u1ef1c quan", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "Xem code \u0111\u00e3 t\u1ea1o b\u1eb1ng JavaScript.", + "Apps.linkTooltip": "L\u01b0u v\u00e0 l\u1ea5y \u0111\u1ecba ch\u1ec9 li\u00ean k\u1ebft.", + "Apps.runTooltip": "Ch\u1ea1y ch\u01b0\u01a1ng tr\u00ecnh.", + "Apps.runProgram": "Ch\u1ea1y", + "Apps.resetProgram": "Tr\u1edf V\u1ec1", + "Apps.dialogOk": "OK", + "Apps.dialogCancel": "H\u1ee7y", + "Apps.catLogic": "L\u00f4git", + "Apps.catLoops": "V\u00f2ng l\u1eb7p", + "Apps.catMath": "To\u00e1n", + "Apps.catText": "V\u0103n b\u1ea3n", + "Apps.catLists": "Danh s\u00e1ch", + "Apps.catColour": "M\u00e0u", + "Apps.catVariables": "Bi\u1ebfn", + "Apps.catProcedures": "Th\u1ee7 t\u1ee5c", + "Apps.httpRequestError": "Ho\u1ea1t \u0111\u1ed9ng b\u1ecb tr\u1ee5c tr\u1eb7c, kh\u00f4ng th\u1ef1c hi\u1ec7n \u0111\u01b0\u1ee3c y\u00eau c\u1ea7u c\u1ee7a b\u1ea1n.", + "Apps.linkAlert": "D\u00f9ng li\u00ean k\u1ebft n\u00e0y \u0111\u1ec3 chia s\u1ebd ch\u01b0\u01a1ng tr\u00ecnh c\u1ee7a b\u1ea1n:\n\n%1", + "Apps.hashError": "Kh\u00f4ng t\u00ecm th\u1ea5y ch\u01b0\u01a1ng tr\u00ecnh \u0111\u01b0\u1ee3c l\u01b0u \u1edf '%1'.", + "Apps.xmlError": "Kh\u00f4ng m\u1edf \u0111\u01b0\u1ee3c ch\u01b0\u01a1ng tr\u00ecnh c\u1ee7a b\u1ea1n. C\u00f3 th\u1ec3 n\u00f3 n\u1eb1m trong m\u1ed9t phi\u00ean b\u1ea3n kh\u00e1c c\u1ee7a Blockly?", + "Apps.listVariable": "danh s\u00e1ch", + "Apps.textVariable": "v\u0103n b\u1ea3n", + "Code.badXml": "L\u1ed7i s\u1eed l\u00fd XML:\n %1\n\nCh\u1ecdn 'OK' \u0111\u1ec3 t\u1eeb b\u1ecf c\u00e1c thay \u0111\u1ed5i ho\u1eb7c 'H\u1ee7y' \u0111\u1ec3 ti\u1ebfp t\u1ee5c ch\u1ec9nh s\u1eeda c\u00e1c XML.", + "Code.badCode": "'L\u1ed7i ch\u01b0\u01a1ng tr\u00ecnh:\n%1", + "Code.timeout": "\u0110\u00e3 v\u01b0\u1ee3t qu\u00e1 s\u1ed1 l\u1ea7n l\u1eb7p cho ph\u00e9p.", + "Code.discard": "X\u00f3a h\u1ebft %1 m\u1ea3nh?", + "Code.title": "Ch\u01b0\u01a1ng tr\u00ecnh", + "Code.blocks": "C\u00e1c m\u1ea3nh", + "Code.trashTooltip": "X\u00f3a t\u1ea5t c\u1ea3 m\u1ecdi m\u1ea3nh.", + "Graph.title": "\u0110\u1ed3 Th\u1ecb", + "Maze.moveForward": "\u0111i t\u1edbi", + "Maze.turnLeft": "quay qua tr\u00e1i", + "Maze.turnRight": "quay qua ph\u1ea3i", + "Maze.doCode": "h\u00e3y", + "Maze.elseCode": "n\u1ebfu kh\u00f4ng", + "Maze.helpIfElse": "M\u1ea3nh 'n\u1ebfu-n\u1ebfu kh\u00f4ng' s\u1ebd th\u1ef1c hi\u1ec7n m\u1ed9t trong hai nh\u00f3m l\u1ec7nh \u0111\u01b0a ra.", + "Maze.pathAhead": "n\u1ebfu c\u00f3 \u0111\u01b0\u1eddng ph\u00eda tr\u01b0\u1edbc", + "Maze.pathLeft": "n\u1ebfu c\u00f3 \u0111\u01b0\u1eddng b\u00ean tr\u00e1i", + "Maze.pathRight": "n\u1ebfu c\u00f3 \u0111\u01b0\u1eddng b\u00ean ph\u1ea3i", + "Maze.repeatUntil": "l\u1eb7p l\u1ea1i cho \u0111\u1ebfn", + "Maze.moveForwardTooltip": "Di chuy\u1ec3n Pegman t\u1edbi m\u1ed9t b\u01b0\u1edbc.", + "Maze.turnTooltip": "Quay Pegman qua b\u00ean tr\u00e1i ho\u1eb7c b\u00ean ph\u1ea3i 90 \u0111\u1ed9.", + "Maze.ifTooltip": "N\u1ebfu c\u00f3 \u0111\u01b0\u1eddng \u1edf h\u01b0\u1edbng \u0111\u1ea5y, h\u00e3y th\u1ef1c hi\u1ec7n c\u00e1c l\u1ec7nh \u0111\u01b0a ra.", + "Maze.ifelseTooltip": "N\u1ebfu c\u00f3 \u0111\u01b0\u1eddng \u1edf h\u01b0\u1edbng \u0111\u1ea5y, h\u00e3y th\u1ef1c hi\u1ec7n c\u00e1c l\u1ec7nh th\u1ee9 nh\u1ea5t. N\u1ebfu kh\u00f4ng, th\u1ef1c hi\u1ec7n c\u00e1c l\u1ec7nh th\u1ee9 hai.", + "Maze.whileTooltip": "Th\u1ef1c hi\u1ec7n c\u00e1c l\u1ec7nh \u0111\u01b0\u1ee3c bao g\u1ed3m cho \u0111\u1ebfn khi \u0111\u1ebfn \u0111\u00edch", + "Maze.capacity0": "B\u1ea1n c\u00f2n %0 m\u1ea3nh.", + "Maze.capacity1": "B\u1ea1n c\u00f2n %1 m\u1ea3nh.", + "Maze.capacity2": "B\u1ea1n c\u00f2n %2 m\u1ea3nh.", + "Maze.nextLevel": "Ch\u00fac m\u1eebng! B\u1ea1n \u0111\u00e3 s\u1eb5n s\u00e0ng qua v\u00f2ng %1?", + "Maze.finalLevel": "Ch\u00fac m\u1eebng! B\u1ea1n \u0111\u00e3 gi\u1ea3i xong v\u00f2ng cu\u1ed1i c\u00f9ng.", + "Maze.maze": "Ma tr\u1eadn", + "Maze.runTooltip": "Khi\u1ebfn ng\u01b0\u1eddi ch\u01a1i l\u00e0m theo l\u1ec7nh trong c\u00e1c m\u1ea3nh.", + "Maze.resetTooltip": "\u0110\u01b0a ng\u01b0\u1eddi ch\u01a1i tr\u1edf l\u1ea1i v\u1ecb tr\u00ed kh\u1edfi \u0111\u1ea7u c\u1ee7a m\u00ea cung.", + "Maze.helpStack": "Ch\u1ed3ng hai m\u1ea3nh '\u0111i t\u1edbi' l\u00ean nhau \u0111\u1ec3 gi\u00fap t\u1edb \u0111\u1ebfn \u0111\u00edch.", + "Maze.helpOneTopBlock": "\u1ede v\u00f2ng n\u00e0y, b\u1ea1n c\u1ea7n g\u1eafn ch\u1ed3ng c\u00e1c m\u1ea3nh l\u1ec7nh l\u00ean nhau trong kho\u1ea3ng tr\u1eafng (c\u00f2n \u0111\u01b0\u1ee3c g\u1ecdi l\u00e0 s\u00e2n ch\u01a1i) \u0111\u1ec3 t\u1ea1o chu\u1ed7i m\u1ec7nh l\u1ec7nh c\u1ea7n thi\u1ebft.", + "Maze.helpRun": "Ch\u1ea1y ch\u01b0\u01a1ng tr\u00ecnh c\u1ee7a b\u1ea1n \u0111\u1ec3 xem \u0111i\u1ec1u g\u00ec s\u1ebd x\u1ea3y ra.", + "Maze.helpReset": "Ch\u01b0\u01a1ng tr\u00ecnh c\u1ee7a b\u1ea1n ch\u01b0a gi\u1ea3i m\u00ea cung. Nh\u1ea5n 'Tr\u1edf l\u1ea1i' v\u00e0 th\u1eed l\u1ea1i.", + "Maze.helpRepeat": "\u0110\u1ebfn cu\u1ed1i \u0111\u01b0\u1eddng ch\u1ec9 b\u1eb1ng hai m\u1ea3nh. S\u1eed d\u1ee5ng 'l\u1eb7p l\u1ea1i' \u0111\u1ec3 ch\u1ea1y m\u1ed9t m\u1ea3nh h\u01a1n m\u1ed9t l\u1ea7n.", + "Maze.helpCapacity": "B\u1ea1n \u0111\u00e3 s\u1eed d\u1ee5ng h\u1ebft t\u1ea5t m\u1ea3nh trong c\u1ea5p n\u00e0y. \u0110\u1ec3 t\u1ea1o m\u1ea3nh m\u1edbi, tr\u01b0\u1edbc ti\u00ean b\u1ea1n c\u1ea7n x\u00f3a m\u1ed9t m\u1ea3nh hi\u1ec7n t\u1ea1i.", + "Maze.helpRepeatMany": "B\u1ea1n c\u00f3 th\u1ec3 \u0111\u1eb7t nhi\u1ec1u m\u1ea3nh v\u00e0o trong m\u1ed9t m\u1ea3nh 'l\u1eb7p l\u1ea1i'.", + "Maze.helpSkins": "L\u1ef1a ch\u1ecdn nh\u00e2n v\u1eadt y\u00eau th\u00edch c\u1ee7a b\u1ea1n t\u1eeb tr\u00ecnh \u0111\u01a1n n\u00e0y.", + "Maze.helpIf": "M\u1ea3nh 'n\u1ebfu [\u0111i\u1ec1u ki\u1ec7n]' nh\u00ecn v\u00e0o \u0111i\u1ec1u ki\u1ec7n r\u1ed3i ch\u1ec9 th\u1ef1c hi\u1ec7n l\u1ec7nh n\u1ebfu c\u00f3 \u0111i\u1ec1u ki\u1ec7n \u1ea5y. H\u00e3y th\u1eed r\u1ebd tr\u00e1i n\u1ebfu c\u00f3 \u0111\u01b0\u1eddng b\u00ean tr\u00e1i.", + "Maze.helpMenu": "\u1ea4n v\u00e0o %1 trong m\u1ea3nh 'n\u1ebfu' \u0111\u1ec3 thay \u0111\u1ed5i h\u00ecnh th\u1ec3 c\u1ee7a n\u00f3.", + "Maze.helpWallFollow": "B\u1ea1n c\u00f3 th\u1ec3 gi\u1ea3i c\u00e1i ma tr\u1eadn r\u1eafc r\u1ed1i n\u00e0y? G\u1ee3i \u00fd: Th\u1eed \u0111i s\u00e1t theo m\u1ed9t b\u1ee9c t\u01b0\u1eddng, y nh\u01b0 b\u1ea1n \u0111ang gi\u1eef m\u1ed9t tay theo su\u1ed1t b\u1ee9c t\u01b0\u1eddng \u1ea5y, d\u00f9 n\u00f3 r\u1ebb ph\u1ea3i hay tr\u00e1i.", + "Plane.rows": "S\u1ed1 h\u00e0ng gh\u1ebf: %1", + "Plane.getRows": "\u0111\u1ebfm s\u1ed1 h\u00e0ng gh\u1ebf (%1)", + "Plane.rows1": "H\u00e0ng h\u1ea1ng nh\u1ea5t: %1", + "Plane.getRows1": "s\u1ed1 h\u00e0ng h\u1ea1ng nh\u1ea5t (%1)", + "Plane.rows2": "H\u00e0ng h\u1ea1ng hai: %1", + "Plane.getRows2": "s\u1ed1 h\u00e0ng h\u1ea1ng hai (%1)", + "Plane.seats": "S\u1ed1 ch\u1ed7 ng\u1ed3i: %1", + "Plane.placeholder": "?", + "Plane.setSeats": "T\u00ednh s\u1ed1 ch\u1ed7 ng\u1ed3i =", + "Plane.plane": "M\u00e1y Bay", + "Plane.description1": "M\u00e1y bay c\u00f3 m\u1ed9t s\u1ed1 h\u00e0ng gh\u1ebf h\u00e0nh kh\u00e1ch. M\u1ed7i h\u00e0ng c\u00f3 b\u1ed1n ch\u1ed7 ng\u1ed3i.", + "Plane.description2": "M\u1ed9t m\u00e1y bay c\u00f3 hai gh\u1ebf trong bu\u1ed3ng l\u00e1i (d\u00e0nh cho phi c\u00f4ng tr\u01b0\u1edfng v\u00e0 phi c\u00f4ng ph\u1ee5), v\u00e0 m\u1ed9t lo\u1ea1t h\u00e0ng gh\u1ebf cho h\u00e0nh kh\u00e1ch. M\u1ed7i h\u00e0ng c\u00f3 b\u1ed1n gh\u1ebf (b\u1ed1n ch\u1ed7 ng\u1ed3i).", + "Plane.description3": "M\u1ed9t chi\u1ebfc m\u00e1y bay n\u00e0y c\u00f3 hai ch\u1ed7 ng\u1ed3i \u1edf s\u00e0n (cho phi c\u00f4ng tr\u01b0\u1edfng v\u00e0 phi c\u00f4ng ph\u00f3), v\u00e0 m\u1ed9t s\u1ed1 h\u00e0ng gh\u1ebf h\u1ea1ng 1 v\u00e0 h\u1ea1ng 2. M\u1ed7i h\u00e0ng h\u1ea1ng 1 c\u00f3 b\u1ed1n ch\u1ed7 ng\u1ed3i. M\u1ed7i h\u00e0ng h\u1ea1ng 2 c\u00f3 n\u0103m ch\u1ed7 ng\u1ed3i.", + "Plane.instructions": "D\u01b0\u1edbi \u0111\u00e2y h\u00e3y t\u1ea1o c\u00f4ng th\u1ee9c t\u00ednh s\u1ed1 ch\u1ed7 ng\u1ed3i tr\u00ean m\u00e1y bay \u0111\u1ec3 n\u00f3 thay \u0111\u1ed5i t\u00f9y theo s\u1ed1 l\u01b0\u1ee3ng h\u00e0ng gh\u1ebf (h\u00ecnh tr\u00ean).", + "Puzzle.country1": "\u00dac", + "Puzzle.country1Language": "Ti\u1ebfng Anh", + "Puzzle.country1City1": "Melbourne", + "Puzzle.country1City2": "Sydney", + "Puzzle.country1HelpUrl": "http://vi.wikipedia.org/wiki/%C3%9Ac", + "Puzzle.country2": "\u0110\u1ee9c", + "Puzzle.country2Language": "Ti\u1ebfng \u0110\u1ee9c", + "Puzzle.country2City1": "B\u00e9clin", + "Puzzle.country2City2": "Munich", + "Puzzle.country2HelpUrl": "http://vi.wikipedia.org/wiki/%C4%90%E1%BB%A9c", + "Puzzle.country3": "Trung Qu\u1ed1c", + "Puzzle.country3Language": "Ti\u1ebfng Hoa", + "Puzzle.country3City1": "B\u1eafc Kinh", + "Puzzle.country3City2": "Th\u01b0\u1ee3ng H\u1ea3i", + "Puzzle.country3HelpUrl": "http://vi.wikipedia.org/wiki/Trung_Qu%E1%BB%91c", + "Puzzle.country4": "Braxin", + "Puzzle.country4Language": "Ti\u1ebfng B\u1ed3 \u0110\u00e0o Nha", + "Puzzle.country4City1": "Rio de Janeiro", + "Puzzle.country4City2": "S\u00e3o Paulo", + "Puzzle.country4HelpUrl": "http://vi.wikipedia.org/wiki/Brasil", + "Puzzle.flag": "c\u1edd:", + "Puzzle.language": "ng\u00f4n ng\u1eef:", + "Puzzle.languageChoose": "ch\u1ecdn...", + "Puzzle.cities": "c\u00e1c th\u00e0nh ph\u1ed1:", + "Puzzle.error0": "R\u1ea5t ho\u00e0n ch\u1ec9nh!\nT\u1ea5t c\u1ea3 %1 m\u1ea3nh \u0111\u1ec1u ch\u00ednh x\u00e1c.", + "Puzzle.error1": "G\u1ea7n \u0111\u00fang r\u1ed3i! M\u1ed9t m\u1ea3nh c\u00f2n ch\u01b0a ch\u00ednh x\u00e1c.", + "Puzzle.error2": "%1 m\u1ea3nh c\u00f2n ch\u01b0a ch\u00ednh x\u00e1c.", + "Puzzle.tryAgain": "C\u00e1c m\u1ea3nh \u0111\u01b0\u1ee3c \u0111\u00e1nh d\u1ea5u l\u00e0 kh\u00f4ng \u0111\u00fang.\nC\u1ed1 l\u00ean!", + "Puzzle.title": "\u0110\u1ed1 vui", + "Puzzle.help": "Tr\u1ee3 gi\u00fap", + "Puzzle.checkAnswers": "Ki\u1ec3m tra \u0111\u00e1p \u00e1n", + "Puzzle.helpText": "V\u1edbi m\u1ed7i qu\u1ed1c gia (m\u00e0u xanh l\u00e1 c\u00e2y), h\u00e3y g\u1eafn v\u00e0o \u0111\u00f3 l\u00e1 c\u1edd \u0111\u00fang c\u1ee7a qu\u1ed1c gia \u0111\u00f3, ch\u1ecdn ng\u00f4n ng\u1eef, v\u00e0 n\u1ed1i ch\u1ed3ng c\u00e1c th\u00e0nh ph\u1ed1 c\u1ee7a n\u00f3 v\u00e0o qu\u1ed1c gia \u0111\u00f3.", + "Turtle.moveTooltip": "Di chuy\u1ec3n con r\u00f9a t\u1edbi ho\u1eb7c lui m\u1ed9t \u0111o\u1ea1n t\u00f9y \u00fd.", + "Turtle.moveForward": "\u0111i t\u1edbi", + "Turtle.moveBackward": "\u0111i lui", + "Turtle.turnTooltip": "Quay con r\u00f9a qua tay tr\u00e1i ho\u1eb7c tay ph\u1ea3i m\u1ed9t s\u1ed1 \u0111\u1ed9 t\u00f9y \u00fd.", + "Turtle.turnRight": "quay qua tay\u00a0ph\u1ea3i", + "Turtle.turnLeft": "quay qua tay\u00a0tr\u00e1i", + "Turtle.widthTooltip": "Thay \u0111\u1ed5i \u0111\u1ed9 r\u1ed9ng c\u1ee7a b\u00fat v\u1ebd.", + "Turtle.setWidth": "\u0111\u1eb7t chi\u1ec1u r\u1ed9ng", + "Turtle.colourTooltip": "Thay m\u00e0u c\u1ee7a b\u00fat v\u1ebd.", + "Turtle.setColour": "g\u00e1n m\u00e0u", + "Turtle.penTooltip": "Nh\u1ea5t b\u00fat v\u1ebd l\u00ean ho\u1eb7c \u0111\u1eb7t xu\u1ed1ng, \u0111\u1ec3 b\u1eaft \u0111\u1ea7u ho\u1eb7c ng\u01b0ng n\u00e9t v\u1ebd.", + "Turtle.penUp": "b\u00fat v\u1ebd nh\u1ea5c l\u00ean", + "Turtle.penDown": "b\u00fat v\u1ebd \u0111\u1eb7t xu\u1ed1ng", + "Turtle.turtleVisibilityTooltip": "L\u00e0m cho con r\u00f9a (v\u00f2ng tr\u00f2n v\u00e0 m\u0169i t\u00ean) hi\u1ec7n h\u00ecnh ho\u1eb7c v\u00f4 h\u00ecnh.", + "Turtle.hideTurtle": "hide R\u00f9a", + "Turtle.showTurtle": "show R\u00f9a", + "Turtle.printHelpUrl": "http://en.wikipedia.org/wiki/Printing", + "Turtle.printTooltip": "In v\u0103n b\u1ea3n theo h\u01b0\u1edbng v\u00e0 v\u1ecb tr\u00ed c\u1ee7a con r\u00f9a.", + "Turtle.print": "In", + "Turtle.fontHelpUrl": "http://en.wikipedia.org/wiki/Font", + "Turtle.fontTooltip": "B\u1ed9 ph\u00f4ng ch\u1eef \u0111\u01b0\u1ee3c s\u1eed d\u1ee5ng b\u1edfi m\u1ea3nh in.", + "Turtle.font": "ph\u00f4ng ch\u1eef", + "Turtle.fontSize": "K\u00edch th\u01b0\u1edbc ph\u00f4ng ch\u1eef", + "Turtle.fontNormal": "th\u01b0\u1eddng", + "Turtle.fontBold": "\u0111\u1eadm", + "Turtle.fontItalic": "nghi\u00eang", + "Turtle.unloadWarning": "N\u1ebfu r\u1eddi kh\u1ecfi trang n\u00e0y b\u1ea1n s\u1ebd m\u1ea5t k\u1ebft qu\u1ea3 hi\u1ec7n t\u1ea1i.", + "Turtle.title": "\u0110\u1ed3 H\u1ecda Con R\u00f9a", + "Turtle.runTooltip": "Khi\u1ebfn con r\u00f9a l\u00e0m theo l\u1ec7nh trong c\u00e1c m\u1ea3nh.", + "Turtle.captureTooltip": "L\u01b0u b\u1ea3n v\u1ebd.", + "Turtle.imgFilename": "banve.png", + "Turtle.catTurtle": "R\u00f9a" +} \ No newline at end of file diff --git a/apps/json/zh-hans.json b/apps/json/zh-hans.json new file mode 100644 index 000000000..7644e6cce --- /dev/null +++ b/apps/json/zh-hans.json @@ -0,0 +1,153 @@ +{ + "@metadata": { + "authors": [ + "Hydra", + "Hzy980512", + "Liuxinyu970226", + "Qiyue2001" + ] + }, + "Apps.subtitle": "\u4e00\u4e2a\u53ef\u89c6\u5316\u7f16\u7a0b\u73af\u5883", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "\u67e5\u770b\u751f\u6210\u7684JavaScript\u4ee3\u7801\u3002", + "Apps.linkTooltip": "\u4fdd\u5b58\u6a21\u5757\u5e76\u751f\u6210\u94fe\u63a5\u3002", + "Apps.runTooltip": "\u4e8e\u5de5\u4f5c\u533a\u4e2d\u8fd0\u884c\u5757\u6240\u5b9a\u4e49\u7684\u7a0b\u5f0f\u3002", + "Apps.runProgram": "\u8fd0\u884c\u7a0b\u5e8f", + "Apps.resetProgram": "\u91cd\u7f6e", + "Apps.dialogOk": "\u786e\u8ba4", + "Apps.dialogCancel": "\u53d6\u6d88", + "Apps.catLogic": "\u903b\u8f91", + "Apps.catLoops": "\u5faa\u73af", + "Apps.catMath": "\u6570\u5b66", + "Apps.catText": "\u6587\u672c", + "Apps.catLists": "\u5217\u8868", + "Apps.catColour": "\u989c\u8272", + "Apps.catVariables": "\u53d8\u91cf", + "Apps.catProcedures": "\u7a0b\u5e8f", + "Apps.httpRequestError": "\u8bf7\u6c42\u5b58\u5728\u95ee\u9898\u3002", + "Apps.linkAlert": "\u70b9\u51fb\u94fe\u63a5\u5206\u4eab\u60a8\u7684\u6a21\u5757\uff1a\n\n%1", + "Apps.hashError": "\u5bf9\u4e0d\u8d77\uff0c\u6ca1\u6709\u4efb\u4f55\u5df2\u4fdd\u5b58\u7684\u7a0b\u5e8f\u5bf9\u5e94'%1' \u3002", + "Apps.xmlError": "\u65e0\u6cd5\u8f7d\u5165\u60a8\u4fdd\u5b58\u7684\u6587\u4ef6\u3002\u60a8\u662f\u5426\u662f\u4f7f\u7528\u5176\u4ed6\u7248\u672c\u7684Blockly\u521b\u5efa\u7684\uff1f", + "Apps.listVariable": "\u5217\u8868", + "Apps.textVariable": "\u6587\u672c", + "Code.badXml": "XML\u89e3\u6790\u9519\u8bef\uff1a\n%1\n\n\u9009\u62e9'\u786e\u5b9a'\u4ee5\u53d6\u6d88\u60a8\u5bf9XML\u7684\u4fee\u6539\u6216'\u53d6\u6d88'\u4ee5\u7ee7\u7eed\u7f16\u8f91\u3002", + "Code.badCode": "\u7a0b\u5e8f\u9519\u8bef\uff1a\n%1", + "Code.timeout": "\u8d85\u8fc7\u6700\u5927\u6267\u884c\u884c\u6570\u3002", + "Code.discard": "\u5220\u9664\u6240\u6709%1\u5757\u5417\uff1f", + "Code.title": "\u4ee3\u7801", + "Code.blocks": "\u5757", + "Code.trashTooltip": "\u653e\u5f03\u6240\u6709\u5757\u3002", + "Graph.title": "\u56fe\u5f62\u8ba1\u7b97\u5668", + "Maze.moveForward": "\u5411\u524d\u79fb\u52a8", + "Maze.turnLeft": "\u5411\u5de6\u8f6c", + "Maze.turnRight": "\u5411\u53f3\u8f6c", + "Maze.doCode": "\u6267\u884c", + "Maze.elseCode": "\u5176\u4ed6", + "Maze.helpIfElse": "If-else\u6a21\u5757\u5c06\u505a\u81f3\u5c11\u4e00\u4ef6\u4e8b\u3002", + "Maze.pathAhead": "\u5982\u524d\u65b9\u6709\u8def", + "Maze.pathLeft": "\u5982\u679c\u8def\u5f84\u5411\u5de6", + "Maze.pathRight": "\u5982\u679c\u8def\u5f84\u5411\u53f3", + "Maze.repeatUntil": "\u91cd\u590d\u76f4\u5230", + "Maze.moveForwardTooltip": "\u5c0f\u4eba\u524d\u79fb1\u6b65", + "Maze.turnTooltip": "\u5c06\u5c0f\u4eba\u5411\u5de6\u6216\u5411\u53f3\u8f6c\u52a890\u5ea6", + "Maze.ifTooltip": "\u5982\u679c\u5728\u67d0\u4e00\u6307\u5b9a\u65b9\u5411\u5b58\u5728\u8def\u5f84\uff0c\u90a3\u4e48\u6267\u884c\u7279\u5b9a\u64cd\u4f5c\u3002", + "Maze.ifelseTooltip": "\u82e5\u67d0\u65b9\u5411\u6709\u8def\u53ef\u884c\uff0c\u5c31\u53bb\u6267\u884c\u7b2c\u4e00\u4e2a\u5757\u6307\u5b9a\u7684\u52a8\u4f5c\u3002\u82e5\u5426\uff0c\u6267\u884c\u7b2c\u4e8c\u4e2a\u5757\u6307\u5b9a\u7684\u52a8\u4f5c\u3002", + "Maze.whileTooltip": "\u91cd\u590d\u5305\u542b\u7684\u52a8\u4f5c\u76f4\u81f3\u5230\u8fbe\u7ec8\u70b9\u3002", + "Maze.capacity0": "\u4f60\u8fd8\u6709%0\u4e2a\u5757\u3002", + "Maze.capacity1": "\u60a8\u8fd8\u5269\u4e0b%1\u5757\u3002", + "Maze.capacity2": "\u4f60\u8fd8\u6709%2\u5757\u3002", + "Maze.nextLevel": "\u606d\u559c\uff01\u4f60\u51c6\u5907\u597d\u524d\u8fdb\u81f3\u7b2c%1\u7ea7\u522b\u4e86\u5417?", + "Maze.finalLevel": "\u606d\u559c\uff01\u4f60\u5df2\u5b8c\u6210\u6700\u7ec8\u5173\u5361\u3002", + "Maze.maze": "\u8ff7\u5bab", + "Maze.runTooltip": "\u8ba9\u73a9\u5bb6\u6309\u7167\u5757\u7684\u6307\u4ee4\u53bb\u505a\u3002", + "Maze.resetTooltip": "\u5c06\u73a9\u5bb6\u653e\u5728\u8ff7\u5bab\u524d\u7aef\u3002", + "Maze.helpStack": "\u7a0b\u5e8f\u662f\u7531\u4e00\u7cfb\u5217\u6a21\u5757\u7ec4\u6210\u7684\u3002\u5c06\u6570\u4e2a\u201c\u524d\u79fb\u201d\u6a21\u5757\u5806\u780c\u8d77\u6765\uff0c\u5e2e\u52a9\u6211\u5b9e\u73b0\u76ee\u6807\u3002", + "Maze.helpOneTopBlock": "\u5728\u8fd9\u4e00\u5173\u5361\u4e2d\uff0c\u4f60\u9700\u8981\u5c06\u6240\u6709\u65b9\u5757\u5806\u5728\u767d\u8272\u5de5\u4f5c\u533a\u5185\u3002", + "Maze.helpRun": "\u8fd0\u884c\u60a8\u7684\u7a0b\u5e8f\u770b\u770b\u4f1a\u53d1\u751f\u4ec0\u4e48\u3002", + "Maze.helpReset": "\u60a8\u7684\u7a0b\u5e8f\u6ca1\u6709\u89e3\u51b3\u8c1c\u9898\u3002\u70b9\u201c\u91cd\u7f6e\u201d\u7136\u540e\u518d\u8bd5\u4e00\u6b21\u3002", + "Maze.helpRepeat": "\u53ea\u7528\u4e24\u4e2a\u65b9\u5757\u5230\u8fbe\u6b64\u8def\u5f84\u7684\u672b\u5c3e\u3002\u4f7f\u7528\u201c\u91cd\u590d\u201d\u6765\u591a\u6b21\u8fd0\u884c\u65b9\u5757\u3002", + "Maze.helpCapacity": "\u60a8\u53ef\u4ee5\u5728\u8fd9\u5173\u91cc\u7528\u5b8c\u6240\u6709\u65b9\u5757\u3002\u8981\u521b\u5efa\u65b0\u65b9\u5757\uff0c\u60a8\u5fc5\u987b\u5148\u5220\u9664\u4e00\u4e2a\u5df2\u5b58\u5728\u7684\u65b9\u5757\u3002", + "Maze.helpRepeatMany": "\u60a8\u53ef\u4ee5\u5728\u201c\u91cd\u590d\u65b9\u5757\u201d\u4e2d\u653e\u7f6e\u591a\u4e2a\u65b9\u5757", + "Maze.helpSkins": "\u4ece\u6b64\u83dc\u5355\u4e2d\u9009\u62e9\u60a8\u6700\u559c\u7231\u7684\u73a9\u5bb6\u3002", + "Maze.helpIf": "\u201cif\u201d\u8bed\u5757\u53ea\u4f1a\u5728\u6761\u4ef6\u4e3a\u771f\u65f6\u624d\u4f1a\u6267\u884c\u3002\u6709\u5411\u5de6\u62d0\u7684\u8def\u5f84\u65f6\u8bd5\u8bd5\u5de6\u8f6c\u3002", + "Maze.helpMenu": "\u5728\u201cif\u201d\u5757\u4e2d\u70b9\u51fb$1\u6765\u6539\u53d8\u5176\u6761\u4ef6\u3002", + "Maze.helpWallFollow": "\u60a8\u53ef\u4ee5\u89e3\u51b3\u8fd9\u4e2a\u590d\u6742\u7684\u8ff7\u5bab\u5417\uff1f\u8bd5\u7740\u6cbf\u7740\u5de6\u8fb9\u7684\u5899\u884c\u8d70\u3002\u4ec5\u9650\u9ad8\u7ea7\u7a0b\u5e8f\u5458\uff01", + "Plane.rows": "\u884c\uff1a%1", + "Plane.getRows": "\u884c (%1)", + "Plane.rows1": "\u5934\u7b49\u884c\uff1a%1", + "Plane.getRows1": "\u5934\u7b49\u884c\uff08%1\uff09", + "Plane.rows2": "\u7ecf\u6d4e\u7b49\u884c\uff1a%1", + "Plane.getRows2": "\u7ecf\u6d4e\u7b49\u884c\uff08%1\uff09", + "Plane.seats": "\u5ea7\u4f4d\uff1a%1", + "Plane.placeholder": "\uff1f", + "Plane.setSeats": "\u5ea7\u4f4d\uff1d", + "Plane.plane": "\u98de\u673a", + "Plane.description1": "\u4e00\u67b6\u98de\u673a\u6709\u4e00\u5b9a\u91cf\u884c\u6570\u7684\u4e58\u5ba2\u5ea7\u4f4d\uff0c\u6bcf\u884c\u5171\u56db\u5ea7\u3002", + "Plane.description2": "\u4e00\u67b6\u98de\u673a\u9664\u4e86\u6709\u4e24\u4e2a\u5ea7\u4f4d\u4f9b\u6b63\u526f\u9a7e\u9a76\u5458\uff0c\u8fd8\u6709\u4e00\u5b9a\u91cf\u884c\u6570\u7684\u4e58\u5ba2\u5ea7\u4f4d\u3002\u6bcf\u884c\u5171\u56db\u5ea7\u3002", + "Plane.description3": "\u4e00\u67b6\u98de\u673a\u9664\u4e86\u6709\u4e24\u4e2a\u5ea7\u4f4d\u4f9b\u6b63\u526f\u9a7e\u9a76\u5458\uff0c\u8fd8\u6709\u4e00\u5b9a\u91cf\u884c\u6570\u7684\u5934\u7b49\u53ca\u7ecf\u6d4e\u4e58\u5ba2\u5ea7\u4f4d\u3002\u5934\u7b49\u6bcf\u884c\u5171\u56db\u5ea7\uff0c\u7ecf\u6d4e\u6bcf\u884c\u5171\u4e94\u5ea7\u3002", + "Plane.instructions": "\u4e8e\u4e0b\u65b9\u5199\u51fa\u4e00\u6761\u516c\u5f0f\u4ee5\u8ba1\u7b97\u98de\u673a\u4e0a\u7684\u5ea7\u4f4d\u603b\u6570\u3002", + "Puzzle.country1": "\u6fb3\u5927\u5229\u4e9a", + "Puzzle.country1Language": "\u82f1\u8bed", + "Puzzle.country1City1": "\u58a8\u5c14\u672c", + "Puzzle.country1City2": "\u6089\u5c3c", + "Puzzle.country1HelpUrl": "http://zh.wikipedia.org/wiki/\u6fb3\u5927\u5229\u4e9a", + "Puzzle.country2": "\u5fb7\u56fd", + "Puzzle.country2Language": "\u5fb7\u8bed", + "Puzzle.country2City1": "\u67cf\u6797", + "Puzzle.country2City2": "\u6155\u5c3c\u9ed1", + "Puzzle.country2HelpUrl": "http://zh.wikipedia.org/wiki/\u5fb7\u56fd", + "Puzzle.country3": "\u4e2d\u56fd", + "Puzzle.country3Language": "\u6c49\u8bed", + "Puzzle.country3City1": "\u5317\u4eac", + "Puzzle.country3City2": "\u4e0a\u6d77", + "Puzzle.country3HelpUrl": "http://zh.wikipedia.org/wiki/\u4e2d\u534e\u4eba\u6c11\u5171\u548c\u56fd", + "Puzzle.country4": "\u5df4\u897f", + "Puzzle.country4Language": "\u8461\u8404\u7259\u8bed", + "Puzzle.country4City1": "\u91cc\u7ea6\u70ed\u5185\u5362", + "Puzzle.country4City2": "\u5723\u4fdd\u7f57", + "Puzzle.country4HelpUrl": "http://zh.wikipedia.org/wiki/\u5df4\u897f", + "Puzzle.flag": "\u56fd\u65d7\uff1a", + "Puzzle.language": "\u8bed\u8a00\uff1a", + "Puzzle.languageChoose": "\u8bf7\u9009\u62e9...", + "Puzzle.cities": "\u57ce\u5e02\uff1a", + "Puzzle.error0": "\u5b8c\u7f8e!\n\u6240\u6709\u5171%1\u5757\u90fd\u6b63\u786e\u3002", + "Puzzle.error1": "\u5dee\u4e0d\u591a\u4e86\uff01\u8fd8\u6709\u4e00\u4e2a\u5757\u662f\u4e0d\u6b63\u786e\u7684\u3002", + "Puzzle.error2": "%1 \u5757\u4e0d\u6b63\u786e", + "Puzzle.tryAgain": "\u9ad8\u4eae\u5757\u4e0d\u6b63\u786e\uff0c\u8bf7\u91cd\u8bd5\u3002", + "Puzzle.title": "\u62fc\u56fe", + "Puzzle.help": "\u5e2e\u52a9", + "Puzzle.checkAnswers": "\u68c0\u67e5\u7b54\u6848", + "Puzzle.helpText": "\u4e3a\u6bcf\u4e2a\u56fd\u5bb6\uff08\u7eff\u8272\uff09\u52a0\u4e0a\u5176\u56fd\u65d7\u3001\u9009\u62e9\u5176\u4f7f\u7528\u7684\u8bed\u8a00\u5e76\u52a0\u5165\u5176\u62e5\u6709\u7684\u57ce\u5e02\u3002", + "Turtle.moveTooltip": "\u5c06\u4e4c\u9f9f\u5411\u524d\u6216\u5411\u540e\u79fb\u52a8\u6307\u5b9a\u7684\u91cf\u3002", + "Turtle.moveForward": "\u524d\u79fb\u6307\u5b9a\u683c\u6570", + "Turtle.moveBackward": "\u540e\u79fb\u6307\u5b9a\u683c\u6570", + "Turtle.turnTooltip": "\u6309\u6307\u5b9a\u7684\u5ea6\u6570\u5411\u5de6\u6216\u5411\u53f3\u8f6c\u52a8\u4e4c\u9f9f\u3002", + "Turtle.turnRight": "\u53f3\u8f6c", + "Turtle.turnLeft": "\u5de6\u8f6c", + "Turtle.widthTooltip": "\u66f4\u6539\u5bbd\u5ea6\u3002", + "Turtle.setWidth": "\u5c06\u5bbd\u5ea6\u8bbe\u7f6e\u4e3a", + "Turtle.colourTooltip": "\u66f4\u6539\u753b\u7b14\u989c\u8272\u3002", + "Turtle.setColour": "\u8bbe\u7f6e\u989c\u8272", + "Turtle.penTooltip": "\u63d0\u9ad8\u6216\u653e\u4e0b\u7b14\u4ee5\u505c\u6b62\u6216\u5f00\u59cb\u7ed8\u56fe\u3002", + "Turtle.penUp": "\u62ff\u8d77\u7b14", + "Turtle.penDown": "\u653e\u4e0b\u7b14", + "Turtle.turtleVisibilityTooltip": "\u4f7f\u4e4c\u9f9f\uff08\u5706\u5708\u548c\u7bad\u5934\uff09\u53ef\u89c1\u6216\u9690\u85cf\u3002", + "Turtle.hideTurtle": "\u9690\u85cf\u4e4c\u9f9f", + "Turtle.showTurtle": "\u663e\u793a\u4e4c\u9f9f", + "Turtle.printHelpUrl": "http://zh.wikipedia.org/wiki/\u5370\u5237", + "Turtle.printTooltip": "\u5728\u9f9f\u7684\u65b9\u5411\u53ca\u4f4d\u7f6e\u7ed8\u5236\u6587\u672c\u3002", + "Turtle.print": "\u6253\u5370", + "Turtle.fontHelpUrl": "http://zh.wikipedia.org/wiki/\u5b57\u4f53", + "Turtle.fontTooltip": "\u8bbe\u7f6e\u6253\u5370\u5757\u4f7f\u7528\u7684\u5b57\u4f53\u3002", + "Turtle.font": "\u5b57\u4f53", + "Turtle.fontSize": "\u5b57\u4f53\u5927\u5c0f", + "Turtle.fontNormal": "\u6b63\u5e38", + "Turtle.fontBold": "\u7c97\u4f53", + "Turtle.fontItalic": "\u659c\u4f53", + "Turtle.unloadWarning": "\u79bb\u5f00\u672c\u9875\u9762\u4f1a\u4e22\u5931\u4f60\u7684\u5de5\u4f5c\u3002", + "Turtle.title": "\u4e4c\u9f9f\u56fe\u5f62", + "Turtle.runTooltip": "\u8ba9\u4e4c\u9f9f\u6309\u7167\u5757\u7684\u6307\u4ee4\u5de5\u4f5c\u3002", + "Turtle.captureTooltip": "\u4fdd\u5b58\u8be5\u7ed8\u56fe\u3002", + "Turtle.imgFilename": "\u7ed8\u56fe.png", + "Turtle.catTurtle": "\u4e4c\u9f9f" +} \ No newline at end of file diff --git a/apps/json/zh-hant.json b/apps/json/zh-hant.json new file mode 100644 index 000000000..e37eda80a --- /dev/null +++ b/apps/json/zh-hant.json @@ -0,0 +1,138 @@ +{ + "@metadata": { + "authors": [ + "Justincheng12345" + ] + }, + "Apps.subtitle": "\u8996\u89ba\u5316\u7a0b\u5f0f\u8a2d\u8a08\u74b0\u5883", + "Apps.blocklyMessage": "Blockly", + "Apps.codeTooltip": "\u67e5\u770b\u7522\u751f\u7684JavaScript\u7a0b\u5f0f\u78bc\u3002", + "Apps.linkTooltip": "\u5132\u5b58\u6a21\u7d44\u4e26\u63d0\u4f9b\u9023\u7d50\u3002", + "Apps.runTooltip": "\u65bc\u5de5\u4f5c\u5340\u4e2d\u904b\u884c\u6a21\u7d44\u6240\u5b9a\u7fa9\u7684\u7a0b\u5f0f\u3002", + "Apps.runProgram": "\u904b\u884c\u7a0b\u5f0f", + "Apps.resetProgram": "\u91cd\u8a2d", + "Apps.dialogOk": "\u78ba\u5b9a", + "Apps.catLogic": "\u908f\u8f2f", + "Apps.catLoops": "\u8ff4\u5708", + "Apps.catMath": "\u6578\u5b78\u516c\u5f0f", + "Apps.catText": "\u6587\u5b57", + "Apps.catLists": "\u5217\u8868", + "Apps.catColour": "\u984f\u8272", + "Apps.catVariables": "\u8b8a\u6578", + "Apps.catProcedures": "\u7a0b\u5e8f", + "Apps.httpRequestError": "\u8acb\u6c42\u5b58\u5728\u554f\u984c\u3002", + "Apps.linkAlert": "\u4ee5\u6b64\u9023\u7d50\u5206\u4eab\u60a8\u7684\u6a21\u7d44\uff1a\n\n%1", + "Apps.hashError": "\u5c0d\u4e0d\u8d77\uff0c\u300c%1\u300d\u4e26\u672a\u5c0d\u61c9\u4efb\u4f55\u5df2\u4fdd\u5b58\u7684\u7a0b\u5f0f\u3002", + "Apps.xmlError": "\u672a\u80fd\u8f09\u5165\u60a8\u4fdd\u5b58\u7684\u6a94\u6848\u3002\u6216\u8a31\u5b83\u662f\u7531\u5176\u4ed6\u7248\u672c\u7684Blockly\u5275\u5efa\uff1f", + "Apps.listVariable": "\u5217\u8868", + "Apps.textVariable": "\u6587\u5b57", + "Code.badXml": "XML \u89e3\u6790\u932f\u8aa4\uff1a\n%1\n\n\u6368\u68c4\u8b8a\u66f4\uff1f", + "Code.badCode": "\u7a0b\u5f0f\u932f\u8aa4\uff1a\n%1", + "Code.timeout": "\u8d85\u904e\u6700\u5927\u57f7\u884c\u6578\u3002", + "Code.discard": "\u522a\u9664\u6240\u6709%1\u6a21\u7d44\uff1f", + "Code.title": "\u4ee3\u78bc", + "Code.blocks": "\u6a21\u7d44", + "Code.trashTooltip": "\u6368\u68c4\u6240\u6709\u6a21\u7d44\u3002", + "Graph.title": "\u5716\u5f62\u8a08\u7b97\u6a5f", + "Maze.moveForward": "\u5411\u524d\u79fb\u52d5", + "Maze.turnLeft": "\u5de6\u8f49", + "Maze.turnRight": "\u53f3\u8f49", + "Maze.doCode": "\u57f7\u884c", + "Maze.elseCode": "\u6216", + "Maze.pathAhead": "\u5982\u524d\u65b9\u6709\u8def", + "Maze.pathLeft": "\u5982\u5de6\u65b9\u6709\u8def", + "Maze.pathRight": "\u5982\u53f3\u65b9\u6709\u8def", + "Maze.repeatUntil": "\u91cd\u8986\u76f4\u81f3", + "Maze.moveForwardTooltip": "\u79fb\u524d\u4e00\u6b65\u3002", + "Maze.turnTooltip": "\u5411\u5de6\u6216\u53f390\u5ea6\u3002", + "Maze.ifTooltip": "\u82e5\u67d0\u65b9\u5411\u6709\u8def\u53ef\u884c\uff0c\u5c31\u53bb\u57f7\u884c\u67d0\u4e9b\u52d5\u4f5c\u3002", + "Maze.ifelseTooltip": "\u82e5\u67d0\u65b9\u5411\u6709\u8def\u53ef\u884c\uff0c\u5c31\u53bb\u57f7\u884c\u7b2c\u4e00\u500b\u6a21\u7d44\u6307\u5b9a\u7684\u52d5\u4f5c\uff0c\u82e5\u5426\uff0c\u57f7\u884c\u7b2c\u4e8c\u500b\u6a21\u7d44\u6307\u5b9a\u7684\u52d5\u4f5c\u3002", + "Maze.whileTooltip": "\u91cd\u8986\u5305\u542b\u7684\u52d5\u4f5c\u76f4\u81f3\u5230\u9054\u7d42\u9ede\u3002", + "Maze.capacity0": "\u4f60\u9918\u4e0b%0\u6a21\u7d44\u3002", + "Maze.capacity1": "\u4f60\u9918\u4e0b%1\u6a21\u7d44\u3002", + "Maze.capacity2": "\u4f60\u9918\u4e0b%2\u6a21\u7d44\u3002", + "Maze.nextLevel": "\u606d\u559c\uff01\u6e96\u5099\u597d\u524d\u9032\u81f3\u7b2c%1\u95dc\u4e86\u55ce\uff1f", + "Maze.finalLevel": "\u606d\u559c\uff01\u4f60\u5df2\u5b8c\u6210\u6700\u7d42\u95dc\u5361\u3002", + "Maze.maze": "\u8ff7\u5bae", + "Maze.runTooltip": "\u8b93\u4eba\u7269\u6309\u6a21\u7d44\u7684\u6307\u4ee4\u5de5\u4f5c\u3002", + "Maze.resetTooltip": "\u5c07\u4eba\u7269\u653e\u56de\u8ff7\u5bae\u958b\u7aef\u3002", + "Maze.helpStack": "\u7a0b\u6216\u662f\u7531\u4e00\u7cfb\u5217\u6a21\u7d44\u7d44\u6210\u3002\u5c07\u6578\u500b\u300c\u524d\u79fb\u300d\u6a21\u7d44\u5806\u780c\u8d77\u4f86\u4ee5\u5be6\u73fe\u76ee\u6a19\u3002", + "Plane.rows": "\u884c\uff1a%1", + "Plane.getRows": "\u884c\uff08%1\uff09", + "Plane.rows1": "\u982d\u7b49\u884c\uff1a%1", + "Plane.getRows1": "\u982d\u7b49\u884c\uff08%1\uff09", + "Plane.rows2": "\u7d93\u6fdf\u7b49\u884c\uff1a%1", + "Plane.getRows2": "\u7d93\u6fdf\u7b49\u884c\uff08%1\uff09", + "Plane.seats": "\u5ea7\u4f4d\uff1a%1", + "Plane.placeholder": "\uff1f", + "Plane.setSeats": "\u5ea7\u4f4d\uff1d", + "Plane.plane": "\u98db\u6a5f", + "Plane.description1": "\u4e00\u67b6\u98db\u6a5f\u6709\u4e00\u5b9a\u91cf\u884c\u6578\u7684\u4e58\u5ba2\u5ea7\u4f4d\uff0c\u6bcf\u884c\u5171\u56db\u5ea7\u3002", + "Plane.description2": "\u4e00\u67b6\u98db\u6a5f\u9664\u4e86\u6709\u5169\u500b\u5ea7\u4f4d\u4f9b\u6b63\u526f\u6a5f\u5e2b\uff0c\u9084\u6709\u4e00\u5b9a\u91cf\u884c\u6578\u7684\u4e58\u5ba2\u5ea7\u4f4d\u3002\u6bcf\u884c\u5171\u56db\u5ea7\u3002", + "Plane.description3": "\u4e00\u67b6\u98db\u6a5f\u9664\u4e86\u6709\u5169\u500b\u5ea7\u4f4d\u4f9b\u6b63\u526f\u6a5f\u5e2b\uff0c\u9084\u6709\u4e00\u5b9a\u91cf\u884c\u6578\u7684\u982d\u7b49\u53ca\u7d93\u6fdf\u4e58\u5ba2\u5ea7\u4f4d\u3002\u982d\u7b49\u6bcf\u884c\u5171\u56db\u5ea7\uff0c\u7d93\u6fdf\u6bcf\u884c\u5171\u4e94\u5ea7\u3002", + "Plane.instructions": "\u65bc\u4e0b\u65b9\u5beb\u51fa\u4e00\u689d\u516c\u5f0f\u4ee5\u8a08\u7b97\u98db\u6a5f\u4e0a\u7684\u5ea7\u4f4d\u7e3d\u6578\u3002", + "Puzzle.country1": "\u6fb3\u6d32", + "Puzzle.country1Language": "\u82f1\u8a9e", + "Puzzle.country1City1": "\u58a8\u723e\u672c", + "Puzzle.country1City2": "\u6089\u5c3c", + "Puzzle.country1HelpUrl": "http://zh.wikipedia.org/wiki/\u6fb3\u6d32", + "Puzzle.country2": "\u5fb7\u570b", + "Puzzle.country2Language": "\u5fb7\u8a9e", + "Puzzle.country2City1": "\u67cf\u6797", + "Puzzle.country2City2": "\u6155\u5c3c\u514b", + "Puzzle.country2HelpUrl": "http://zh.wikipedia.org/wiki/\u5fb7\u570b", + "Puzzle.country3": "\u4e2d\u570b", + "Puzzle.country3Language": "\u4e2d\u6587", + "Puzzle.country3City1": "\u5317\u4eac", + "Puzzle.country3City2": "\u4e0a\u6d77", + "Puzzle.country3HelpUrl": "http://zh.wikipedia.org/wiki/\u4e2d\u570b", + "Puzzle.country4": "\u5df4\u897f", + "Puzzle.country4Language": "\u8461\u8404\u7259\u6587", + "Puzzle.country4City1": "\u91cc\u7d04\u71b1\u5167\u76e7", + "Puzzle.country4City2": "\u8056\u4fdd\u7f85", + "Puzzle.country4HelpUrl": "http://zh.wikipedia.org/wiki/\u5df4\u897f", + "Puzzle.flag": "\u570b\u65d7\uff1a", + "Puzzle.language": "\u8a9e\u8a00\uff1a", + "Puzzle.languageChoose": "\u8acb\u9078\u64c7\u2026", + "Puzzle.cities": "\u57ce\u5e02\uff1a", + "Puzzle.error0": "\u5b8c\u7f8e\uff01\n\u6240\u6709\u5171%1\u584a\u7686\u6b63\u78ba\u3002", + "Puzzle.error1": "\u5dee\u4e0d\u591a\uff01\u6709\u4e00\u584a\u51fa\u932f\u4e86\u3002", + "Puzzle.error2": "%1\u584a\u51fa\u932f\u3002", + "Puzzle.tryAgain": "\u9ad8\u4eae\u986f\u793a\u7684\u584a\u4e0d\u6b63\u78ba\uff0c\u8acb\u91cd\u8a66\u3002", + "Puzzle.title": "\u62fc\u5716", + "Puzzle.help": "\u8aaa\u660e", + "Puzzle.checkAnswers": "\u6aa2\u67e5\u7b54\u6848", + "Puzzle.helpText": "\u70ba\u6bcf\u500b\u570b\u5bb6\uff08\u7da0\u8272\uff09\u52a0\u4e0a\u5176\u570b\u65d7\u3001\u9078\u64c7\u5176\u4f7f\u7528\u7684\u8a9e\u8a00\u4e26\u52a0\u5165\u5176\u64c1\u6709\u7684\u57ce\u5e02\u3002", + "Turtle.moveTooltip": "\u5c07\u70cf\u9f9c\u5411\u524d\u6216\u5411\u5f8c\u79fb\u52d5\u6307\u5b9a\u7684\u91cf\u3002", + "Turtle.moveForward": "\u5411\u524d\u79fb\u52d5", + "Turtle.moveBackward": "\u5411\u5f8c\u79fb\u52d5", + "Turtle.turnTooltip": "\u6309\u6307\u5b9a\u5ea6\u6578\u5411\u5de6\u6216\u5411\u53f3\u8f49\u52d5\u70cf\u9f9c\u3002", + "Turtle.turnRight": "\u53f3\u8f49", + "Turtle.turnLeft": "\u5de6\u8f49", + "Turtle.widthTooltip": "\u66f4\u6539\u5bec\u5ea6\u3002", + "Turtle.setWidth": "\u5c07\u5bec\u5ea6\u8a2d\u7f6e\u70ba", + "Turtle.colourTooltip": "\u66f4\u6539\u92fc\u7b46\u3002", + "Turtle.setColour": "\u8a2d\u7f6e\u984f\u8272", + "Turtle.penTooltip": "\u63d0\u9ad8\u6216\u653e\u4e0b\u7b46\u4ee5\u505c\u6b62\u6216\u958b\u59cb\u7e8c\u756b", + "Turtle.penUp": "\u62ff\u8d77\u7b46", + "Turtle.penDown": "\u653e\u4e0b\u7b46", + "Turtle.turtleVisibilityTooltip": "\u4f7f\u9f9c\uff08\u7da0\u8272\u5713\u5708\u548c\u7bad\u982d\uff09\uff0c\u53ef\u898b\u6216\u96b1\u85cf\u3002", + "Turtle.hideTurtle": "\u96b1\u85cf\u70cf\u9f9c", + "Turtle.showTurtle": "\u986f\u793a\u70cf\u9f9c", + "Turtle.printHelpUrl": "http://zh.wikipedia.org/wiki/\u5370\u5237", + "Turtle.printTooltip": "\u5728\u70cf\u9f9c\u7684\u65b9\u5411\u53ca\u4f4d\u7f6e\u7e6a\u88fd\u6587\u5b57\u3002", + "Turtle.print": "\u5217\u5370", + "Turtle.fontHelpUrl": "http://zh.wikipedia.org/wiki/\u5b57\u9ad4", + "Turtle.fontTooltip": "\u8a2d\u7f6e\u5217\u5370\u6a21\u7d44\u4f7f\u7528\u7684\u5b57\u578b\u3002", + "Turtle.font": "\u5b57\u578b", + "Turtle.fontSize": "\u5b57\u9ad4\u5927\u5c0f", + "Turtle.fontNormal": "\u4e00\u822c", + "Turtle.fontBold": "\u7c97\u9ad4", + "Turtle.fontItalic": "\u659c\u9ad4", + "Turtle.unloadWarning": "\u96e2\u958b\u672c\u9801\u9762\u5c07\u5931\u53bb\u4f60\u7684\u5de5\u4f5c\u3002", + "Turtle.title": "\u70cf\u9f9c\u5716\u5f62", + "Turtle.runTooltip": "\u8b93\u70cf\u9f9c\u6309\u6a21\u7d44\u7684\u6307\u4ee4\u5de5\u4f5c\u3002", + "Turtle.captureTooltip": "\u5132\u5b58\u8a72\u7e6a\u5716\u3002", + "Turtle.imgFilename": "drawing.png", + "Turtle.catTurtle": "\u70cf\u9f9c" +} \ No newline at end of file diff --git a/apps/json/zh-tw.json b/apps/json/zh-tw.json new file mode 100644 index 000000000..9809df208 --- /dev/null +++ b/apps/json/zh-tw.json @@ -0,0 +1,11 @@ +{ + "Apps.catLogic": "邏輯", + "Apps.catVariables": "變量", + "Apps.catProcedures": "流程", + "Apps.catMath": "算數", + "Apps.catText": "字串", + "Apps.catLists": "列表", + "Code.blocks": "積木", + "Apps.catColour": "Colour", + "Code.title": "正體中文版" +} diff --git a/apps/maze/astro.png b/apps/maze/astro.png new file mode 100644 index 000000000..6ed8b1ae6 Binary files /dev/null and b/apps/maze/astro.png differ diff --git a/apps/maze/bg_astro.jpg b/apps/maze/bg_astro.jpg new file mode 100644 index 000000000..8c71174de Binary files /dev/null and b/apps/maze/bg_astro.jpg differ diff --git a/apps/maze/bg_panda.jpg b/apps/maze/bg_panda.jpg new file mode 100644 index 000000000..e812a9381 Binary files /dev/null and b/apps/maze/bg_panda.jpg differ diff --git a/apps/maze/blocks.js b/apps/maze/blocks.js new file mode 100644 index 000000000..3a2754125 --- /dev/null +++ b/apps/maze/blocks.js @@ -0,0 +1,165 @@ +/** + * Blockly Apps: Maze Blocks + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Blocks for Blockly's Maze application. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +// Extensions to Blockly's language and JavaScript generator. + +Blockly.Blocks['maze_moveForward'] = { + // Block for moving forward. + init: function() { + this.setHelpUrl('http://code.google.com/p/blockly/wiki/Move'); + this.setColour(290); + this.appendDummyInput() + .appendTitle(BlocklyApps.getMsg('Maze_moveForward')); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(BlocklyApps.getMsg('Maze_moveForwardTooltip')); + } +}; + +Blockly.JavaScript['maze_moveForward'] = function(block) { + // Generate JavaScript for moving forward. + return 'Maze.moveForward(\'block_id_' + block.id + '\');\n'; +}; + +Blockly.Blocks['maze_turn'] = { + // Block for turning left or right. + init: function() { + var DIRECTIONS = + [[BlocklyApps.getMsg('Maze_turnLeft'), 'turnLeft'], + [BlocklyApps.getMsg('Maze_turnRight'), 'turnRight']]; + if (Maze.addArrows) { + // Append arrows to direction messages. + DIRECTIONS[0][0] += ' \u27F2'; + DIRECTIONS[1][0] += ' \u27F3'; + } + this.setHelpUrl('http://code.google.com/p/blockly/wiki/Turn'); + this.setColour(290); + this.appendDummyInput() + .appendTitle(new Blockly.FieldDropdown(DIRECTIONS), 'DIR'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(BlocklyApps.getMsg('Maze_turnTooltip')); + } +}; + +Blockly.JavaScript['maze_turn'] = function(block) { + // Generate JavaScript for turning left or right. + var dir = block.getTitleValue('DIR'); + return 'Maze.' + dir + '(\'block_id_' + block.id + '\');\n'; +}; + +Blockly.Blocks['maze_if'] = { + // Block for 'if' conditional if there is a path. + init: function() { + var DIRECTIONS = + [[BlocklyApps.getMsg('Maze_pathAhead'), 'isPathForward'], + [BlocklyApps.getMsg('Maze_pathLeft'), 'isPathLeft'], + [BlocklyApps.getMsg('Maze_pathRight'), 'isPathRight']]; + if (Maze.addArrows) { + // Append arrows to direction messages. + DIRECTIONS[1][0] += ' \u27F2'; + DIRECTIONS[2][0] += ' \u27F3'; + } + this.setColour(210); + this.appendDummyInput() + .appendTitle(new Blockly.FieldDropdown(DIRECTIONS), 'DIR'); + this.appendStatementInput('DO') + .appendTitle(BlocklyApps.getMsg('Maze_doCode')); + this.setTooltip(BlocklyApps.getMsg('Maze_ifTooltip')); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + + +Blockly.JavaScript['maze_if'] = function(block) { + // Generate JavaScript for 'if' conditional if there is a path. + var argument = 'Maze.' + block.getTitleValue('DIR') + + '(\'block_id_' + block.id + '\')'; + var branch = Blockly.JavaScript.statementToCode(block, 'DO'); + var code = 'if (' + argument + ') {\n' + branch + '}\n'; + return code; +}; + +Blockly.Blocks['maze_ifElse'] = { + // Block for 'if/else' conditional if there is a path. + init: function() { + var DIRECTIONS = + [[BlocklyApps.getMsg('Maze_pathAhead'), 'isPathForward'], + [BlocklyApps.getMsg('Maze_pathLeft'), 'isPathLeft'], + [BlocklyApps.getMsg('Maze_pathRight'), 'isPathRight']]; + if (Maze.addArrows) { + // Append arrows to direction messages. + DIRECTIONS[1][0] += ' \u27F2'; + DIRECTIONS[2][0] += ' \u27F3'; + } + this.setColour(210); + this.appendDummyInput() + .appendTitle(new Blockly.FieldDropdown(DIRECTIONS), 'DIR'); + this.appendStatementInput('DO') + .appendTitle(BlocklyApps.getMsg('Maze_doCode')); + this.appendStatementInput('ELSE') + .appendTitle(BlocklyApps.getMsg('Maze_elseCode')); + this.setTooltip(BlocklyApps.getMsg('Maze_ifelseTooltip')); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +Blockly.JavaScript['maze_ifElse'] = function(block) { + // Generate JavaScript for 'if/else' conditional if there is a path. + var argument = 'Maze.' + block.getTitleValue('DIR') + + '(\'block_id_' + block.id + '\')'; + var branch0 = Blockly.JavaScript.statementToCode(block, 'DO'); + var branch1 = Blockly.JavaScript.statementToCode(block, 'ELSE'); + var code = 'if (' + argument + ') {\n' + branch0 + + '} else {\n' + branch1 + '}\n'; + return code; +}; + +Blockly.Blocks['maze_forever'] = { + // Do forever loop. + init: function() { + this.setHelpUrl('http://code.google.com/p/blockly/wiki/Repeat'); + this.setColour(120); + this.appendDummyInput() + .appendTitle(BlocklyApps.getMsg('Maze_repeatUntil')) + .appendTitle(new Blockly.FieldImage(Maze.SKIN.marker, 12, 16)); + this.appendStatementInput('DO') + .appendTitle(BlocklyApps.getMsg('Maze_doCode')); + this.setPreviousStatement(true); + this.setTooltip(BlocklyApps.getMsg('Maze_whileTooltip')); + } +}; + +Blockly.JavaScript['maze_forever'] = function(block) { + // Generate JavaScript for do forever loop. + var branch = Blockly.JavaScript.statementToCode(block, 'DO'); + if (Blockly.JavaScript.INFINITE_LOOP_TRAP) { + branch = Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g, + '\'block_id_' + block.id + '\'') + branch; + } + return 'while (true) {\n' + branch + '}\n'; +}; diff --git a/apps/maze/generated/af.js b/apps/maze/generated/af.js new file mode 100644 index 000000000..5dd306c9f --- /dev/null +++ b/apps/maze/generated/af.js @@ -0,0 +1,60 @@ +// This file was automatically generated from common.soy. +// Please don't edit this file by hand. + +if (typeof apps == 'undefined') { var apps = {}; } + + +apps.messages = function(opt_data, opt_ignored, opt_ijData) { + return '
    a visual programming environmentBlocklySee generated JavaScript code.Save and link to blocks.Run the program defined by the blocks in the workspace.Run ProgramResetOKCancelLogicLoopsMathTextListsColourVariablesProceduresThere was a problem with the request.Share your blocks with this link:\\n\\n%1Sorry, \'%1\' doesn\'t correspond with any saved program.Could not load your saved file. Perhaps it was created with a different version of Blockly?listtext
    '; +}; + + +apps.dialog = function(opt_data, opt_ignored, opt_ijData) { + return '
    '; +}; + + +apps.codeDialog = function(opt_data, opt_ignored, opt_ijData) { + return '
    ' + apps.ok(null, null, opt_ijData) + '
    '; +}; + + +apps.storageDialog = function(opt_data, opt_ignored, opt_ijData) { + return '
    ' + apps.ok(null, null, opt_ijData) + '
    '; +}; + + +apps.ok = function(opt_data, opt_ignored, opt_ijData) { + return '
    '; +}; + +; +// This file was automatically generated from template.soy. +// Please don't edit this file by hand. + +if (typeof mazepage == 'undefined') { var mazepage = {}; } + + +mazepage.messages = function(opt_data, opt_ignored, opt_ijData) { + return apps.messages(null, null, opt_ijData) + '
    move forwardturn leftturn rightdoelseIf-else blocks will do one thing or the other.if path aheadif path to the leftif path to the rightrepeat untilMoves the player forward one space.Turns the player left or right by 90 degrees.If there is a path in the specified direction, then do some actions.If there is a path in the specified direction, then do the first block of actions. Otherwise, do the second block of actions.Repeat the enclosed actions until finish point is reached.You have %0 blocks left.You have %1 block left.You have %2 blocks left.Congratulations! Are you ready to proceed to level %1?Congratulations! You have solved the final level.
    '; +}; + + +mazepage.start = function(opt_data, opt_ignored, opt_ijData) { + var output = mazepage.messages(null, null, opt_ijData) + '

    Blockly : Maze   '; + for (var i161 = 1; i161 < 11; i161++) { + output += ' ' + ((i161 == opt_ijData.level) ? '' + soy.$$escapeHtml(i161) + '' : (i161 < opt_ijData.level) ? '' : '' + soy.$$escapeHtml(i161) + ''); + } + output += '

     
    + + + + + + + + diff --git a/apps/maze/marker.png b/apps/maze/marker.png new file mode 100644 index 000000000..235f31656 Binary files /dev/null and b/apps/maze/marker.png differ diff --git a/apps/maze/maze.js b/apps/maze/maze.js new file mode 100644 index 000000000..134eb040d --- /dev/null +++ b/apps/maze/maze.js @@ -0,0 +1,1458 @@ +/** + * Blockly Apps: Maze + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview JavaScript for Blockly's Maze application. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +/** + * Create a namespace for the application. + */ +var Maze = {}; + +// Supported languages. +BlocklyApps.LANGUAGES = ['br', 'ca', 'cs', 'da', 'de', 'el', 'en', + 'es', 'eu', 'fa', 'fr', 'gl', 'hu', 'ia', 'it', 'ko', 'lv', 'mk', 'ms', + 'nl', 'pl', 'pms', 'pt', 'ru', 'sk', 'sr', 'sv', 'sw', 'th', 'tr', + 'uk', 'vi', 'zh-hans', 'zh-hant']; +BlocklyApps.LANG = BlocklyApps.getLang(); + +document.write('\n'); + +Maze.MAX_LEVEL = 10; +Maze.LEVEL = BlocklyApps.getNumberParamFromUrl('level', 1, Maze.MAX_LEVEL); +Maze.MAX_BLOCKS = [undefined, // Level 0. + Infinity, Infinity, 2, 5, 5, 5, 5, 10, 7, 10][Maze.LEVEL]; + +Maze.SKINS = [ + // sprite: A 1029x51 set of 21 avatar images. + // tiles: A 250x200 set of 20 map images. + // marker: A 20x34 goal image. + // background: An optional 400x450 background image, or false. + // graph: Colour of optional grid lines, or false. + // look: Colour of sonar-like look icon. + { + sprite: 'pegman.png', + tiles: 'tiles_pegman.png', + marker: 'marker.png', + background: false, + graph: false, + look: '#000' + }, + { + sprite: 'astro.png', + tiles: 'tiles_astro.png', + marker: 'marker.png', + background: 'bg_astro.jpg', + // Coma star cluster, photo by George Hatfield, used with permission. + graph: false, + look: '#fff' + }, + { + sprite: 'panda.png', + tiles: 'tiles_panda.png', + marker: 'marker.png', + background: 'bg_panda.jpg', + // Spring canopy, photo by Rupert Fleetingly, CC licensed for reuse. + graph: false, + look: '#000' + } +]; +Maze.SKIN_ID = BlocklyApps.getNumberParamFromUrl('skin', 0, Maze.SKINS.length); +Maze.SKIN = Maze.SKINS[Maze.SKIN_ID]; + +/** + * Milliseconds between each animation frame. + */ +Maze.stepSpeed; + +/** + * The types of squares in the maze, which is represented + * as a 2D array of SquareType values. + * @enum {number} + */ +Maze.SquareType = { + WALL: 0, + OPEN: 1, + START: 2, + FINISH: 3 +}; + +// The maze square constants defined above are inlined here +// for ease of reading and writing the static mazes. +Maze.map = [ +// Level 0. + undefined, +// Level 1. + [[0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 2, 1, 3, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0]], +// Level 2. + [[0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 1, 3, 0, 0, 0], + [0, 0, 2, 1, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0]], +// Level 3. + [[0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 2, 1, 1, 1, 1, 3, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0]], +// Level 4. +/** + * Note, the path continues past the start and the goal in both directions. + * This is intentionally done so users see the maze is about getting from + * the start to the goal and not necessarily about moving over every part of + * the maze, 'mowing the lawn' as Neil calls it. + */ + [[0, 0, 0, 0, 0, 0, 0, 1], + [0, 0, 0, 0, 0, 0, 1, 1], + [0, 0, 0, 0, 0, 1, 3, 0], + [0, 0, 0, 0, 1, 1, 0, 0], + [0, 0, 0, 1, 1, 0, 0, 0], + [0, 0, 1, 1, 0, 0, 0, 0], + [0, 2, 1, 0, 0, 0, 0, 0], + [1, 1, 0, 0, 0, 0, 0, 0]], +// Level 5. + [[0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 3, 0, 0], + [0, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 0, 2, 1, 1, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0]], +// Level 6. + [[0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 1, 1, 1, 1, 1, 0, 0], + [0, 1, 0, 0, 0, 1, 0, 0], + [0, 1, 1, 3, 0, 1, 0, 0], + [0, 0, 0, 0, 0, 1, 0, 0], + [0, 2, 1, 1, 1, 1, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0]], +// Level 7. + [[0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 1, 1, 0], + [0, 2, 1, 1, 1, 1, 0, 0], + [0, 0, 0, 0, 0, 1, 1, 0], + [0, 1, 1, 3, 0, 1, 0, 0], + [0, 1, 0, 1, 0, 1, 0, 0], + [0, 1, 1, 1, 1, 1, 1, 0], + [0, 0, 0, 0, 0, 0, 0, 0]], +// Level 8. + [[0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 1, 1, 1, 1, 0, 0, 0], + [0, 1, 0, 0, 1, 1, 0, 0], + [0, 1, 1, 1, 0, 1, 0, 0], + [0, 0, 0, 1, 0, 1, 0, 0], + [0, 2, 1, 1, 0, 3, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0]], +// Level 9. + [[0, 0, 0, 0, 0, 0, 0, 0], + [0, 1, 1, 1, 1, 1, 0, 0], + [0, 0, 1, 0, 0, 0, 0, 0], + [3, 1, 1, 1, 1, 1, 1, 0], + [0, 1, 0, 1, 0, 1, 1, 0], + [1, 1, 1, 1, 1, 0, 1, 0], + [0, 1, 0, 1, 0, 2, 1, 0], + [0, 0, 0, 0, 0, 0, 0, 0]], +// Level 10. + [[0, 0, 0, 0, 0, 0, 0, 0], + [0, 1, 1, 0, 3, 0, 1, 0], + [0, 1, 1, 0, 1, 1, 1, 0], + [0, 1, 0, 1, 0, 1, 0, 0], + [0, 1, 1, 1, 1, 1, 1, 0], + [0, 0, 0, 1, 0, 0, 1, 0], + [0, 2, 1, 1, 1, 0, 1, 0], + [0, 0, 0, 0, 0, 0, 0, 0]] +][Maze.LEVEL]; + +/** + * Measure maze dimensions and set sizes. + * ROWS: Number of tiles down. + * COLS: Number of tiles across. + * SQUARE_SIZE: Pixel height and width of each maze square (i.e. tile). + */ +Maze.ROWS = Maze.map.length; +Maze.COLS = Maze.map[0].length; +Maze.SQUARE_SIZE = 50; +Maze.PEGMAN_HEIGHT = 52; +Maze.PEGMAN_WIDTH = 49; + +Maze.MAZE_WIDTH = Maze.SQUARE_SIZE * Maze.COLS; +Maze.MAZE_HEIGHT = Maze.SQUARE_SIZE * Maze.ROWS; +Maze.PATH_WIDTH = Maze.SQUARE_SIZE / 3; + +/** + * Constants for cardinal directions. Subsequent code assumes these are + * in the range 0..3 and that opposites have an absolute difference of 2. + * @enum {number} + */ +Maze.DirectionType = { + NORTH: 0, + EAST: 1, + SOUTH: 2, + WEST: 3 +}; + +/** + * Outcomes of running the user program. + */ +Maze.ResultType = { + UNSET: 0, + SUCCESS: 1, + FAILURE: -1, + TIMEOUT: 2, + ERROR: -2 +}; + +/** + * Result of last execution. + */ +Maze.result = Maze.ResultType.UNSET; + +/** + * Starting direction. + */ +Maze.startDirection = Maze.DirectionType.EAST; + +/** + * PIDs of animation tasks currently executing. + */ +Maze.pidList = []; + +// Map each possible shape to a sprite. +// Input: Binary string representing Centre/North/West/South/East squares. +// Output: [x, y] coordinates of each tile's sprite in tiles.png. +Maze.tile_SHAPES = { + '10010': [4, 0], // Dead ends + '10001': [3, 3], + '11000': [0, 1], + '10100': [0, 2], + '11010': [4, 1], // Vertical + '10101': [3, 2], // Horizontal + '10110': [0, 0], // Elbows + '10011': [2, 0], + '11001': [4, 2], + '11100': [2, 3], + '11110': [1, 1], // Junctions + '10111': [1, 0], + '11011': [2, 1], + '11101': [1, 2], + '11111': [2, 2], // Cross + 'null0': [4, 3], // Empty + 'null1': [3, 0], + 'null2': [3, 1], + 'null3': [0, 3], + 'null4': [1, 3] +}; + +/** + * Create and layout all the nodes for the path, scenery, Pegman, and goal. + */ +Maze.drawMap = function() { + var svg = document.getElementById('svgMaze'); + var scale = Math.max(Maze.ROWS, Maze.COLS) * Maze.SQUARE_SIZE; + svg.setAttribute('viewBox', '0 0 ' + scale + ' ' + scale); + + // Draw the outer square. + var square = document.createElementNS(Blockly.SVG_NS, 'rect'); + square.setAttribute('width', Maze.MAZE_WIDTH); + square.setAttribute('height', Maze.MAZE_HEIGHT); + square.setAttribute('fill', '#F1EEE7'); + square.setAttribute('stroke-width', 1); + square.setAttribute('stroke', '#CCB'); + svg.appendChild(square); + + if (Maze.SKIN.background) { + var tile = document.createElementNS(Blockly.SVG_NS, 'image'); + tile.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', + Maze.SKIN.background); + tile.setAttribute('height', Maze.MAZE_HEIGHT); + tile.setAttribute('width', Maze.MAZE_WIDTH); + tile.setAttribute('x', 0); + tile.setAttribute('y', 0); + svg.appendChild(tile); + } + + if (Maze.SKIN.graph) { + // Draw the grid lines. + // The grid lines are offset so that the lines pass through the centre of + // each square. A half-pixel offset is also added to as standard SVG + // practice to avoid blurriness. + var offset = Maze.SQUARE_SIZE / 2 + 0.5; + for (var k = 0; k < Maze.ROWS; k++) { + var h_line = document.createElementNS(Blockly.SVG_NS, 'line'); + h_line.setAttribute('y1', k * Maze.SQUARE_SIZE + offset); + h_line.setAttribute('x2', Maze.MAZE_WIDTH); + h_line.setAttribute('y2', k * Maze.SQUARE_SIZE + offset); + h_line.setAttribute('stroke', Maze.SKIN.graph); + h_line.setAttribute('stroke-width', 1); + svg.appendChild(h_line); + } + for (var k = 0; k < Maze.COLS; k++) { + var v_line = document.createElementNS(Blockly.SVG_NS, 'line'); + v_line.setAttribute('x1', k * Maze.SQUARE_SIZE + offset); + v_line.setAttribute('x2', k * Maze.SQUARE_SIZE + offset); + v_line.setAttribute('y2', Maze.MAZE_HEIGHT); + v_line.setAttribute('stroke', Maze.SKIN.graph); + v_line.setAttribute('stroke-width', 1); + svg.appendChild(v_line); + } + } + + // Draw the tiles making up the maze map. + + // Return a value of '0' if the specified square is wall or out of bounds, + // '1' otherwise (empty, start, finish). + var normalize = function(x, y) { + if (x < 0 || x >= Maze.COLS || y < 0 || y >= Maze.ROWS) { + return '0'; + } + return (Maze.map[y][x] == Maze.SquareType.WALL) ? '0' : '1'; + }; + + // Compute and draw the tile for each square. + var tileId = 0; + for (var y = 0; y < Maze.ROWS; y++) { + for (var x = 0; x < Maze.COLS; x++) { + // Compute the tile index. + var tile = normalize(x, y) + + normalize(x, y - 1) + // North. + normalize(x + 1, y) + // West. + normalize(x, y + 1) + // South. + normalize(x - 1, y); // East. + + // Draw the tile. + if (!Maze.tile_SHAPES[tile]) { + // Empty square. Use null0 for large areas, with null1-4 for borders. + // Add some randomness to avoid large empty spaces. + if (tile == '00000' && Math.random() > 0.3) { + tile = 'null0'; + } else { + tile = 'null' + Math.floor(1 + Math.random() * 4); + } + } + var left = Maze.tile_SHAPES[tile][0]; + var top = Maze.tile_SHAPES[tile][1]; + // Tile's clipPath element. + var tileClip = document.createElementNS(Blockly.SVG_NS, 'clipPath'); + tileClip.setAttribute('id', 'tileClipPath' + tileId); + var clipRect = document.createElementNS(Blockly.SVG_NS, 'rect'); + clipRect.setAttribute('width', Maze.SQUARE_SIZE); + clipRect.setAttribute('height', Maze.SQUARE_SIZE); + + clipRect.setAttribute('x', x * Maze.SQUARE_SIZE); + clipRect.setAttribute('y', y * Maze.SQUARE_SIZE); + + tileClip.appendChild(clipRect); + svg.appendChild(tileClip); + // Tile sprite. + var tile = document.createElementNS(Blockly.SVG_NS, 'image'); + tile.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', + Maze.SKIN.tiles); + // Position the tile sprite relative to the clipRect. + tile.setAttribute('height', Maze.SQUARE_SIZE * 4); + tile.setAttribute('width', Maze.SQUARE_SIZE * 5); + tile.setAttribute('clip-path', 'url(#tileClipPath' + tileId + ')'); + tile.setAttribute('x', (x - left) * Maze.SQUARE_SIZE); + tile.setAttribute('y', (y - top) * Maze.SQUARE_SIZE); + svg.appendChild(tile); + tileId++; + } + } + + // Add finish marker. + var finishMarker = document.createElementNS(Blockly.SVG_NS, 'image'); + finishMarker.setAttribute('id', 'finish'); + finishMarker.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', + Maze.SKIN.marker); + finishMarker.setAttribute('height', 34); + finishMarker.setAttribute('width', 20); + svg.appendChild(finishMarker); + + // Pegman's clipPath element, whose (x, y) is reset by Maze.displayPegman + var pegmanClip = document.createElementNS(Blockly.SVG_NS, 'clipPath'); + pegmanClip.setAttribute('id', 'pegmanClipPath'); + var clipRect = document.createElementNS(Blockly.SVG_NS, 'rect'); + clipRect.setAttribute('id', 'clipRect'); + clipRect.setAttribute('width', Maze.PEGMAN_WIDTH); + clipRect.setAttribute('height', Maze.PEGMAN_HEIGHT); + pegmanClip.appendChild(clipRect); + svg.appendChild(pegmanClip); + + // Add Pegman. + var pegmanIcon = document.createElementNS(Blockly.SVG_NS, 'image'); + pegmanIcon.setAttribute('id', 'pegman'); + pegmanIcon.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', + Maze.SKIN.sprite); + pegmanIcon.setAttribute('height', Maze.PEGMAN_HEIGHT); + pegmanIcon.setAttribute('width', Maze.PEGMAN_WIDTH * 21); // 49 * 21 = 1029 + pegmanIcon.setAttribute('clip-path', 'url(#pegmanClipPath)'); + svg.appendChild(pegmanIcon); +}; + +/** + * Initialize Blockly and the maze. Called on page load. + */ +Maze.init = function() { + // Measure the height of arrow characters. + // Firefox on Vista creates enormously high arrows (80px) for no reason. + // TODO: Detect if arrow is printed, or Unicode square is printed. + var textElement = document.getElementById('arrowTest'); + var height = textElement.getBBox().height; + Maze.addArrows = height < Blockly.BlockSvg.MIN_BLOCK_Y; + var svg = textElement.ownerSVGElement + svg.parentNode.removeChild(svg); + + BlocklyApps.init(); + + // Setup the Pegman menu. + var pegmanImg = document.querySelector('#pegmanButton>img'); + pegmanImg.style.backgroundImage = 'url(' + Maze.SKIN.sprite + ')'; + var pegmanMenu = document.getElementById('pegmanMenu'); + var handlerFactory = function(n) { + return function() { + Maze.changePegman(n); + }; + }; + for (var i = 0; i < Maze.SKINS.length; i++) { + if (i == Maze.SKIN_ID) { + continue; + } + var div = document.createElement('div'); + var img = document.createElement('img'); + img.src = '../../media/1x1.gif'; + img.style.backgroundImage = 'url(' + Maze.SKINS[i].sprite + ')'; + div.appendChild(img); + pegmanMenu.appendChild(div); + Blockly.bindEvent_(div, 'mousedown', null, handlerFactory(i)); + } + Blockly.bindEvent_(window, 'resize', null, Maze.hidePegmanMenu); + var pegmanButton = document.getElementById('pegmanButton'); + pegmanButton.addEventListener('mousedown', Maze.showPegmanMenu, true); + pegmanButton.addEventListener('touchstart', Maze.showPegmanMenu, true); + + var rtl = BlocklyApps.isRtl(); + var toolbox = document.getElementById('toolbox'); + Blockly.inject(document.getElementById('blockly'), + {path: '../../', + maxBlocks: Maze.MAX_BLOCKS, + rtl: rtl, + toolbox: toolbox, + trashcan: true}); + Blockly.loadAudio_(['apps/maze/win.mp3', 'apps/maze/win.ogg'], 'win'); + Blockly.loadAudio_(['apps/maze/whack.mp3', 'apps/maze/whack.ogg'], 'whack'); + + Blockly.JavaScript.INFINITE_LOOP_TRAP = ' BlocklyApps.checkTimeout(%1);\n'; + Maze.drawMap(); + + var blocklyDiv = document.getElementById('blockly'); + var visualization = document.getElementById('visualization'); + var onresize = function(e) { + var top = visualization.offsetTop; + blocklyDiv.style.top = Math.max(10, top - window.scrollY) + 'px'; + blocklyDiv.style.left = rtl ? '10px' : '420px'; + blocklyDiv.style.width = (window.innerWidth - 440) + 'px'; + }; + window.addEventListener('scroll', function() { + onresize(); + Blockly.fireUiEvent(window, 'resize'); + }); + window.addEventListener('resize', onresize); + onresize(); + Blockly.fireUiEvent(window, 'resize'); + + var defaultXml = + '' + + ' ' + + ''; + BlocklyApps.loadBlocks(defaultXml); + + // Locate the start and finish squares. + for (var y = 0; y < Maze.ROWS; y++) { + for (var x = 0; x < Maze.COLS; x++) { + if (Maze.map[y][x] == Maze.SquareType.START) { + Maze.start_ = {x: x, y: y}; + } else if (Maze.map[y][x] == Maze.SquareType.FINISH) { + Maze.finish_ = {x: x, y: y}; + } + } + } + + Maze.reset(true); + Blockly.addChangeListener(function() {Maze.updateCapacity()}); + + document.body.addEventListener('mousemove', Maze.updatePegSpin_, true); + + BlocklyApps.bindClick('runButton', Maze.runButtonClick); + BlocklyApps.bindClick('resetButton', Maze.resetButtonClick); + + if (Maze.LEVEL == 1) { + // Make connecting blocks easier for beginners. + Blockly.SNAP_RADIUS *= 2; + } + if (Maze.LEVEL == 10) { + // Level 10 gets an introductory modal dialog. + var content = document.getElementById('dialogHelpWallFollow'); + var style = { + width: '30%', + left: '35%', + top: '12em' + }; + BlocklyApps.showDialog(content, null, false, true, style, + BlocklyApps.stopDialogKeyDown); + BlocklyApps.startDialogKeyDown(); + } else { + // All other levels get interactive help. But wait 5 seconds for the + // user to think a bit before they are told what to do. + window.setTimeout(function() { + Blockly.addChangeListener(function() {Maze.levelHelp()}); + Maze.levelHelp(); + }, 5000); + } + + // Lazy-load the syntax-highlighting. + window.setTimeout(BlocklyApps.importPrettify, 1); +}; + +if (window.location.pathname.match(/readonly.html$/)) { + window.addEventListener('load', BlocklyApps.initReadonly); +} else { + window.addEventListener('load', Maze.init); +} + +/** + * When the workspace changes, update the help as needed. + */ +Maze.levelHelp = function() { + if (Blockly.Block.dragMode_ != 0) { + // Don't change helps during drags. + return; + } else if (Maze.result == Maze.ResultType.SUCCESS) { + // The user has already won. They are just playing around. + return; + } + var userBlocks = Blockly.Xml.domToText( + Blockly.Xml.workspaceToDom(Blockly.mainWorkspace)); + var toolbar = Blockly.mainWorkspace.flyout_.workspace_.getTopBlocks(true); + var content = null; + var origin = null; + var style = null; + if (Maze.LEVEL == 1) { + if (Blockly.mainWorkspace.getAllBlocks().length < 2) { + content = document.getElementById('dialogHelpStack'); + style = {width: '370px', top: '120px'}; + style[Blockly.RTL ? 'right' : 'left'] = '215px'; + origin = toolbar[0].getSvgRoot(); + } else { + var topBlocks = Blockly.mainWorkspace.getTopBlocks(true) + if (topBlocks.length > 1) { + var iframe = document.getElementById('iframeOneTopBlock'); + var xml = '' + + ''; + iframe.src = 'readonly.html' + + '?lang=' + encodeURIComponent(BlocklyApps.LANG) + + '&xml=' + encodeURIComponent(xml); + content = document.getElementById('dialogHelpOneTopBlock'); + style = {width: '360px', top: '120px'}; + style[Blockly.RTL ? 'right' : 'left'] = '225px'; + origin = topBlocks[0].getSvgRoot(); + } else if (Maze.result == Maze.ResultType.UNSET) { + // Show run help dialog. + content = document.getElementById('dialogHelpRun'); + style = {width: '360px', top: '410px'}; + style[Blockly.RTL ? 'right' : 'left'] = '400px'; + origin = document.getElementById('runButton'); + } + } + } else if (Maze.LEVEL == 2) { + if (Maze.result != Maze.ResultType.UNSET && + document.getElementById('runButton').style.display == 'none') { + content = document.getElementById('dialogHelpReset'); + style = {width: '360px', top: '410px'}; + style[Blockly.RTL ? 'right' : 'left'] = '400px'; + origin = document.getElementById('resetButton'); + } + } else if (Maze.LEVEL == 3) { + if (userBlocks.indexOf('maze_forever') == -1) { + if (Blockly.mainWorkspace.remainingCapacity() == 0) { + content = document.getElementById('dialogHelpCapacity'); + style = {width: '430px', top: '310px'}; + style[Blockly.RTL ? 'right' : 'left'] = '50px'; + origin = document.getElementById('capacityBubble'); + } else { + content = document.getElementById('dialogHelpRepeat'); + style = {width: '360px', top: '320px'}; + style[Blockly.RTL ? 'right' : 'left'] = '425px'; + origin = toolbar[3].getSvgRoot(); + } + } + } else if (Maze.LEVEL == 4) { + if (Blockly.mainWorkspace.remainingCapacity() == 0 && + (userBlocks.indexOf('maze_forever') == -1 || + Blockly.mainWorkspace.getTopBlocks(false).length > 1)) { + content = document.getElementById('dialogHelpCapacity'); + style = {width: '430px', top: '310px'}; + style[Blockly.RTL ? 'right' : 'left'] = '50px'; + origin = document.getElementById('capacityBubble'); + } else { + var showHelp = true; + // Only show help if there is not a loop with two nested blocks. + var blocks = Blockly.mainWorkspace.getAllBlocks(); + for (var i = 0; i < blocks.length; i++) { + var block = blocks[i]; + if (block.type != 'maze_forever') { + continue; + } + var j = 0; + while (block) { + var kids = block.getChildren(); + block = kids.length ? kids[0] : null; + j++; + } + if (j > 2) { + showHelp = false; + break; + } + } + if (showHelp) { + content = document.getElementById('dialogHelpRepeatMany'); + style = {width: '360px', top: '320px'}; + style[Blockly.RTL ? 'right' : 'left'] = '425px'; + origin = toolbar[3].getSvgRoot(); + } + } + } else if (Maze.LEVEL == 5) { + if (Maze.SKIN_ID == 0 && !Maze.showPegmanMenu.activatedOnce) { + content = document.getElementById('dialogHelpSkins'); + style = {width: '360px', top: '60px'}; + style[Blockly.RTL ? 'left' : 'right'] = '20px'; + origin = document.getElementById('pegmanButton'); + } + } else if (Maze.LEVEL == 6) { + if (userBlocks.indexOf('maze_if') == -1) { + content = document.getElementById('dialogHelpIf'); + style = {width: '360px', top: '400px'}; + style[Blockly.RTL ? 'right' : 'left'] = '425px'; + origin = toolbar[4].getSvgRoot(); + } + } else if (Maze.LEVEL == 7) { + if (!Maze.levelHelp.initialized7_) { + // Create fake dropdown. + var span = document.createElement('span'); + span.className = 'helpMenuFake'; + var options = + [BlocklyApps.getMsg('Maze_pathAhead'), + BlocklyApps.getMsg('Maze_pathLeft'), + BlocklyApps.getMsg('Maze_pathRight')]; + var prefix = Blockly.commonWordPrefix(options); + var suffix = Blockly.commonWordSuffix(options); + if (suffix) { + var option = options[0].slice(prefix, -suffix); + } else { + var option = options[0].substring(prefix); + } + span.textContent = option + ' \u25BE'; + // Inject fake dropdown into message. + var container = document.getElementById('helpMenuText'); + var msg = container.textContent; + container.textContent = ''; + var parts = msg.split(/%\d/); + for (var i = 0; i < parts.length; i++) { + container.appendChild(document.createTextNode(parts[i])); + if (i != parts.length - 1) { + container.appendChild(span.cloneNode(true)); + } + } + Maze.levelHelp.initialized7_ = true; + } + if (userBlocks.indexOf('maze_if') == -1 || + userBlocks.indexOf('isPathForward') != -1) { + content = document.getElementById('dialogHelpMenu'); + style = {width: '360px', top: '400px'}; + style[Blockly.RTL ? 'right' : 'left'] = '425px'; + origin = toolbar[4].getSvgRoot(); + } + } else if (Maze.LEVEL == 9) { + if (userBlocks.indexOf('maze_ifElse') == -1) { + content = document.getElementById('dialogHelpIfElse'); + style = {width: '360px', top: '305px'}; + style[Blockly.RTL ? 'right' : 'left'] = '425px'; + origin = toolbar[5].getSvgRoot(); + } + } + if (content) { + if (content.parentNode != document.getElementById('dialog')) { + BlocklyApps.showDialog(content, origin, true, false, style, null); + } + } else { + BlocklyApps.hideDialog(false); + } +}; + +/** + * Reload with a different Pegman skin. + * @param {number} newSkin ID of new skin. + */ +Maze.changePegman = function(newSkin) { + Maze.saveToStorage(); + window.location = window.location.protocol + '//' + + window.location.host + window.location.pathname + + '?lang=' + BlocklyApps.LANG + '&level=' + Maze.LEVEL + '&skin=' + newSkin; +}; + +/** + * Save the blocks for a one-time reload. + */ +Maze.saveToStorage = function() { + var xml = Blockly.Xml.workspaceToDom(Blockly.mainWorkspace); + var text = Blockly.Xml.domToText(xml); + window.sessionStorage.loadOnceBlocks = text; +}; + +/** + * Display the Pegman skin-change menu. + */ +Maze.showPegmanMenu = function() { + var menu = document.getElementById('pegmanMenu'); + if (menu.style.display == 'block') { + return; // Menu is already open. + } + var button = document.getElementById('pegmanButton'); + Blockly.addClass_(button, 'buttonHover'); + menu.style.top = (button.offsetTop + button.offsetHeight) + 'px'; + menu.style.left = button.offsetLeft + 'px'; + menu.style.display = 'block'; + window.setTimeout(function() { + Maze.pegmanMenuMouse_ = Blockly.bindEvent_(document.body, 'mousedown', + null, Maze.hidePegmanMenu); + }, 0); + // Close the skin-changing hint if open. + if (document.getElementById('dialogHelpSkins').className != + 'dialogHiddenContent') { + BlocklyApps.hideDialog(false); + } + Maze.showPegmanMenu.activatedOnce = true; +}; + +/** + * Hide the Pegman skin-change menu. + */ +Maze.hidePegmanMenu = function() { + document.getElementById('pegmanMenu').style.display = 'none'; + Blockly.removeClass_(document.getElementById('pegmanButton'), 'buttonHover'); + if (Maze.pegmanMenuMouse_) { + Blockly.unbindEvent_(Maze.pegmanMenuMouse_); + delete Maze.pegmanMenuMouse_; + } +}; + +/** + * Reset the maze to the start position and kill any pending animation tasks. + * @param {boolean} first True if an opening animation is to be played. + */ +Maze.reset = function(first) { + // Kill all tasks. + for (var x = 0; x < Maze.pidList.length; x++) { + window.clearTimeout(Maze.pidList[x]); + } + Maze.pidList = []; + + // Move Pegman into position. + Maze.pegmanX = Maze.start_.x; + Maze.pegmanY = Maze.start_.y; + + if (first) { + Maze.pegmanD = Maze.startDirection + 1; + Maze.scheduleFinish(false); + Maze.pidList.push(window.setTimeout(function() { + Maze.stepSpeed = 100; + Maze.schedule([Maze.pegmanX, Maze.pegmanY, Maze.pegmanD * 4], + [Maze.pegmanX, Maze.pegmanY, Maze.pegmanD * 4 - 4]); + Maze.pegmanD++; + }, Maze.stepSpeed * 5)); + } else { + Maze.pegmanD = Maze.startDirection; + Maze.displayPegman(Maze.pegmanX, Maze.pegmanY, Maze.pegmanD * 4); + } + + // Move the finish icon into position. + var finishIcon = document.getElementById('finish'); + finishIcon.setAttribute('x', Maze.SQUARE_SIZE * (Maze.finish_.x + 0.5) - + finishIcon.getAttribute('width') / 2); + finishIcon.setAttribute('y', Maze.SQUARE_SIZE * (Maze.finish_.y + 0.6) - + finishIcon.getAttribute('height')); + + // Make 'look' icon invisible and promote to top. + var lookIcon = document.getElementById('look'); + lookIcon.style.display = 'none'; + lookIcon.parentNode.appendChild(lookIcon); + var paths = lookIcon.getElementsByTagName('path'); + for (var i = 0, path; path = paths[i]; i++) { + path.setAttribute('stroke', Maze.SKIN.look); + } +}; + +/** + * Click the run button. Start the program. + */ +Maze.runButtonClick = function() { + BlocklyApps.hideDialog(false); + // Only allow a single top block on level 1. + if (Maze.LEVEL == 1 && Blockly.mainWorkspace.getTopBlocks().length > 1) { + return; + } + var runButton = document.getElementById('runButton'); + var resetButton = document.getElementById('resetButton'); + // Ensure that Reset button is at least as wide as Run button. + if (!resetButton.style.minWidth) { + resetButton.style.minWidth = runButton.offsetWidth + 'px'; + } + runButton.style.display = 'none'; + resetButton.style.display = 'inline'; + Blockly.mainWorkspace.traceOn(true); + Maze.reset(false); + Maze.execute(); +}; + +/** + * Updates the document's 'capacity' element with a message + * indicating how many more blocks are permitted. The capacity + * is retrieved from Blockly.mainWorkspace.remainingCapacity(). + */ +Maze.updateCapacity = function() { + var cap = Blockly.mainWorkspace.remainingCapacity(); + var p = document.getElementById('capacity'); + if (cap == Infinity) { + p.style.display = 'none'; + } else { + p.style.display = 'inline'; + p.innerHTML = ''; + cap = Number(cap); + var capSpan = document.createElement('span'); + capSpan.className = 'capacityNumber'; + capSpan.appendChild(document.createTextNode(cap)); + if (cap == 0) { + var msg = BlocklyApps.getMsg('Maze_capacity0'); + } else if (cap == 1) { + var msg = BlocklyApps.getMsg('Maze_capacity1'); + } else { + var msg = BlocklyApps.getMsg('Maze_capacity2'); + } + var parts = msg.split(/%\d/); + for (var i = 0; i < parts.length; i++) { + p.appendChild(document.createTextNode(parts[i])); + if (i != parts.length - 1) { + p.appendChild(capSpan.cloneNode(true)); + } + } + } +}; + +/** + * Click the reset button. Reset the maze. + */ +Maze.resetButtonClick = function() { + document.getElementById('runButton').style.display = 'inline'; + document.getElementById('resetButton').style.display = 'none'; + Blockly.mainWorkspace.traceOn(false); + Maze.reset(false); + Maze.levelHelp(); +}; + +/** + * Execute the user's code. Heaven help us... + */ +Maze.execute = function() { + BlocklyApps.log = []; + BlocklyApps.ticks = 1000; + var code = Blockly.JavaScript.workspaceToCode(); + Maze.result = Maze.ResultType.UNSET; + + // Try running the user's code. There are four possible outcomes: + // 1. If pegman reaches the finish [SUCCESS], true is thrown. + // 2. If the program is terminated due to running too long [TIMEOUT], + // false is thrown. + // 3. If another error occurs [ERROR], that error is thrown. + // 4. If the program ended normally but without solving the maze [FAILURE], + // no error or exception is thrown. + try { + eval(code); + Maze.result = Maze.ResultType.FAILURE; + } catch (e) { + // A boolean is thrown for normal termination. + // Abnormal termination is a user error. + if (e === Infinity) { + Maze.result = Maze.ResultType.TIMEOUT; + } else if (e === true) { + Maze.result = Maze.ResultType.SUCCESS; + } else if (e === false) { + Maze.result = Maze.ResultType.ERROR; + } else { + // Syntax error, can't happen. + Maze.result = Maze.ResultType.ERROR; + window.alert(e); + } + } + + // Fast animation if execution is successful. Slow otherwise. + Maze.stepSpeed = (Maze.result == Maze.ResultType.SUCCESS) ? 100 : 150; + + // BlocklyApps.log now contains a transcript of all the user's actions. + // Reset the maze and animate the transcript. + Maze.reset(false); + Maze.pidList.push(window.setTimeout(Maze.animate, 100)); +}; + +/** + * Iterate through the recorded path and animate pegman's actions. + */ +Maze.animate = function() { + // All tasks should be complete now. Clean up the PID list. + Maze.pidList = []; + + var action = BlocklyApps.log.shift(); + if (!action) { + BlocklyApps.highlight(null); + Maze.levelHelp(); + return; + } + BlocklyApps.highlight(action[1]); + + switch (action[0]) { + case 'north': + Maze.schedule([Maze.pegmanX, Maze.pegmanY, Maze.pegmanD * 4], + [Maze.pegmanX, Maze.pegmanY - 1, Maze.pegmanD * 4]); + Maze.pegmanY--; + break; + case 'east': + Maze.schedule([Maze.pegmanX, Maze.pegmanY, Maze.pegmanD * 4], + [Maze.pegmanX + 1, Maze.pegmanY, Maze.pegmanD * 4]); + Maze.pegmanX++; + break; + case 'south': + Maze.schedule([Maze.pegmanX, Maze.pegmanY, Maze.pegmanD * 4], + [Maze.pegmanX, Maze.pegmanY + 1, Maze.pegmanD * 4]); + Maze.pegmanY++; + break; + case 'west': + Maze.schedule([Maze.pegmanX, Maze.pegmanY, Maze.pegmanD * 4], + [Maze.pegmanX - 1, Maze.pegmanY, Maze.pegmanD * 4]); + Maze.pegmanX--; + break; + case 'look_north': + Maze.scheduleLook(Maze.DirectionType.NORTH); + break; + case 'look_east': + Maze.scheduleLook(Maze.DirectionType.EAST); + break; + case 'look_south': + Maze.scheduleLook(Maze.DirectionType.SOUTH); + break; + case 'look_west': + Maze.scheduleLook(Maze.DirectionType.WEST); + break; + case 'fail_forward': + Maze.scheduleFail(true); + break; + case 'fail_backward': + Maze.scheduleFail(false); + break; + case 'left': + Maze.schedule([Maze.pegmanX, Maze.pegmanY, Maze.pegmanD * 4], + [Maze.pegmanX, Maze.pegmanY, Maze.pegmanD * 4 - 4]); + Maze.pegmanD = Maze.constrainDirection4(Maze.pegmanD - 1); + break; + case 'right': + Maze.schedule([Maze.pegmanX, Maze.pegmanY, Maze.pegmanD * 4], + [Maze.pegmanX, Maze.pegmanY, Maze.pegmanD * 4 + 4]); + Maze.pegmanD = Maze.constrainDirection4(Maze.pegmanD + 1); + break; + case 'finish': + Maze.scheduleFinish(true); + window.setTimeout(Maze.congratulations, 1000); + } + + Maze.pidList.push(window.setTimeout(Maze.animate, Maze.stepSpeed * 5)); +}; + +/** + * Congratulates the user for completing the level and offers to + * direct them to the next level, if available. + */ +Maze.congratulations = function() { + var content = document.getElementById('dialogDone'); + var buttonDiv = document.getElementById('dialogDoneButtons'); + buttonDiv.textContent = ''; + var style = { + width: '40%', + left: '30%', + top: '5em' + }; + if (Maze.LEVEL < Maze.MAX_LEVEL) { + var text = BlocklyApps.getMsg('Maze_nextLevel') + .replace('%1', Maze.LEVEL + 1); + var cancel = document.createElement('button'); + cancel.appendChild( + document.createTextNode(BlocklyApps.getMsg('dialogCancel'))); + cancel.addEventListener('click', BlocklyApps.hideDialog, true); + cancel.addEventListener('touchend', BlocklyApps.hideDialog, true); + buttonDiv.appendChild(cancel); + + var ok = document.createElement('button'); + ok.className = 'secondary'; + ok.appendChild(document.createTextNode(BlocklyApps.getMsg('dialogOk'))); + ok.addEventListener('click', Maze.nextLevel, true); + ok.addEventListener('touchend', Maze.nextLevel, true); + buttonDiv.appendChild(ok); + + BlocklyApps.showDialog(content, null, false, true, style, + function() { + document.body.removeEventListener('keydown', + Maze.congratulationsKeyDown_, true); + }); + document.body.addEventListener('keydown', + Maze.congratulationsKeyDown_, true); + + } else { + var text = BlocklyApps.getMsg('Maze_finalLevel'); + var ok = document.createElement('button'); + ok.className = 'secondary'; + ok.addEventListener('click', BlocklyApps.hideDialog, true); + ok.addEventListener('touchend', BlocklyApps.hideDialog, true); + ok.appendChild(document.createTextNode(BlocklyApps.getMsg('dialogOk'))); + buttonDiv.appendChild(ok); + BlocklyApps.showDialog(content, null, false, true, style, + BlocklyApps.stopDialogKeyDown); + BlocklyApps.startDialogKeyDown(); + } + document.getElementById('dialogDoneText').textContent = text; + + var pegSpin = document.getElementById('pegSpin'); + pegSpin.style.backgroundImage = 'url(' + Maze.SKIN.sprite + ')'; +}; + +/** + * If the user preses enter, escape, or space, hide the dialog. + * Enter and space move to the next level, escape does not. + * @param {!Event} e Keyboard event. + * @private + */ +Maze.congratulationsKeyDown_ = function(e) { + if (e.keyCode == 13 || + e.keyCode == 27 || + e.keyCode == 32) { + BlocklyApps.hideDialog(true); + e.stopPropagation(); + e.preventDefault(); + if (e.keyCode != 27) { + Maze.nextLevel(); + } + } +}; + +/** + * Go to the next level. + */ +Maze.nextLevel = function() { + window.location = window.location.protocol + '//' + + window.location.host + window.location.pathname + + '?lang=' + BlocklyApps.LANG + '&level=' + (Maze.LEVEL + 1) + + '&skin=' + Maze.SKIN_ID; +}; + +/** + * Point the congratulations Pegman to face the mouse. + * @param {Event} e Mouse move event. + * @private + */ +Maze.updatePegSpin_ = function(e) { + if (document.getElementById('dialogDone').className == + 'dialogHiddenContent') { + return; + } + var pegSpin = document.getElementById('pegSpin'); + var bBox = BlocklyApps.getBBox_(pegSpin); + var x = bBox.x + bBox.width / 2 - window.scrollX; + var y = bBox.y + bBox.height / 2 - window.scrollY; + var dx = e.clientX - x; + var dy = e.clientY - y; + var angle = Math.atan(dy / dx); + // Convert from radians to degrees because I suck at math. + angle = angle / Math.PI * 180; + // 0: North, 90: East, 180: South, 270: West. + if (dx > 0) { + angle += 90; + } else { + angle += 270; + } + // Divide into 16 quads. + var quad = Math.round(angle / 360 * 16); + if (quad == 16) { + quad = 15; + } + // Display correct Pegman sprite. + pegSpin.style.backgroundPosition = (-quad * Maze.PEGMAN_WIDTH) + 'px 0px'; +}; + +/** + * Schedule the animations for a move or turn. + * @param {!Array.} startPos X, Y and direction starting points. + * @param {!Array.} endPos X, Y and direction ending points. + */ +Maze.schedule = function(startPos, endPos) { + var deltas = [(endPos[0] - startPos[0]) / 4, + (endPos[1] - startPos[1]) / 4, + (endPos[2] - startPos[2]) / 4]; + Maze.displayPegman(startPos[0] + deltas[0], + startPos[1] + deltas[1], + Maze.constrainDirection16(startPos[2] + deltas[2])); + Maze.pidList.push(window.setTimeout(function() { + Maze.displayPegman(startPos[0] + deltas[0] * 2, + startPos[1] + deltas[1] * 2, + Maze.constrainDirection16(startPos[2] + deltas[2] * 2)); + }, Maze.stepSpeed)); + Maze.pidList.push(window.setTimeout(function() { + Maze.displayPegman(startPos[0] + deltas[0] * 3, + startPos[1] + deltas[1] * 3, + Maze.constrainDirection16(startPos[2] + deltas[2] * 3)); + }, Maze.stepSpeed * 2)); + Maze.pidList.push(window.setTimeout(function() { + Maze.displayPegman(endPos[0], endPos[1], + Maze.constrainDirection16(endPos[2])); + }, Maze.stepSpeed * 3)); +}; + +/** + * Schedule the animations and sounds for a failed move. + * @param {boolean} forward True if forward, false if backward. + */ +Maze.scheduleFail = function(forward) { + var deltaX = 0; + var deltaY = 0; + switch (Maze.pegmanD) { + case Maze.DirectionType.NORTH: + deltaY = -0.25; + break; + case Maze.DirectionType.EAST: + deltaX = 0.25; + break; + case Maze.DirectionType.SOUTH: + deltaY = 0.25; + break; + case Maze.DirectionType.WEST: + deltaX = -0.25; + break; + } + if (!forward) { + deltaX = -deltaX; + deltaY = -deltaY; + } + var direction16 = Maze.constrainDirection16(Maze.pegmanD * 4); + Maze.displayPegman(Maze.pegmanX + deltaX, + Maze.pegmanY + deltaY, + direction16); + Blockly.playAudio('whack', .5); + Maze.pidList.push(window.setTimeout(function() { + Maze.displayPegman(Maze.pegmanX, + Maze.pegmanY, + direction16); + }, Maze.stepSpeed)); + Maze.pidList.push(window.setTimeout(function() { + Maze.displayPegman(Maze.pegmanX + deltaX, + Maze.pegmanY + deltaY, + direction16); + Blockly.playAudio('whack', .5); + }, Maze.stepSpeed * 2)); + Maze.pidList.push(window.setTimeout(function() { + Maze.displayPegman(Maze.pegmanX, Maze.pegmanY, direction16); + }, Maze.stepSpeed * 3)); +}; + +/** + * Schedule the animations and sound for a victory dance. + * @param {boolean} sound Play the victory sound. + */ +Maze.scheduleFinish = function(sound) { + var direction16 = Maze.constrainDirection16(Maze.pegmanD * 4); + Maze.displayPegman(Maze.pegmanX, Maze.pegmanY, 16); + if (sound) { + Blockly.playAudio('win', .5); + } + Maze.stepSpeed = 150; // Slow down victory animation a bit. + Maze.pidList.push(window.setTimeout(function() { + Maze.displayPegman(Maze.pegmanX, Maze.pegmanY, 18); + }, Maze.stepSpeed)); + Maze.pidList.push(window.setTimeout(function() { + Maze.displayPegman(Maze.pegmanX, Maze.pegmanY, 16); + }, Maze.stepSpeed * 2)); + Maze.pidList.push(window.setTimeout(function() { + Maze.displayPegman(Maze.pegmanX, Maze.pegmanY, direction16); + }, Maze.stepSpeed * 3)); +}; + +/** + * Display Pegman at the specified location, facing the specified direction. + * @param {number} x Horizontal grid (or fraction thereof). + * @param {number} y Vertical grid (or fraction thereof). + * @param {number} d Direction (0 - 15) or dance (16 - 17). + */ +Maze.displayPegman = function(x, y, d) { + var pegmanIcon = document.getElementById('pegman'); + pegmanIcon.setAttribute('x', + x * Maze.SQUARE_SIZE - d * Maze.PEGMAN_WIDTH + 1); + pegmanIcon.setAttribute('y', + Maze.SQUARE_SIZE * (y + 0.5) - Maze.PEGMAN_HEIGHT / 2 - 8); + + var clipRect = document.getElementById('clipRect'); + clipRect.setAttribute('x', x * Maze.SQUARE_SIZE + 1); + clipRect.setAttribute('y', pegmanIcon.getAttribute('y')); +}; + +/** + * Display the look icon at Pegman's current location, + * in the specified direction. + * @param {!Maze.DirectionType} d Direction (0 - 3). + */ +Maze.scheduleLook = function(d) { + var x = Maze.pegmanX; + var y = Maze.pegmanY; + switch (d) { + case Maze.DirectionType.NORTH: + x += 0.5; + break; + case Maze.DirectionType.EAST: + x += 1; + y += 0.5; + break; + case Maze.DirectionType.SOUTH: + x += 0.5; + y += 1; + break; + case Maze.DirectionType.WEST: + y += 0.5; + break; + } + x *= Maze.SQUARE_SIZE; + y *= Maze.SQUARE_SIZE; + d = d * 90 - 45; + + var lookIcon = document.getElementById('look'); + lookIcon.setAttribute('transform', + 'translate(' + x + ', ' + y + ') ' + + 'rotate(' + d + ' 0 0) scale(.4)'); + var paths = lookIcon.getElementsByTagName('path'); + lookIcon.style.display = 'inline'; + for (var x = 0, path; path = paths[x]; x++) { + Maze.scheduleLookStep(path, Maze.stepSpeed * x); + } +}; + +/** + * Schedule one of the 'look' icon's waves to appear, then disappear. + * @param {!Element} path Element to make appear. + * @param {number} delay Milliseconds to wait before making wave appear. + */ +Maze.scheduleLookStep = function(path, delay) { + Maze.pidList.push(window.setTimeout(function() { + path.style.display = 'inline'; + window.setTimeout(function() { + path.style.display = 'none'; + }, Maze.stepSpeed * 2); + }, delay)); +}; + +/** + * Keep the direction within 0-3, wrapping at both ends. + * @param {number} d Potentially out-of-bounds direction value. + * @return {number} Legal direction value. + */ +Maze.constrainDirection4 = function(d) { + if (d < 0) { + d += 4; + } else if (d > 3) { + d -= 4; + } + return d; +}; + +/** + * Keep the direction within 0-15, wrapping at both ends. + * @param {number} d Potentially out-of-bounds direction value. + * @return {number} Legal direction value. + */ +Maze.constrainDirection16 = function(d) { + if (d < 0) { + d += 16; + } else if (d > 15) { + d -= 16; + } + return d; +}; + +// API +// Human-readable aliases. + +Maze.moveForward = function(id) { + Maze.move(0, id); +}; + +Maze.moveBackward = function(id) { + Maze.move(2, id); +}; + +Maze.turnLeft = function(id) { + Maze.turn(0, id); +}; + +Maze.turnRight = function(id) { + Maze.turn(1, id); +}; + +Maze.isPathForward = function(id) { + return Maze.isPath(0, id); +}; + +Maze.isPathRight = function(id) { + return Maze.isPath(1, id); +}; + +Maze.isPathBackward = function(id) { + return Maze.isPath(2, id); +}; + +Maze.isPathLeft = function(id) { + return Maze.isPath(3, id); +}; + +// Core functions. + +/** + * Attempt to move pegman forward or backward. + * @param {number} direction Direction to move (0 = forward, 2 = backward). + * @param {string} id ID of block that triggered this action. + * @throws {true} If the end of the maze is reached. + * @throws {false} If Pegman collides with a wall. + */ +Maze.move = function(direction, id) { + if (!Maze.isPath(direction, null)) { + BlocklyApps.log.push(['fail_' + (direction ? 'backward' : 'forward'), id]); + throw false; + } + // If moving backward, flip the effective direction. + var effectiveDirection = Maze.pegmanD + direction; + var command; + switch (Maze.constrainDirection4(effectiveDirection)) { + case Maze.DirectionType.NORTH: + Maze.pegmanY--; + command = 'north'; + break; + case Maze.DirectionType.EAST: + Maze.pegmanX++; + command = 'east'; + break; + case Maze.DirectionType.SOUTH: + Maze.pegmanY++; + command = 'south'; + break; + case Maze.DirectionType.WEST: + Maze.pegmanX--; + command = 'west'; + break; + } + BlocklyApps.log.push([command, id]); + if (Maze.pegmanX == Maze.finish_.x && Maze.pegmanY == Maze.finish_.y) { + // Finished. Terminate the user's program. + BlocklyApps.log.push(['finish', null]); + throw true; + } +}; + +/** + * Turn pegman left or right. + * @param {number} direction Direction to turn (0 = left, 1 = right). + * @param {string} id ID of block that triggered this action. + */ +Maze.turn = function(direction, id) { + if (direction) { + // Right turn (clockwise). + Maze.pegmanD++; + BlocklyApps.log.push(['right', id]); + } else { + // Left turn (counterclockwise). + Maze.pegmanD--; + BlocklyApps.log.push(['left', id]); + } + Maze.pegmanD = Maze.constrainDirection4(Maze.pegmanD); +}; + +/** + * Is there a path next to pegman? + * @param {number} direction Direction to look + * (0 = forward, 1 = right, 2 = backward, 3 = left). + * @param {?string} id ID of block that triggered this action. + * Null if called as a helper function in Maze.move(). + * @return {boolean} True if there is a path. + */ +Maze.isPath = function(direction, id) { + var effectiveDirection = Maze.pegmanD + direction; + var square; + var command; + switch (Maze.constrainDirection4(effectiveDirection)) { + case Maze.DirectionType.NORTH: + square = Maze.map[Maze.pegmanY - 1] && + Maze.map[Maze.pegmanY - 1][Maze.pegmanX]; + command = 'look_north'; + break; + case Maze.DirectionType.EAST: + square = Maze.map[Maze.pegmanY][Maze.pegmanX + 1]; + command = 'look_east'; + break; + case Maze.DirectionType.SOUTH: + square = Maze.map[Maze.pegmanY + 1] && + Maze.map[Maze.pegmanY + 1][Maze.pegmanX]; + command = 'look_south'; + break; + case Maze.DirectionType.WEST: + square = Maze.map[Maze.pegmanY][Maze.pegmanX - 1]; + command = 'look_west'; + break; + } + if (id) { + BlocklyApps.log.push([command, id]); + } + return square !== Maze.SquareType.WALL && square !== undefined; +}; diff --git a/apps/maze/panda.png b/apps/maze/panda.png new file mode 100644 index 000000000..a90d68ae8 Binary files /dev/null and b/apps/maze/panda.png differ diff --git a/apps/maze/pegman.png b/apps/maze/pegman.png new file mode 100644 index 000000000..bcd09ad22 Binary files /dev/null and b/apps/maze/pegman.png differ diff --git a/apps/maze/readonly.html b/apps/maze/readonly.html new file mode 100644 index 000000000..6c541b514 --- /dev/null +++ b/apps/maze/readonly.html @@ -0,0 +1,36 @@ + + + + + + Blockly : Maze Readonly + + + + + + + + + diff --git a/apps/maze/sources/bamboo.xcf b/apps/maze/sources/bamboo.xcf new file mode 100644 index 000000000..52c0a8c9f Binary files /dev/null and b/apps/maze/sources/bamboo.xcf differ diff --git a/apps/maze/sources/readme.txt b/apps/maze/sources/readme.txt new file mode 100644 index 000000000..c81ceb832 --- /dev/null +++ b/apps/maze/sources/readme.txt @@ -0,0 +1,25 @@ +This directory contains sources for the images used in the Maze app. These +files are not required to run the maze, but they are required if one wants +to modify the graphics. + +Pegman: +* tiles_pegman.xcf -- A Gimp file containing layers for the road, buildings, +their shadows, and a grid. + +Astronaut: +* space_station.pov -- A POV-Ray 3.6 file that renders 3D sprites for the +space station modules. Runs as an animation where 'clock' starts at 1 and +increments to 15. +* tiles_astro.xcf -- A Gimp file containing all the 3D sprites as layers. +This graphic needs to be brightend, shrunk, and sharpened for use. + +Panda: +* bamboo.xcf -- A Gimp file containing the slices needed to create all 15 +permutations of the bamboo road. Original graphics created with: +http://www.ignorancia.org/en/index.php?page=bamboo +(Jaime Vives Piqueres, Creative Commons, Attribution-ShareAlike) +* tiles_panda.xcf -- A Gimp file containing all the bamboo sprites as layers. +This graphic needs to be shrunk for use. + +The avatars' sprites are from Google Maps. Googlers can check: +//depot/google3/googledata/html/external_content/maps_gstatic_com/mapfiles/cb diff --git a/apps/maze/sources/space_station.pov b/apps/maze/sources/space_station.pov new file mode 100755 index 000000000..63d32c130 --- /dev/null +++ b/apps/maze/sources/space_station.pov @@ -0,0 +1 @@ +#include "colors.inc" // Toggle to generate all 16 states. #declare north = (clock >= 8); #declare binary1 = mod(clock, 8); #declare east = (binary1 >= 4); #declare binary2 = mod(binary1, 4); #declare south = (binary2 >= 2); #declare binary3 = mod(binary2, 2); #declare west = binary3; #declare seed1 = seed(north * 1 + east * 2 + south * 4 + west * 8); // Camera's angle (zoom) to keep everything in view. #declare camera_angle = 30; // How far back is the camera, drags the lights along with it. #declare camera_back = 50; #declare colour1 = color rgb <1, 1, 1>; // modules #declare colour2 = color rgb <0.8, 0.8, 0.85>; // tunnels #declare colour3 = color rgb <0.7, 0.7, 0.75>; // boxes #declare hex1 = 4; #declare hex2 = 1; #if (north) // North cylinder { // module <0, 0, 0>, <0, 11, 0>, 5 texture {pigment { colour1 }} normal { wrinkles 0.2 scale .1 } } cylinder { // tunnel <0, 0, 0>, <0, 20, 0>, 3 texture {pigment { colour2 }} normal { wrinkles 0.2 scale .1 } } text { ttf "cyrvetic.ttf" str(rand(seed1)*100, -2, 0) .5, 0 pigment { Black } scale 2 translate -1*x translate -0.7*y translate -5*z rotate 90*z translate 8*y } box { <-hex1, 0, -hex2>, texture {pigment { colour3 }} normal { wrinkles 0.2 scale .1 } } box { <-hex1, 0, -hex2>, texture {pigment { colour3 }} normal { wrinkles 0.2 scale .1 } rotate <0, 60, 0> } box { <-hex1, 0, -hex2>, texture {pigment { colour3 }} normal { wrinkles 0.2 scale .1 } rotate <0, -60, 0> } #end #if (east) // East cylinder { // module <0, 0, 0>, <11, 0, 0>, 5 texture {pigment { colour1 }} normal { wrinkles 0.2 scale .1 } } cylinder { // tunnel <0, 0, 0>, <20, 0, 0>, 3 texture {pigment { colour2 }} normal { wrinkles 0.2 scale .1 } } text { ttf "cyrvetic.ttf" str(rand(seed1)*100, -2, 0) .5, 0 pigment { Black } scale 2 translate -1*x translate -0.7*y translate -5*z rotate 0*z translate 8*x } box { <0, -hex1, -hex2>, <12, hex1, hex2> texture {pigment { colour3 }} normal { wrinkles 0.2 scale .1 } } box { <0, -hex1, -hex2>, <12, hex1, hex2> texture {pigment { colour3 }} normal { wrinkles 0.2 scale .1 } rotate <60, 0, 0> } box { <0, -hex1, -hex2>, <12, hex1, hex2> texture {pigment { colour3 }} normal { wrinkles 0.2 scale .1 } rotate <-60, 0, 0> } #end #if (south) // South cylinder { // module <0, 0, 0>, <0, -11, 0>, 5 texture {pigment { colour1 }} normal { wrinkles 0.2 scale .1 } } cylinder { // tunnel <0, 0, 0>, <0, -20, 0>, 3 texture {pigment { colour2 }} normal { wrinkles 0.2 scale .1 } } text { ttf "cyrvetic.ttf" str(rand(seed1)*100, -2, 0) .5, 0 pigment { Black } scale 2 translate -1*x translate -0.7*y translate -5*z rotate -90*z translate -8*y } box { <-hex1, 0, -hex2>, texture {pigment { colour3 }} normal { wrinkles 0.2 scale .1 } } box { <-hex1, 0, -hex2>, texture {pigment { colour3 }} normal { wrinkles 0.2 scale .1 } rotate <0, 60, 0> } box { <-hex1, 0, -hex2>, texture {pigment { colour3 }} normal { wrinkles 0.2 scale .1 } rotate <0, -60, 0> } #end #if (west) // West cylinder { // module <0, 0, 0>, <-11, 0, 0>, 5 texture {pigment { colour1 }} normal { wrinkles 0.2 scale .1 } } cylinder { // tunnel <0, 0, 0>, <-20, 0, 0>, 3 texture {pigment { colour2 }} normal { wrinkles 0.2 scale .1 } } text { ttf "cyrvetic.ttf" str(rand(seed1)*100, -2, 0) .5, 0 pigment { Black } scale 2 translate -1*x translate -.7*y translate -5*z rotate 180*z translate -8*x } box { <0, -hex1, -hex2>, <-12, hex1, hex2> texture {pigment { colour3 }} normal { wrinkles 0.2 scale .1 } } box { <0, -hex1, -hex2>, <-12, hex1, hex2> texture {pigment { colour3 }} normal { wrinkles 0.2 scale .1 } rotate <60, 0, 0> } box { <0, -hex1, -hex2>, <-12, hex1, hex2> texture {pigment { colour3 }} normal { wrinkles 0.2 scale .1 } rotate <-60, 0, 0> } #end #declare paths = north + east + south + west; #if (paths = 1) // Dead end. sphere { <0, 0, 0>, 8 texture {pigment { colour1 }} normal { wrinkles 0.2 scale .1 } } #else #if (paths != 0) sphere { <0, 0, 0>, 5 texture {pigment { colour1 }} normal { wrinkles 0.2 scale .1 } } #end #end // Look from slightly below. camera { orthographic location <0, -camera_back/5, -camera_back> look_at <0, 0, 0> angle camera_angle right .58 // Aspect ratio } // Sunlight. light_source { <-camera_back/2, -camera_back/2, -camera_back*2> color White parallel point_at <0,0,0> } \ No newline at end of file diff --git a/apps/maze/sources/tiles_astro.xcf b/apps/maze/sources/tiles_astro.xcf new file mode 100644 index 000000000..94b15a53c Binary files /dev/null and b/apps/maze/sources/tiles_astro.xcf differ diff --git a/apps/maze/sources/tiles_panda.xcf b/apps/maze/sources/tiles_panda.xcf new file mode 100644 index 000000000..94f08507d Binary files /dev/null and b/apps/maze/sources/tiles_panda.xcf differ diff --git a/apps/maze/sources/tiles_pegman.xcf b/apps/maze/sources/tiles_pegman.xcf new file mode 100644 index 000000000..32a685c13 Binary files /dev/null and b/apps/maze/sources/tiles_pegman.xcf differ diff --git a/apps/maze/style.css b/apps/maze/style.css new file mode 100644 index 000000000..4849db3a0 --- /dev/null +++ b/apps/maze/style.css @@ -0,0 +1,178 @@ +.tab { + padding: 6px 12px; + text-decoration: none; + color: #000; +} +#selected { + font-weight: bold; + background-color: #ddd; + border-radius: 20px; +} +#blockly { + position: fixed; + bottom: 10px; +} +#visualization { + position: relative; +} +#capacityBubble { + position: absolute; + margin-top: -0.5em; + left: 10px; + top: 375px; + width: 380px; +} +html[dir="RTL"] #capacityBubble { + left: auto; + right: 10px; +} +#capacity { + display: none; + color: #fff; + padding: 5px 1em; + border-radius: 15px; + background-color: rgba(64,64,64,0.7); + font-size: large; +} +.capacityNumber { + font-weight: bold; +} +#containerCode { + direction: ltr; + font-size: large; + overflow: auto; + max-height: 400px; +} +#iframeOneTopBlock { + height: 100px; + width: 100%; + border: none; +} +#pegSpin { + height: 50px; + width: 49px; + background-position: -343px 0px; + margin-top: 10px; + position: absolute; +} +html[dir="RTL"] #pegSpin { + background-position: -441px 0px; +} + +img[src$="help.png"] { + height: 64px; + width: 64px; +} +html[dir="RTL"] .mirrorImg { + transform: scaleX(-1); + -moz-transform: scaleX(-1); + -webkit-transform: scaleX(-1); + -o-transform: scaleX(-1); + -ms-transform: scaleX(-1); +} +.helpMenuFake { + border-radius: 4px; + background-color: #bfcdde; + color: #000; + padding: 0 1ex; + cursor: default; +} +img[src$="help_up.png"] { + margin: -20px 10px 0; + height: 64px; + width: 23px; +} +img[src$="help_down.png"] { + margin: 0 10px -20px; + height: 64px; + width: 23px; +} + +/* 'Look' icon */ +#look>path { + display: none; + fill: none; + stroke-width: 10; + stroke-linecap: round; + stroke-opacity: 0.7; +} + +/* Buttons */ +button.primary { + /* Can't use "text-align: start" due to IE. */ + text-align: left; +} +html[dir="RTL"] button.primary { + text-align: right; +} +#languageMenu { + vertical-align: top; + margin-top: 12px; +} + +/* Sprited icons. */ +.icon21 { + height: 21px; + width: 21px; + background-image: url(icons.png); +} +.code { + background-position: -21px 0px; +} +.link { + background-position: 0px 0px; +} +.run { + background-position: 0px -21px; +} +.stop { + background-position: -21px -21px; +} + +#pegmanButton { + padding: 0; + margin: 0 5px; + position: relative; + font-size: large; +} +#pegmanButton:active { + border: 1px solid #ddd !important; +} +#pegmanButton>img { + margin-left: -0.5ex; + margin-right: 0.5ex; + height: 38px; + width: 49px; + background-position: -980px 0px; + opacity: 0.8; +} +html[dir="RTL"] #pegmanButton>img { + margin-left: 0.5ex; + margin-right: -0.5ex; +} +#pegmanButton>span { + position: absolute; + top: 0.8ex; + margin-left: -15px; +} +html[dir="RTL"] #pegmanButton>span { + margin-right: -15px; +} +#pegmanMenu { + border: 1px solid #ddd; + border-radius: 5px; + box-shadow: 2px 2px 5px #888; + display: none; + position: absolute; +} +#pegmanMenu>div { + background-color: #fff; +} +#pegmanMenu>div:hover { + background-color: #57e; +} +#pegmanMenu>div>img { + height: 38px; + width: 49px; + background-position: -980px 0px; +} diff --git a/apps/maze/template.soy b/apps/maze/template.soy new file mode 100644 index 000000000..c68f945ec --- /dev/null +++ b/apps/maze/template.soy @@ -0,0 +1,277 @@ +{namespace mazepage} + +/** + * This is a Closure Template. + * + * To regenerate just en.js, run this command: + * java -jar ../_soy/SoyToJsSrcCompiler.jar --outputPathFormat generated/en.js --srcs ../common.soy,template.soy + * + * To regenerate all files, see: trunk/apps/template.soy. + */ + +/** + * Translated messages for use in JavaScript. + */ +{template .messages} + {call apps.messages /} +
    + {msg meaning="Maze.moveForward" desc="block text - Imperative or infinitive of a verb for a person moving (walking) in the direction he/she is facing."}move forward{/msg} + {msg meaning="Maze.turnLeft" desc="[[Translating:Blockly#Drop-Down_Menus dropdown]] - Imperative or infinitive of a verb for a person turning his head and body one quarter rotation counter-clockwise. Prefer a translation that has text in common with the translation of 'turn right'. See [[Translating:Blockly#Drop-Down_Menus]]."}turn left{/msg} + {msg meaning="Maze.turnRight" desc="[[Translating:Blockly#Drop-Down_Menus dropdown]] - Imperative or infinitive of a verb for a person turning his head and body one quarter rotation clockwise. Prefer a translation that has text in common with the translation of 'turn left'. See [[Translating:Blockly#Drop-Down_Menus]]."}turn right{/msg} + {msg meaning="Maze.doCode" desc="block text - Imperative or infinitive of a verb preceding one or more commands to a person. This is part of [https://code.google.com/p/blockly/wiki/Loops#repeat repeat] and [https://code.google.com/p/blockly/wiki/IfElse#If_blocks if] blocks."}do{/msg} + {msg meaning="Maze.elseCode" desc="block text - Conjunction meaning 'otherwise', introducing commands to be performed if a previous condition was not true, as in 'if x\u003E3, do this, else do that'. See [https://code.google.com/p/blockly/wiki/IfElse#If-Else_blocks]."}else{/msg} + // This definition was copied up here ahead of when it is needed so that it is adjacent + // to the previous definition. + {msg meaning="Maze.helpIfElse" desc="callout - This is shown when the 'if-else' block is introduced. For 'if-else' concatenate the words for 'if' and 'else/otherwise'."}If-else blocks will do one thing or the other.{/msg} + {msg meaning="Maze.pathAhead" desc="[[Translating:Blockly#Drop-Down_Menus dropdown]] - Condensed form of 'if there is a path ahead', as in: 'if path ahead, go forward'. Prefer translation that has text in common with 'if path to the left' and 'if path to the right'."}if path ahead{/msg} + {msg meaning="Maze.pathLeft" desc="[[Translating:Blockly#Drop-Down_Menus dropdown]] - Condensed form of 'if there is a path to the left', as in: 'if path to the left, turn left'."}if path to the left{/msg} + {msg meaning="Maze.pathRight" desc="[[Translating:Blockly#Drop-Down_Menus dropdown]] - Condensed form of 'if there is a path to the right', as in: 'if path to the right, turn right'."}if path to the right{/msg} + {{msg meaning="Maze.repeatUntil" desc="block text - Imperative or infinitive of a verb to repeat the following commands. The phrase is followed by the symbol denoting the end of the maze.\n\nSee also:\n* {lb}{lb}msg-blockly|Maze.helpRepeatMany{rb}{rb}."}}repeat until{{/msg}} + {msg meaning="Maze.moveForwardTooltip" desc="tooltip - Moves the icon on the screen representing the player forward one square on the maze board."}Moves the player forward one space.{/msg} + {msg meaning="Maze.turnTooltip" desc="tooltip - Turns the icon on the screen representing the player 90 degrees counter-clockwise (left) or clockwise (right)."}Turns the player left or right by 90 degrees.{/msg} + {msg meaning="Maze.ifTooltip" desc="tooltip - 'path' refers to a path through a maze."}If there is a path in the specified direction, then do some actions.{/msg} + {msg meaning="Maze.ifelseTooltip" desc="tooltip - 'path' refers to a path through a maze."}If there is a path in the specified direction, then do the first block of actions. Otherwise, do the second block of actions.{/msg} + {msg meaning="Maze.whileTooltip" desc="tooltip - Repeat the enclosed commands until the maze has been successfully completed (the end point reached)."}Repeat the enclosed actions until finish point is reached.{/msg} + {msg meaning="Maze.capacity0" desc="warning - No more blocks may be added until some are removed. Please include '%0' in the translated string. It will be replaced with '0' and made bold."}You have %0 blocks left.{/msg} + {{msg meaning="Maze.capacity1" desc="warning - Only one more block may be added. Please include '%1' in the translated string. It will be replaced with '1' and made bold.\n\nSee also:\n* {lb}{lb}msg-blockly|Maze.capacity2{rb}{rb}"}}You have %1 block left.{{/msg}} + {{msg meaning="Maze.capacity2" desc="warning - Only %2 more blocks may be used, where %2 is an integer greater than 1.\n\nSee also:\n* {lb}{lb}msg-blockly|Maze.capacity1{rb}{rb}"}}You have %2 blocks left.{{/msg}} + {msg meaning="Maze.nextLevel" desc="alert - This is displayed when the user solves the maze, inviting them to precede to the next level of difficulty.\n\nParameters:\n* %1 - the number of the next level, which is always an integer greater than 1."}Congratulations! Are you ready to proceed to level %1?{/msg} + {msg meaning="Maze.finalLevel" desc="alert - This is displayed when the user solves the most difficult level."}Congratulations! You have solved the final level.{/msg} +
    +{/template} + +/** + * Web page structure. + */ +{template .start} + {call .messages /} + + + + + +
    +

    + + {msg meaning="Apps.blocklyMessage" desc="IBID"}Blockly{/msg} + {sp}:{sp} + {msg meaning="Maze.maze" desc="title - Specifies that this is Blockly's '''Maze''' tutorial."} + Maze + {/msg} + + {sp} {sp} + {for $i in range(1, 11)} + {sp} + {if $i == $ij.level} + {$i} + {else} + {if $i < $ij.level} + + {else} + {$i} + {/if} + {/if} + {/for} +

    +
    + + {sp} {sp} + +
    + +
    + + + + + + + +
    +
    +
    +
    + + + + + + +
    + + + + + +
    + + + + + + {call .toolbox /} +
    + + ⟲⟳ + + +
    + + {call apps.dialog /} + {call apps.codeDialog /} + {call apps.storageDialog /} +
    +
    + +
    +
    +
    +
    + +   + {{msg meaning="Maze.helpStack" desc="callout - The words for 'stack' and 'blocks' should be the same as for stacking children's blocks. Use the imperative verb form appropriate for speaking to a child, gender unspecified. If no gender-neutral singular/familiar form exists but a gender-neutral plural/formal form exists, use that instead. Be sure to use the same translation of 'move forward' as above.\n\n'move forward' refers to {lb}{lb}msg-blockly|Maze.moveForward{rb}{rb}."}}Stack a couple of 'move forward' blocks together to help me reach the goal.{{/msg}} + + +
    +
    +
    +
    + +   + {msg meaning="Maze.helpOneTopBlock" desc="callout - This is displayed if a user attempts to run a program composed of multiple stacks of blocks, letting them know they need to create a single stack."}On this level, you need to stack together all of the blocks in the white workspace.{/msg} + +
    +
    +
    +
    + {msg meaning="Maze.helpRun" desc="callout - This is shown after the user has created a program on the first level."}Run your program to see what happens.{/msg} + + +
    +
    +
    +
    +
    +
    + {{msg meaning="Maze.helpReset" desc="callout - This is shown after the user has run a program that does not solve the maze.\n\n'Reset' refers to {lb}{lb}msg-blockly|Apps.resetProgram{rb}{rb}."}}Your program didn't solve the maze. Press 'Reset' and try again.{{/msg}} + + +
    +
    +
    +
    +
    +
    + + + {msg meaning="Maze.helpRepeat" desc="callout - This is shown when the 'repeat' block is introduced. The word 'path' refers to a path through a maze, and 'block' refers to a child's building block."}Reach the end of this path using only two blocks. Use 'repeat' to run a block more than once.{/msg} + + +
    +
    +
    +
    + +   + {msg meaning="Maze.helpCapacity" desc="callout - This is shown after the user has used all the blocks permitted on this level."}You have used up all the blocks for this level. To create a new block, you first need to delete an existing block.{/msg} +
    +
    +
    +
    + + + {{msg meaning="Maze.helpRepeatMany" desc="callout - This is a hint that the user should place a second block inside of a 'repeat' block.\n\n'repeat' should be consistent with {lb}{lb}msg-blockly|Maze.repeatUntil{rb}{rb}."}}You can fit more than one block inside a 'repeat' block.{{/msg}} + + +
    +
    +
    +
    + + + {{msg meaning="Maze.helpSkins" desc="callout - This is a hint that the user can change the appearance of the player that moves within the maze."}}Choose your favourite player from this menu.{{/msg}} + + +
    +
    +
    +
    + + + {msg meaning="Maze.helpIf" desc="callout - This is shown when the 'if' block is introduced. An example of an 'if' block is: 'if there is a path to the left, turn left'."}An 'if' block will do something only if the condition is true. Try turning left if there is a path to the left.{/msg} + + +
    +
    +
    +
    + + + {msg meaning="Maze.helpMenu" desc="callout - %1 will be replaced with an image of the dropdown menu that the user needs to click."}Click on %1 in the 'if' block to change its condition.{/msg} + + +
    +
    +
    +
    + + + {msg meaning="Maze.helpIfElse" desc="IBID"}If-else blocks will do one thing or the other.{/msg} + + +
    +
    +
    +
    + +   + {msg meaning="Maze.helpWallFollow" desc="callout - This advises the user to solve a maze by keeping his/her left hand in contact with the wall while proceding through it. The final sentence is a warning that only advanced programmers should attempt this problem, as beginners tend to get frustrated."}Can you solve this complicated maze? Try following the left-hand wall. Advanced programmers only!{/msg} + {call apps.ok /} +
    +
    +{/template} + +/** + * Toolboxes for each level. + */ +{template .toolbox} + +{/template} + +/** + * Readonly Blockly in an iframe. + */ +{template .readonly} + {call .messages /} + + + + +
    +{/template} diff --git a/apps/maze/tiles_astro.png b/apps/maze/tiles_astro.png new file mode 100644 index 000000000..e21a19303 Binary files /dev/null and b/apps/maze/tiles_astro.png differ diff --git a/apps/maze/tiles_panda.png b/apps/maze/tiles_panda.png new file mode 100644 index 000000000..1e096b77e Binary files /dev/null and b/apps/maze/tiles_panda.png differ diff --git a/apps/maze/tiles_pegman.png b/apps/maze/tiles_pegman.png new file mode 100644 index 000000000..8ac9275f3 Binary files /dev/null and b/apps/maze/tiles_pegman.png differ diff --git a/apps/maze/title.png b/apps/maze/title.png new file mode 100644 index 000000000..1e6a26726 Binary files /dev/null and b/apps/maze/title.png differ diff --git a/apps/maze/whack.mp3 b/apps/maze/whack.mp3 new file mode 100644 index 000000000..cd8cc21fd Binary files /dev/null and b/apps/maze/whack.mp3 differ diff --git a/apps/maze/whack.ogg b/apps/maze/whack.ogg new file mode 100644 index 000000000..b4d58be87 Binary files /dev/null and b/apps/maze/whack.ogg differ diff --git a/apps/maze/win.mp3 b/apps/maze/win.mp3 new file mode 100644 index 000000000..cb1594a14 Binary files /dev/null and b/apps/maze/win.mp3 differ diff --git a/apps/maze/win.ogg b/apps/maze/win.ogg new file mode 100644 index 000000000..444757621 Binary files /dev/null and b/apps/maze/win.ogg differ diff --git a/apps/plane/blocks.js b/apps/plane/blocks.js new file mode 100644 index 000000000..165fa6741 --- /dev/null +++ b/apps/plane/blocks.js @@ -0,0 +1,105 @@ +/** + * Blockly Apps: Plane Seat Calculator Blocks + * + * Copyright 2013 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Blocks for Blockly's Plane Seat Calculator application. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +Blockly.Blocks['plane_set_seats'] = { + // Block seat variable setter. + init: function() { + this.setHelpUrl(Blockly.Msg.VARIABLES_SET_HELPURL); + this.setColour(330); + this.appendValueInput('VALUE') + .appendTitle(BlocklyApps.getMsg('Plane_setSeats')); + this.setTooltip(Blockly.Msg.VARIABLES_SET_TOOLTIP); + } +}; + +Blockly.JavaScript['plane_set_seats'] = function(block) { + // Generate JavaScript for seat variable setter. + var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE', + Blockly.JavaScript.ORDER_ASSIGNMENT) || 'NaN'; + return argument0 + ';'; +}; + +Blockly.Blocks['plane_get_rows'] = { + // Block for row variable getter. + init: function() { + this.setHelpUrl(Blockly.Msg.VARIABLES_GET_HELPURL); + this.setColour(330); + this.appendDummyInput() + .appendTitle(BlocklyApps.getMsg('Plane_getRows'), 'title'); + this.setOutput(true, 'Number'); + }, + customUpdate: function() { + this.setTitleValue( + BlocklyApps.getMsg('Plane_getRows').replace('%1', Plane.rows1st), + 'title'); + } +}; + +Blockly.JavaScript['plane_get_rows'] = function(block) { + // Generate JavaScript for row variable getter. + return ['Plane.rows1st', Blockly.JavaScript.ORDER_MEMBER]; +}; + +Blockly.Blocks['plane_get_rows1st'] = { + // Block for first class row variable getter. + init: function() { + this.setHelpUrl(Blockly.Msg.VARIABLES_GET_HELPURL); + this.setColour(330); + this.appendDummyInput() + .appendTitle(BlocklyApps.getMsg('Plane_getRows1'), 'title'); + this.setOutput(true, 'Number'); + }, + customUpdate: function() { + this.setTitleValue( + BlocklyApps.getMsg('Plane_getRows1').replace('%1', Plane.rows1st), + 'title'); + } +}; + +Blockly.JavaScript['plane_get_rows1st'] = function(block) { + // Generate JavaScript for first class row variable getter. + return ['Plane.rows1st', Blockly.JavaScript.ORDER_MEMBER]; +}; + +Blockly.Blocks['plane_get_rows2nd'] = { + // Block for second class row variable getter. + init: function() { + this.setHelpUrl(Blockly.Msg.VARIABLES_GET_HELPURL); + this.setColour(330); + this.appendDummyInput() + .appendTitle(BlocklyApps.getMsg('Plane_getRows2'), 'title'); + this.setOutput(true, 'Number'); + }, + customUpdate: function() { + this.setTitleValue( + BlocklyApps.getMsg('Plane_getRows2').replace('%1', Plane.rows2nd), + 'title'); + } +}; + +Blockly.JavaScript['plane_get_rows2nd'] = function(block) { + // Generate JavaScript for second class row variable getter. + return ['Plane.rows2nd', Blockly.JavaScript.ORDER_MEMBER]; +}; diff --git a/apps/plane/generated/af.js b/apps/plane/generated/af.js new file mode 100644 index 000000000..11b498fdd --- /dev/null +++ b/apps/plane/generated/af.js @@ -0,0 +1,67 @@ +// This file was automatically generated from common.soy. +// Please don't edit this file by hand. + +if (typeof apps == 'undefined') { var apps = {}; } + + +apps.messages = function(opt_data, opt_ignored, opt_ijData) { + return '
    a visual programming environmentBlocklySee generated JavaScript code.Save and link to blocks.Run the program defined by the blocks in the workspace.Run ProgramResetOKCancelLogicLoopsMathTextListsColourVariablesProceduresThere was a problem with the request.Share your blocks with this link:\\n\\n%1Sorry, \'%1\' doesn\'t correspond with any saved program.Could not load your saved file. Perhaps it was created with a different version of Blockly?listtext
    '; +}; + + +apps.dialog = function(opt_data, opt_ignored, opt_ijData) { + return '
    '; +}; + + +apps.codeDialog = function(opt_data, opt_ignored, opt_ijData) { + return '
    ' + apps.ok(null, null, opt_ijData) + '
    '; +}; + + +apps.storageDialog = function(opt_data, opt_ignored, opt_ijData) { + return '
    ' + apps.ok(null, null, opt_ijData) + '
    '; +}; + + +apps.ok = function(opt_data, opt_ignored, opt_ijData) { + return '
    '; +}; + +; +// This file was automatically generated from template.soy. +// Please don't edit this file by hand. + +if (typeof planepage == 'undefined') { var planepage = {}; } + + +planepage.messages = function(opt_data, opt_ignored, opt_ijData) { + return apps.messages(null, null, opt_ijData) + '
    Rows: %1rows (%1)1st class rows: %11st class rows (%1)2nd class rows: %12nd class rows (%1)Seats: %1?seats =
    '; +}; + + +planepage.start = function(opt_data, opt_ignored, opt_ijData) { + var output = planepage.messages(null, null, opt_ijData) + '

    Blockly : Plane   '; + for (var i128 = 1; i128 < 4; i128++) { + output += ' ' + ((i128 == opt_ijData.level) ? '' + soy.$$escapeHtml(i128) + '' : (i128 < opt_ijData.level) ? '' : '' + soy.$$escapeHtml(i128) + ''); + } + output += '

    + + + + + + + diff --git a/apps/plane/plane.js b/apps/plane/plane.js new file mode 100644 index 000000000..7420567d2 --- /dev/null +++ b/apps/plane/plane.js @@ -0,0 +1,230 @@ +/** + * Blockly Apps: Plane Seat Calculator + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview JavaScript for Blockly's Plane Seat Calculator application. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +/** + * Create a namespace for the application. + */ +var Plane = {}; + +// Supported languages. +BlocklyApps.LANGUAGES = ['en', 'de', 'fa', 'hu', 'it', 'ru', 'uk', 'vi']; +BlocklyApps.LANG = BlocklyApps.getLang(); + +document.write('\n'); + +Plane.MAX_LEVEL = 3; +Plane.LEVEL = BlocklyApps.getNumberParamFromUrl('level', 1, Plane.MAX_LEVEL); + + +Plane.rows1st = 0; +Plane.rows2nd = 0; + +/** + * Redraw the rows when the slider has moved. + * @param {number} value New slider position. + */ +Plane.sliderChange = function(value) { + var newRows = Math.round(value * 410 / 20); + Plane.redraw(newRows); +}; + +/** + * Change the text of a label. + * @param {string} id ID of element to change. + * @param {string} text New text. + */ +Plane.setText = function(id, text) { + var el = document.getElementById(id); + while (el.firstChild) { + el.removeChild(el.firstChild); + } + el.appendChild(document.createTextNode(text)); +}; + +/** + * Display a checkmark or cross next to the answer. + * @param {?boolean} ok True for checkmark, false for cross, null for nothing. + */ +Plane.setCorrect = function(ok) { + var yes = document.getElementById('seatYes'); + var no = document.getElementById('seatNo'); + yes.style.display = 'none'; + no.style.display = 'none'; + if (ok === true) { + yes.style.display = 'block'; + } else if (ok === false) { + no.style.display = 'block'; + } +}; + +/** + * Initialize Blockly and the SVG plane. + */ +Plane.init = function() { + BlocklyApps.init(); + + var rtl = BlocklyApps.isRtl(); + var toolbox = document.getElementById('toolbox'); + Blockly.inject(document.getElementById('blockly'), + {path: '../../', + rtl: rtl, + toolbox: toolbox}); + + var defaultXml = + '' + + ' ' + + ' ' + + ''; + BlocklyApps.loadBlocks(defaultXml); + + Blockly.addChangeListener(Plane.recalculate); + + //window.onbeforeunload = function() { + // return 'Leaving this page will result in the loss of your work.'; + //}; + + // Initialize the slider. + var svg = document.getElementById('plane'); + Plane.rowSlider = new Slider(60, 330, 425, svg, Plane.sliderChange); + Plane.rowSlider.setValue(0.225); + + // Draw five 1st class rows. + Plane.redraw(5); +}; + +window.addEventListener('load', Plane.init); + +/** + * Use the blocks to calculate the number of seats. + * Display the calculated number. + */ +Plane.recalculate = function() { + // Find the 'set' block and use it as the formula root. + var rootBlock = null; + var blocks = Blockly.mainWorkspace.getTopBlocks(false); + for (var i = 0, block; block = blocks[i]; i++) { + if (block.type == 'plane_set_seats') { + rootBlock = block; + } + } + var seats = NaN; + Blockly.JavaScript.init(); + var code = Blockly.JavaScript.blockToCode(rootBlock); + try { + seats = eval(code); + } catch (e) { + // Allow seats to remain NaN. + } + Plane.setText('seatText', + BlocklyApps.getMsg('Plane_seats').replace( + '%1', isNaN(seats) ? '?' : seats)); + Plane.setCorrect(isNaN(seats) ? null : (Plane.answer() == seats)); + + // Update blocks to show values. + function updateBlocks(blocks) { + for (var i = 0, block; block = blocks[i]; i++) { + block.customUpdate && block.customUpdate(); + } + } + updateBlocks(Blockly.mainWorkspace.getAllBlocks()); + updateBlocks(Blockly.mainWorkspace.flyout_.workspace_.getAllBlocks()); +}; + +/** + * Calculate the correct answer. + * @return {number} Number of seats. + */ +Plane.answer = function() { + if (Plane.LEVEL == 1) { + return Plane.rows1st * 4; + } else if (Plane.LEVEL == 2) { + return 2 + (Plane.rows1st * 4); + } else if (Plane.LEVEL == 3) { + return 2 + (Plane.rows1st * 4) + (Plane.rows2nd * 5); + } + throw 'Unknown level.'; +}; + +/** + * Redraw the SVG to show a new number of rows. + * @param {number} newRows + */ +Plane.redraw = function(newRows) { + var rows1st = Plane.rows1st; + var rows2nd = Plane.rows2nd; + var svg = document.getElementById('plane'); + if (newRows != rows1st) { + while (newRows < rows1st) { + var row = document.getElementById('row1st' + rows1st); + row.parentNode.removeChild(row); + rows1st--; + } + while (newRows > rows1st) { + rows1st++; + var row = document.createElementNS('http://www.w3.org/2000/svg', + 'use'); + row.setAttribute('id', 'row1st' + rows1st); + // Row of 4 seats. + row.setAttribute('x', (rows1st - 1) * 20); + row.setAttributeNS('http://www.w3.org/1999/xlink', + 'xlink:href', '#row1st'); + svg.appendChild(row); + } + + if (Plane.LEVEL == 3) { + newRows = Math.floor((21 - newRows) * 1.11); + while (newRows < rows2nd) { + var row = document.getElementById('row2nd' + rows2nd); + row.parentNode.removeChild(row); + rows2nd--; + } + while (newRows > rows2nd) { + rows2nd++; + var row = document.createElementNS('http://www.w3.org/2000/svg', + 'use'); + row.setAttribute('id', 'row2nd' + rows2nd); + row.setAttribute('x', 400 - (rows2nd - 1) * 18); + row.setAttributeNS('http://www.w3.org/1999/xlink', + 'xlink:href', '#row2nd'); + svg.appendChild(row); + } + } + + if (Plane.LEVEL < 3) { + Plane.setText('row1stText', + BlocklyApps.getMsg('Plane_rows').replace('%1', rows1st)); + } else { + Plane.setText('row1stText', + BlocklyApps.getMsg('Plane_rows1').replace('%1', rows1st)); + Plane.setText('row2ndText', + BlocklyApps.getMsg('Plane_rows2').replace('%1', rows2nd)); + } + + Plane.rows1st = rows1st; + Plane.rows2nd = rows2nd; + Plane.recalculate(); + } +}; diff --git a/apps/plane/style.css b/apps/plane/style.css new file mode 100644 index 000000000..c8b8e94db --- /dev/null +++ b/apps/plane/style.css @@ -0,0 +1,64 @@ +.tab { + padding: 6px 12px; + text-decoration: none; + color: #000; +} +#selected { + font-weight: bold; + background-color: #ddd; + border-radius: 20px; +} + +#blockly { + height: 300px; + width: 100%; + border-style: solid; + border-color: #ddd; + border-width: 0 1px 1px 0; +} + +/* SVG Plane. */ +#fuselage { + fill: #fff; + stroke: #000; +} +#wing, #tail { + fill: #ddd; + stroke: #444; +} +.crew { + fill: #f44; + stroke: #000; +} +.seat1st { + fill: #88f; + stroke: #000; +} +.seat2nd { + fill: #8b8; + stroke: #000; +} +#seatYes, #seatNo { + font-size: 40pt; +} +text { + font-family: sans-serif; + font-size: 20pt; + fill: #444; +} + +/* Slider. */ +.sliderTrack { + stroke: #aaa; + stroke-width: 6px; + stroke-linecap: round; +} +.sliderKnob { + fill: #ddd; + stroke: #bbc; + stroke-width: 1px; + stroke-linejoin: round; +} +.sliderKnob:hover { + fill: #eee; +} diff --git a/apps/plane/template.soy b/apps/plane/template.soy new file mode 100644 index 000000000..29ed14499 --- /dev/null +++ b/apps/plane/template.soy @@ -0,0 +1,207 @@ +{namespace planepage} + +/** + * This is a Closure Template. + * + * To regenerate just en.js, run this command: + * java -jar ../_soy/SoyToJsSrcCompiler.jar --outputPathFormat generated/en.js --srcs ../common.soy,template.soy + * + * To regenerate all files, see: trunk/apps/template.soy. + */ + +/** + * Translated messages for use in JavaScript. + */ +{template .messages} + {call apps.messages /} +
    + {msg meaning="Plane.rows" desc="page text - Total number of rows of seats on an airplane.\n\nParameters:\n* %1 - number of rows of seats on an airplane. It is always an integer greater than or equal to zero."}Rows: %1{/msg} + {msg meaning="Plane.getRows" desc="block text - The number of rows on the airplane, to be used in a mathematical equation, such as: \u0026quot;seats = 4 x '''rows (5)'''\u0026quot;.\n\nParameters:\n* %1 - number of rows of seats on an airplane. It is always an integer greater than or equal to zero."}rows (%1){/msg} + {msg meaning="Plane.rows1" desc="page text - The number of rows of first-class seats on the airplane. You can see the block at [http://blockly-share.appspot.com/static/apps/plane/plane.html?lang=en\u0026level=3].\n\nParameters:\n* %1 - number of rows of first-class seats on an airplane. It is always an integer greater than or equal to zero."}1st class rows: %1{/msg} + {msg meaning="Plane.getRows1" desc="block text - The number of rows of first-class seats on the, to be used in a mathematical equation. See [http://blockly-share.appspot.com/static/apps/plane/plane.html?lang=en\u0026level=3].\n\nParameters:\n* %1 - number of rows of first-class seats on an airplane. It is always an integer greater than or equal to zero."}1st class rows (%1){/msg} + {msg meaning="Plane.rows2" desc="page text - The number of rows of second-class seats on the airplane. %1 is an integer greater or equal to zero. See [http://blockly-share.appspot.com/static/apps/plane/plane.html?lang=en\u0026level=3].\n\nParameters:\n* %1 - number of rows of second-class seats on an airplane. It is always an integer greater than or equal to zero."}2nd class rows: %1{/msg} + {msg meaning="Plane.getRows2" desc="block text - The number of rows of second-class (also called 'economy class') seats on the airplane, to be used in a mathematical expression.\n\nParameters:\n* %1 - number of rows of second-class seats on an airplane. It is always an integer greater than or equal to zero."}2nd class rows (%1){/msg} + {msg meaning="Plane.seats" desc="page text - The total number of seats on the airplane.\n\nParameters:\n* %1 - number of seats on an airplane. It is always either the next message or an integer greater than or equal to zero."}Seats: %1{/msg} + {msg meaning="Plane.placeholder" desc="page text - A word or symbol indicating that this numeric value has not yet been determined."}?{/msg} + {msg meaning="Plane.setSeats" desc="block text - The first half of a mathematical equation determining the number of seats in an airplane, such as: \u0026quot;'''seats =''' 4 x rows\u0026quot;."}seats ={/msg} +
    +{/template} + +/** + * Web page structure. + */ +{template .start} + {call .messages /} + + + + + +
    +

    + + {msg meaning="Apps.blocklyMessage" desc="IBID"}Blockly{/msg} + {sp}:{sp} + {msg meaning="Plane.plane" desc="title - Specifies that this is Blockly's '''Plane''' (airplane) tutorial. The word \u0026quot;plane\u0026quot; was chosen over \u0026quot;airplane\u0026quot; in English because it is shorter and less formal."} + Plane + {/msg} + + {sp} {sp} + {for $i in range(1, 4)} + {sp} + {if $i == $ij.level} + {$i} + {else} + {if $i < $ij.level} + + {else} + {$i} + {/if} + {/if} + {/for} +

    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {if $ij.level > 1} + + + {/if} + + +

    + {switch $ij.level} + {case 1} + {msg meaning="Plane.description1" desc="instructions - Note that in [http://blockly-share.appspot.com/static/apps/plane/plane.html?lang=en\u0026level=1 this level], there is only one type of seat on the plane."}An airplane has a number of rows of passenger seats. Each row contains four seats.{/msg} + {case 2} + {msg meaning="Plane.description2" desc="instructions - Note that in [http://blockly-share.appspot.com/static/apps/plane/plane.html?lang=en\u0026level=2 this level], there are two types of seats on this plane."}An airplane has two seats in the flight deck (for the pilot and co-pilot), and a number of rows of passenger seats. Each row contains four seats.{/msg} + {case 3} + {msg meaning="Plane.description3" desc="instructions - Note that in [http://blockly-share.appspot.com/static/apps/plane/plane.html?lang=en\u0026level=3 this level], there are three types of seats on this plane. Be sure to use the same terms for \u0026quot;1st class\u0026quot; and \u0026quot;2nd class\u0026quot; as you did for the earlier messages."}An airplane has two seats in the flight deck (for the pilot and co-pilot), and a number of rows of 1st class and 2nd class passenger seats. Each 1st class row contains four seats. Each 2nd class row contains five seats.{/msg} + {/switch} +

    +

    + {msg meaning="Plane.instructions" desc="page text - This text appears below the airplane graphic and above the space for the user to create the formula. The number of rows an the graphic may be changed by the user with a slider. See [http://blockly-share.appspot.com/static/apps/plane/plane.html?lang=en\u0026level=1] for a picture."}Build a formula (below) that calculates the total number of seats on the airplane as the rows are changed (above).{/msg} +

    + + + + + + + {call .toolbox /} +
    +{/template} + +/** + * Toolboxes for each level. + */ +{template .toolbox} + +{/template} diff --git a/apps/prettify.css b/apps/prettify.css new file mode 100644 index 000000000..d44b3a228 --- /dev/null +++ b/apps/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} \ No newline at end of file diff --git a/apps/prettify.js b/apps/prettify.js new file mode 100644 index 000000000..7b990496d --- /dev/null +++ b/apps/prettify.js @@ -0,0 +1,30 @@ +!function(){var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; +(function(){function S(a){function d(e){var b=e.charCodeAt(0);if(b!==92)return b;var a=e.charAt(1);return(b=r[a])?b:"0"<=a&&a<="7"?parseInt(e.substring(1),8):a==="u"||a==="x"?parseInt(e.substring(2),16):e.charCodeAt(1)}function g(e){if(e<32)return(e<16?"\\x0":"\\x")+e.toString(16);e=String.fromCharCode(e);return e==="\\"||e==="-"||e==="]"||e==="^"?"\\"+e:e}function b(e){var b=e.substring(1,e.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),e=[],a= +b[0]==="^",c=["["];a&&c.push("^");for(var a=a?1:0,f=b.length;a122||(l<65||h>90||e.push([Math.max(65,h)|32,Math.min(l,90)|32]),l<97||h>122||e.push([Math.max(97,h)&-33,Math.min(l,122)&-33]))}}e.sort(function(e,a){return e[0]-a[0]||a[1]-e[1]});b=[];f=[];for(a=0;ah[0]&&(h[1]+1>h[0]&&c.push("-"),c.push(g(h[1])));c.push("]");return c.join("")}function s(e){for(var a=e.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),c=a.length,d=[],f=0,h=0;f=2&&e==="["?a[f]=b(l):e!=="\\"&&(a[f]=l.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var x=0,m=!1,j=!1,k=0,c=a.length;k=5&&"lang-"===w.substring(0,5))&&!(t&&typeof t[1]==="string"))f=!1,w="src";f||(r[z]=w)}h=c;c+=z.length;if(f){f=t[1];var l=z.indexOf(f),B=l+f.length;t[2]&&(B=z.length-t[2].length,l=B-f.length);w=w.substring(5);H(j+h,z.substring(0,l),g,k);H(j+h+l,f,I(w,f),k);H(j+h+B,z.substring(B),g,k)}else k.push(j+h,w)}a.g=k}var b={},s;(function(){for(var g=a.concat(d),j=[],k={},c=0,i=g.length;c=0;)b[n.charAt(e)]=r;r=r[1];n=""+r;k.hasOwnProperty(n)||(j.push(r),k[n]=q)}j.push(/[\S\s]/);s=S(j)})();var x=d.length;return g}function v(a){var d=[],g=[];a.tripleQuotedStrings?d.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?d.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, +q,"'\"`"]):d.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&g.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var b=a.hashComments;b&&(a.cStyleComments?(b>1?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),g.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,q])):d.push(["com", +/^#[^\n\r]*/,q,"#"]));a.cStyleComments&&(g.push(["com",/^\/\/[^\n\r]*/,q]),g.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));if(b=a.regexLiterals){var s=(b=b>1?"":"\n\r")?".":"[\\S\\s]";g.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+("/(?=[^/*"+b+"])(?:[^/\\x5B\\x5C"+b+"]|\\x5C"+s+"|\\x5B(?:[^\\x5C\\x5D"+b+"]|\\x5C"+ +s+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&g.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&g.push(["kwd",RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),q]);d.push(["pln",/^\s+/,q," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");g.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/, +q],["pun",RegExp(b),q]);return C(d,g)}function J(a,d,g){function b(a){var c=a.nodeType;if(c==1&&!x.test(a.className))if("br"===a.nodeName)s(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((c==3||c==4)&&g){var d=a.nodeValue,i=d.match(m);if(i)c=d.substring(0,i.index),a.nodeValue=c,(d=d.substring(i.index+i[0].length))&&a.parentNode.insertBefore(j.createTextNode(d),a.nextSibling),s(a),c||a.parentNode.removeChild(a)}}function s(a){function b(a,c){var d= +c?a.cloneNode(!1):a,e=a.parentNode;if(e){var e=b(e,1),g=a.nextSibling;e.appendChild(d);for(var i=g;i;i=g)g=i.nextSibling,e.appendChild(i)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),d;(d=a.parentNode)&&d.nodeType===1;)a=d;c.push(a)}for(var x=/(?:^|\s)nocode(?:\s|$)/,m=/\r\n?|\n/,j=a.ownerDocument,k=j.createElement("li");a.firstChild;)k.appendChild(a.firstChild);for(var c=[k],i=0;i=0;){var b=d[g];F.hasOwnProperty(b)?D.console&&console.warn("cannot override language handler %s",b):F[b]=a}}function I(a,d){if(!a||!F.hasOwnProperty(a))a=/^\s*=l&&(b+=2);g>=B&&(r+=2)}}finally{if(f)f.style.display=h}}catch(u){D.console&&console.log(u&&u.stack||u)}}var D=window,y=["break,continue,do,else,for,if,return,while"],E=[[y,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], +"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],M=[E,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],N=[E,"abstract,assert,boolean,byte,extends,final,finally,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"], +O=[N,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,internal,into,is,let,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"],E=[E,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],P=[y,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], +Q=[y,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],W=[y,"as,assert,const,copy,drop,enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"],y=[y,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],R=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/, +V=/\S/,X=v({keywords:[M,O,E,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",P,Q,y],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),F={};p(X,["default-code"]);p(C([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-", +/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);p(C([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/], +["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);p(C([],[["atv",/^[\S\s]+/]]),["uq.val"]);p(v({keywords:M,hashComments:!0,cStyleComments:!0,types:R}),["c","cc","cpp","cxx","cyc","m"]);p(v({keywords:"null,true,false"}),["json"]);p(v({keywords:O,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:R}), +["cs"]);p(v({keywords:N,cStyleComments:!0}),["java"]);p(v({keywords:y,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);p(v({keywords:P,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);p(v({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]);p(v({keywords:Q, +hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);p(v({keywords:E,cStyleComments:!0,regexLiterals:!0}),["javascript","js"]);p(v({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);p(v({keywords:W,cStyleComments:!0,multilineStrings:!0}),["rc","rs","rust"]); +p(C([],[["str",/^[\S\s]+/]]),["regex"]);var Y=D.PR={createSimpleLexer:C,registerLangHandler:p,sourceDecorator:v,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:D.prettyPrintOne=function(a,d,g){var b=document.createElement("div");b.innerHTML="
    "+a+"
    ";b=b.firstChild;g&&J(b,g,!0);K({h:d,j:g,c:b,i:1}); +return b.innerHTML},prettyPrint:D.prettyPrint=function(a,d){function g(){for(var b=D.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;ia visual programming environmentBlocklySee generated JavaScript code.Save and link to blocks.Run the program defined by the blocks in the workspace.Run ProgramResetOKCancelLogicLoopsMathTextListsColourVariablesProceduresThere was a problem with the request.Share your blocks with this link:\\n\\n%1Sorry, \'%1\' doesn\'t correspond with any saved program.Could not load your saved file. Perhaps it was created with a different version of Blockly?listtext'; +}; + + +apps.dialog = function(opt_data, opt_ignored, opt_ijData) { + return '
    '; +}; + + +apps.codeDialog = function(opt_data, opt_ignored, opt_ijData) { + return '
    ' + apps.ok(null, null, opt_ijData) + '
    '; +}; + + +apps.storageDialog = function(opt_data, opt_ignored, opt_ijData) { + return '
    ' + apps.ok(null, null, opt_ijData) + '
    '; +}; + + +apps.ok = function(opt_data, opt_ignored, opt_ijData) { + return '
    '; +}; + +; +// This file was automatically generated from template.soy. +// Please don't edit this file by hand. + +if (typeof puzzlepage == 'undefined') { var puzzlepage = {}; } + + +puzzlepage.messages = function(opt_data, opt_ignored, opt_ijData) { + return '
    Australiëflag_au.png50100EngelsMelbourneSydneyhttp://af.wikipedia.org/wiki/AustraliëDuitslandflag_de.png60100DuitsBerlynMünchenhttp://af.wikipedia.org/wiki/DuitslandSjinaflag_cn.png66100SjineesBeijingShanghaihttp://af.wikipedia.org/wiki/SjinaBrasiliëflag_br.png70100PortugeesRio de JaneiroSão Paulohttp://af.wikipedia.org/wiki/Brasiliëvlag:taal:kies...stede:Perfek!\nAl %1 blokke is korrek.Byna! Eén blok is inkorrek.%1 blokke is inkorrek.Die gemerkte blok is nie korrek nie.\nHou aan om te probeer.
    '; +}; + + +puzzlepage.start = function(opt_data, opt_ignored, opt_ijData) { + return puzzlepage.messages(null, null, opt_ijData) + ' + + + + + + + diff --git a/apps/puzzle/keys.js b/apps/puzzle/keys.js new file mode 100644 index 000000000..e15814992 --- /dev/null +++ b/apps/puzzle/keys.js @@ -0,0 +1,9 @@ +// This file was automatically generated from template.soy. +// Please don't edit this file by hand. + +if (typeof puzzlepage == 'undefined') { var puzzlepage = {}; } + + +puzzlepage.start = function(opt_data, opt_ignored) { + return '\n'); + +/** + * Initialize Blockly and the puzzle. Called on page load. + */ +Puzzle.init = function() { + BlocklyApps.init(); + + var rtl = BlocklyApps.isRtl(); + Blockly.inject(document.getElementById('blockly'), + {path: '../../', + rtl: rtl, + scrollbars: false, + trashcan: false}); + + var blocklyDiv = document.getElementById('blockly'); + var onresize = function(e) { + blocklyDiv.style.width = (window.innerWidth - 20) + 'px'; + blocklyDiv.style.height = + (window.innerHeight - blocklyDiv.offsetTop - 15) + 'px'; + }; + onresize(); + window.addEventListener('resize', onresize); + Blockly.fireUiEvent(window, 'resize'); + + // Add the blocks. + if (window.sessionStorage.loadOnceBlocks) { + var text = window.sessionStorage.loadOnceBlocks; + delete window.sessionStorage.loadOnceBlocks; + var xml = Blockly.Xml.textToDom(text); + Blockly.Xml.domToWorkspace(Blockly.mainWorkspace, xml); + } else { + // Create one of every block. + var blocksCountries = []; + var blocksFlags = []; + var blocksCities = []; + var i = 1; + while (BlocklyApps.getMsgOrNull('Puzzle_country' + i)) { + var block = new Blockly.Block(Blockly.mainWorkspace, 'country'); + block.populate(i); + blocksCountries.push(block); + var block = new Blockly.Block(Blockly.mainWorkspace, 'flag'); + block.populate(i); + blocksFlags.push(block); + var j = 1; + while (BlocklyApps.getMsgOrNull('Puzzle_country' + i + 'City' + j)) { + var block = new Blockly.Block(Blockly.mainWorkspace, 'city'); + block.populate(i, j); + blocksCities.push(block); + j++; + } + i++; + } + Puzzle.shuffle(blocksCountries); + Puzzle.shuffle(blocksFlags); + Puzzle.shuffle(blocksCities); + var blocks = [].concat(blocksCountries, blocksFlags, blocksCities); + if (rtl) { + blocks.reverse(); + } + // Initialize all the blocks. + for (var i = 0, block; block = blocks[i]; i++) { + block.setDeletable(false); + block.initSvg(); + block.render(); + } + var totalArea = 0; + // Measure the surface area of each block. + for (var i = 0, block; block = blocks[i]; i++) { + var blockBox = block.svg_.getRootElement().getBBox(); + block.cached_width_ = blockBox.width; + block.cached_height_ = blockBox.height; + block.cached_area_ = blockBox.width * blockBox.height; + totalArea += block.cached_area_; + } + // Position the blocks randomly. + var MARGIN = 50; + Blockly.svgResize(); + var workspaceBox = Blockly.svgSize(); + workspaceBox.width -= MARGIN; + workspaceBox.height -= MARGIN; + var countedArea = 0; + for (var i = 0, block; block = blocks[i]; i++) { + var blockBox = block.svg_.getRootElement().getBBox(); + // Spread the blocks horizontally, grouped by type. + // Spacing is proportional to block's area. + if (rtl) { + var dx = blockBox.width + + (countedArea / totalArea) * workspaceBox.width; + } else { + var dx = (countedArea / totalArea) * + (workspaceBox.width - blockBox.width); + } + dx = Math.round(dx + Math.random() * MARGIN); + var dy = Math.round(Math.random() * + (workspaceBox.height - blockBox.height)); + block.moveBy(dx, dy); + countedArea += block.cached_area_; + } + + BlocklyApps.bindClick('checkButton', Puzzle.checkAnswers); + BlocklyApps.bindClick('helpButton', function(){Puzzle.showHelp(true);}); + + Puzzle.showHelp(false); + /** + * HACK: + * Chrome (v28) displays a broken image tag on any image that is also + * shown in the help dialog. Selecting the block fixes the problem. + * If Chrome stops corrupting the Australian flag, delete this entire hack. + */ + if (goog.userAgent.WEBKIT) { + var blocks = Blockly.mainWorkspace.getAllBlocks(); + for (var i = 0, block; block = blocks[i]; i++) { + block.select(); + } + Blockly.selected.unselect(); + } + } +}; + +if (window.location.pathname.match(/readonly.html$/)) { + window.addEventListener('load', BlocklyApps.initReadonly); +} else { + window.addEventListener('load', Puzzle.init); +} + +/** + * Shuffles the values in the specified array using the Fisher-Yates in-place + * shuffle (also known as the Knuth Shuffle). + * Runtime: O(n) + * Based on Closure's goog.array.shuffle. + * @param {!Array} arr The array to be shuffled. + */ +Puzzle.shuffle = function(arr) { + for (var i = arr.length - 1; i > 0; i--) { + // Choose a random array index in [0, i] (inclusive with i). + var j = Math.floor(Math.random() * (i + 1)); + var tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } +}; + +/** + * Return a list of all languages. + * @return {!Array>} Array of human-readable and + * language-neutral tuples. + */ +Puzzle.languages = function() { + var list = [[BlocklyApps.getMsg('Puzzle_languageChoose'), '0']]; + var i = 1; + var lang; + while (lang = BlocklyApps.getMsgOrNull('Puzzle_country' + i + 'Language')) { + list[i] = [lang, String(i)]; + i++; + } + return list; +}; + +/** + * Count and highlight the errors. + */ +Puzzle.checkAnswers = function() { + var blocks = Blockly.mainWorkspace.getAllBlocks(); + var errors = 0; + var badBlocks = []; + for (var b = 0, block; block = blocks[b]; b++) { + if (!block.isCorrect()) { + errors++; + // Bring the offending blocks to the front. + block.select(); + badBlocks.push(block); + } + } + + var graphValue = document.getElementById('graphValue'); + window.setTimeout(function() { + graphValue.style.width = + (100 * (blocks.length - errors) / blocks.length) + 'px'; + }, 500); + + var messages; + if (errors == 1) { + messages = [BlocklyApps.getMsg('Puzzle_error1'), + BlocklyApps.getMsg('Puzzle_tryAgain')]; + } else if (errors) { + messages = [BlocklyApps.getMsg('Puzzle_error2').replace('%1', errors), + BlocklyApps.getMsg('Puzzle_tryAgain')]; + } else { + messages = [BlocklyApps.getMsg('Puzzle_error0').replace( + '%1', blocks.length)]; + } + var textDiv = document.getElementById('answerMessage'); + textDiv.textContent = ''; + for (var i = 0; i < messages.length; i++) { + var line = document.createElement('div'); + line.appendChild(document.createTextNode(messages[i])); + textDiv.appendChild(line); + } + + var content = document.getElementById('answers'); + var button = document.getElementById('checkButton'); + var rtl = BlocklyApps.isRtl(); + var style = { + width: '25%', + left: rtl ? '5%' : '70%', + top: '5em' + }; + BlocklyApps.showDialog(content, button, true, true, style, + BlocklyApps.stopDialogKeyDown); + BlocklyApps.startDialogKeyDown(); + + // Pick a random bad block and blink it until the dialog closes. + if (badBlocks.length) { + Puzzle.shuffle(badBlocks); + var badBlock = badBlocks[0]; + var blink = function() { + badBlock.select(); + if (BlocklyApps.isDialogVisible_) { + window.setTimeout(function() {badBlock.unselect();}, 150); + window.setTimeout(blink, 300); + } + }; + blink(); + } +}; + +/** + * Show the help pop-up. + * @param {boolean} animate Animate the pop-up opening. + */ +Puzzle.showHelp = function(animate) { + var help = document.getElementById('help'); + var button = document.getElementById('helpButton'); + var style = { + width: '50%', + left: '25%', + top: '5em' + }; + BlocklyApps.showDialog(help, button, animate, true, style, + BlocklyApps.stopDialogKeyDown); + BlocklyApps.startDialogKeyDown(); +}; diff --git a/apps/puzzle/readonly.html b/apps/puzzle/readonly.html new file mode 100644 index 000000000..06f5dc8b7 --- /dev/null +++ b/apps/puzzle/readonly.html @@ -0,0 +1,36 @@ + + + + + + Blockly : Puzzle Readonly + + + + + + + + + diff --git a/apps/puzzle/style.css b/apps/puzzle/style.css new file mode 100644 index 000000000..2226275d9 --- /dev/null +++ b/apps/puzzle/style.css @@ -0,0 +1,22 @@ +body { + overflow: hidden; +} + +#graph { + position: absolute; + bottom: 25px; + height: 15px; + width: 100px; + border: 1px solid #ddd; +} +#graphValue { + height: 15px; + width: 0; + background-color: #0d0; + transition-property: width; + transition-duration: 1s; +} + +#blockly { + position: fixed; +} diff --git a/apps/puzzle/template.soy b/apps/puzzle/template.soy new file mode 100644 index 000000000..8cd753638 --- /dev/null +++ b/apps/puzzle/template.soy @@ -0,0 +1,250 @@ +{namespace puzzlepage} + +/** + * This is a Closure Template. + * + * To regenerate just en.js, run this command: + * java -jar ../_soy/SoyToJsSrcCompiler.jar --outputPathFormat generated/en.js --srcs ../common.soy,template.soy + * + * To regenerate all files, see: trunk/apps/template.soy. + */ + +/** + * Translated messages for use in JavaScript. + */ +{template .messages} +
    + {{msg meaning="Puzzle.country1" desc="The name of the country Australia\n{lb}{lb}Identical|Australia{rb}{rb}"}}Australia{{/msg}} + flag_au.png + 50 + 100 + + {{msg meaning="Puzzle.country1Language" desc="The English language.{lb}{lb}Identical|English{rb}{rb}"}} + English + {{/msg}} + + + {msg meaning="Puzzle.country1City1" desc="The city Melbourne in Australia."} + Melbourne + {/msg} + + + {msg meaning="Puzzle.country1City2" desc="The city Sydney in Australia."} + Sydney + {/msg} + + + {msg meaning="Puzzle.country1HelpUrl" + desc="The URL of a page with basic information about Australia."} + http://en.wikipedia.org/wiki/Australia + {/msg} + + + {{msg meaning="Puzzle.country2" desc="The country Germany.\n{lb}{lb}Identical|Germany{rb}{rb}"}} + Germany + {/msg} + + flag_de.png + 60 + 100 + + {{msg meaning="Puzzle.country2Language" desc="The German language.\n{lb}{lb}Identical|German{rb}{rb}"}} + German + {{/msg}} + + + {msg meaning="Puzzle.country2City1" desc="The city Berlin in Germany."} + Berlin + {/msg} + + + {msg meaning="Puzzle.country2City2" desc="The city Munich (M\u00fcnchen) in Germany."} + Munich + {/msg} + + + {msg meaning="Puzzle.country2HelpUrl" + desc="The URL of a page with basic information about Germany."} + http://en.wikipedia.org/wiki/Germany + {/msg} + + + {msg meaning="Puzzle.country3" desc="The People's Republic of China."} + China + {/msg} + + flag_cn.png + 66 + 100 + + {{msg meaning="Puzzle.country3Language" desc="The Chinese language.\n{lb}{lb}Identical|Chinese{rb}{rb}"}} + Chinese + {{/msg}} + + + {msg meaning="Puzzle.country3City1" desc="The capital city of China (also known as Peking)."} + Beijing + {/msg} + + + {msg meaning="Puzzle.country3City2" desc="The city Shanghai in China."} + Shanghai + {/msg} + + + {msg meaning="Puzzle.country3HelpUrl" + desc="The URL of a page with basic information about China."} + http://en.wikipedia.org/wiki/China + {/msg} + + + {msg meaning="Puzzle.country4" desc="The name of the country Brazil."} + Brazil + {/msg} + + flag_br.png + 70 + 100 + + {{msg meaning="Puzzle.country4Language" desc="The Portuguese language.\n{lb}{lb}Identical|Portuguese{rb}{rb}"}} + Portuguese + {{/msg}} + + + {msg meaning="Puzzle.country4City1" desc="The city Rio de Janeiro in Brazil."} + Rio de Janeiro + {/msg} + + + {msg meaning="Puzzle.country4City2" desc="The city S\u00e3o Paulo in Brazil."} + São Paulo + {/msg} + + + {msg meaning="Puzzle.country4HelpUrl" + desc="The URL of a page with basic information about Brazil."} + http://en.wikipedia.org/wiki/Brazil + {/msg} + + + {{msg meaning="Puzzle.flag" desc="[[File:Config-language.png|left||32px]]\nnoun the official flag representing a country (the national flag).\n{lb}{lb}Identical|Flag{rb}{rb}"}} + flag: + {/msg} + + + {{msg meaning="Puzzle.language" + desc="Prompt for the user to provide the official language of a country.\n{lb}{lb}Identical|Language{rb}{rb}"}} + language: + {{/msg}} + + + {{msg meaning="Puzzle.languageChoose" + desc="Initial text displayed in a dropdown menu from which the user should choose the language spoken in the indicated country.\n{lb}{lb}Identical|Choose{rb}{rb}"}} + choose... + {{/msg}} + + + {{msg meaning="Puzzle.cities" desc="A label preceding a list of cities.\n{lb}{lb}Identical|City{rb}{rb}"}} + cities: + {{/msg}} + + + {msg meaning="Puzzle.error0" + desc="A congratulatory message displayed if the user placed all of the blocks correctly.\n\nParameters:\n* %1 - number of blocks correctly placed. It is always an integer greater than 1.\n\nThe use of a new line character is optional."} + Perfect!\nAll %1 blocks are correct. + {/msg} + + + {{msg meaning="Puzzle.error1" + desc="An encouraging error message displayed if the user placed all blocks except 1 correctly.\n\nIf the number of incorrect blocks is 2 or more, Puzzle.error2 is used instead."}} + Almost! One block is incorrect. + {{/msg}} + + + {{msg meaning="Puzzle.error2" + desc="An error message displayed if the user misplaced multiple blocks.\n\nParameters:\n* %1 - number of blocks incorrectly placed, which is always greater than 1 (or the message Puzzle.error1 would be used)."}} + %1 blocks are incorrect. + {{/msg}} + + + {msg meaning="Puzzle.tryAgain" + desc="A message indicating that a visually distinguished block is incorrect and that the user should try to fix it.\n\nThe use of a new line character is optional."} + The highlighted block is not correct.\nKeep trying. + {/msg} + +
    +{/template} + +/** + * Web page structure. + */ +{template .start} + {call .messages /} + + + + + + + + + + +
    + + {call apps.dialog /} +
    +
    + {msg meaning="Puzzle.helpText" + desc="Instructions for the puzzle. For context, see [http://blockly-demo.appspot.com/static/apps/puzzle/index.html Blockly Puzzle]."} + For each country (green), attach its flag, choose its language, and make a stack of its cities. + {/msg} +
    + + {call apps.ok /} +
    +
    +
    +
    +
    + {call apps.ok /} +
    +{/template} + +/** + * Readonly Blockly in an iframe. + */ +{template .readonly} + {call .messages /} + + + + +
    +{/template} diff --git a/apps/puzzle/title.png b/apps/puzzle/title.png new file mode 100644 index 000000000..60b26377c Binary files /dev/null and b/apps/puzzle/title.png differ diff --git a/apps/slider.js b/apps/slider.js new file mode 100644 index 000000000..99fe50893 --- /dev/null +++ b/apps/slider.js @@ -0,0 +1,200 @@ +/** + * Blockly Apps: SVG Slider + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview A slider control in SVG. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +/** + * Object representing a horizontal slider widget. + * @param {number} x The horizontal offset of the slider. + * @param {number} y The vertical offset of the slider. + * @param {number} width The total width of the slider. + * @param {!Element} svgParent The SVG element to append the slider to. + * @param {Function} opt_changeFunc Optional callback function that will be + * called when the slider is moved. The current value is passed. + * @constructor + */ +var Slider = function(x, y, width, svgParent, opt_changeFunc) { + this.KNOB_Y_ = y - 12; + this.KNOB_MIN_X_ = x + 8; + this.KNOB_MAX_X_ = x + width - 8; + this.value_ = 0.5; + this.changeFunc_ = opt_changeFunc; + + // Draw the slider. + /* + + + */ + var track = document.createElementNS(Slider.SVG_NS_, 'line'); + track.setAttribute('class', 'sliderTrack'); + track.setAttribute('x1', x); + track.setAttribute('y1', y); + track.setAttribute('x2', x + width); + track.setAttribute('y2', y); + svgParent.appendChild(track); + this.track_ = track; + var knob = document.createElementNS(Slider.SVG_NS_, 'path'); + knob.setAttribute('class', 'sliderKnob'); + knob.setAttribute('d', 'm 0,0 l -8,8 v 12 h 16 v -12 z'); + svgParent.appendChild(knob); + this.knob_ = knob; + this.setValue(0.5); + + // Find the root SVG object. + while (svgParent && svgParent.nodeName.toLowerCase() != 'svg') { + svgParent = svgParent.parentNode; + } + this.SVG_ = svgParent; + + // Bind the events to this slider. + var thisSlider = this; + Slider.bindEvent_(this.knob_, 'mousedown', function(e) { + return thisSlider.knobMouseDown_(e); + }); + Slider.bindEvent_(this.SVG_, 'mouseup', Slider.knobMouseUp_); + Slider.bindEvent_(this.SVG_, 'mousemove', Slider.knobMouseMove_); + Slider.bindEvent_(document, 'mouseover', Slider.mouseOver_); +}; + +Slider.SVG_NS_ = 'http://www.w3.org/2000/svg'; + +Slider.activeSlider_ = null; +Slider.startMouseX_ = 0; +Slider.startKnobX_ = 0; + +/** + * Start a drag when clicking down on the knob. + * @param {!Event} e Mouse-down event. + * @private + */ +Slider.prototype.knobMouseDown_ = function(e) { + Slider.activeSlider_ = this; + Slider.startMouseX_ = this.mouseToSvg_(e).x; + Slider.startKnobX_ = 0; + var transform = this.knob_.getAttribute('transform'); + if (transform) { + var r = transform.match(/translate\(\s*([-\d.]+)/); + if (r) { + Slider.startKnobX_ = Number(r[1]); + } + } + // Stop browser from attempting to drag the knob. + e.preventDefault(); + return false; +}; + +/** + * Stop a drag when clicking up anywhere. + * @param {Event} e Mouse-up event. + * @private + */ +Slider.knobMouseUp_ = function(e) { + Slider.activeSlider_ = null; +}; + +/** + * Stop a drag when the mouse enters a node not part of the SVG. + * @param {Event} e Mouse-up event. + * @private + */ +Slider.mouseOver_ = function(e) { + if (!Slider.activeSlider_) { + return; + } + var node = e.target; + // Find the root SVG object. + do { + if (node == Slider.activeSlider_.SVG_) { + return; + } + } while (node = node.parentNode); + Slider.knobMouseUp_(e); +}; + +/** + * Drag the knob to follow the mouse. + * @param {!Event} e Mouse-move event. + * @private + */ +Slider.knobMouseMove_ = function(e) { + var thisSlider = Slider.activeSlider_; + if (!thisSlider) { + return; + } + var x = thisSlider.mouseToSvg_(e).x - Slider.startMouseX_ + + Slider.startKnobX_; + x = Math.min(Math.max(x, thisSlider.KNOB_MIN_X_), thisSlider.KNOB_MAX_X_); + thisSlider.knob_.setAttribute('transform', + 'translate(' + x + ',' + thisSlider.KNOB_Y_ + ')'); + + thisSlider.value_ = (x - thisSlider.KNOB_MIN_X_) / + (thisSlider.KNOB_MAX_X_ - thisSlider.KNOB_MIN_X_); + thisSlider.changeFunc_ && thisSlider.changeFunc_(thisSlider.value_); +}; + +/** + * Returns the slider's value (0.0 - 1.0). + * @return {number} Current value. + */ +Slider.prototype.getValue = function() { + return this.value_; +}; + +/** + * Sets the slider's value (0.0 - 1.0). + * @param {number} value New value. + */ +Slider.prototype.setValue = function(value) { + this.value_ = Math.min(Math.max(value, 0), 1); + var x = this.KNOB_MIN_X_ + + (this.KNOB_MAX_X_ - this.KNOB_MIN_X_) * this.value_; + this.knob_.setAttribute('transform', + 'translate(' + x + ',' + this.KNOB_Y_ + ')'); +}; + +/** + * Convert the mouse coordinates into SVG coordinates. + * @param {!Object} e Object with x and y mouse coordinates. + * @return {!Object} Object with x and y properties in SVG coordinates. + * @private + */ +Slider.prototype.mouseToSvg_ = function(e) { + var svgPoint = this.SVG_.createSVGPoint(); + svgPoint.x = e.clientX; + svgPoint.y = e.clientY; + var matrix = this.SVG_.getScreenCTM().inverse(); + return svgPoint.matrixTransform(matrix); +}; + +/** + * Bind an event to a function call. + * @param {!Element} element Element upon which to listen. + * @param {string} name Event name to listen to (e.g. 'mousedown'). + * @param {!Function} func Function to call when event is triggered. + * @private + */ +Slider.bindEvent_ = function(element, name, func) { + element.addEventListener(name, func, false); +}; diff --git a/apps/turtle/blocks.js b/apps/turtle/blocks.js new file mode 100644 index 000000000..9c7de1525 --- /dev/null +++ b/apps/turtle/blocks.js @@ -0,0 +1,216 @@ +/** + * Blockly Apps: Turtle Graphics Blocks + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Blocks for Blockly's Turtle Graphics application. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +// Extensions to Blockly's language and JavaScript generator. + +Blockly.Blocks['draw_move'] = { + // Block for moving forward or backwards. + init: function() { + var DIRECTIONS = + [[BlocklyApps.getMsg('Turtle_moveForward'), 'moveForward'], + [BlocklyApps.getMsg('Turtle_moveBackward'), 'moveBackward']]; + this.setColour(160); + this.appendValueInput('VALUE') + .setCheck('Number') + .appendTitle(new Blockly.FieldDropdown(DIRECTIONS), 'DIR'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(BlocklyApps.getMsg('Turtle_moveTooltip')); + } +}; + +Blockly.JavaScript['draw_move'] = function(block) { + // Generate JavaScript for moving forward or backwards. + var value = Blockly.JavaScript.valueToCode(block, 'VALUE', + Blockly.JavaScript.ORDER_NONE) || '0'; + return 'Turtle.' + block.getTitleValue('DIR') + + '(' + value + ', \'block_id_' + block.id + '\');\n'; +}; + + +Blockly.Blocks['draw_turn'] = { + // Block for turning left or right. + init: function() { + var DIRECTIONS = + [[BlocklyApps.getMsg('Turtle_turnRight'), 'turnRight'], + [BlocklyApps.getMsg('Turtle_turnLeft'), 'turnLeft']]; + this.setColour(160); + this.appendValueInput('VALUE') + .setCheck('Number') + .appendTitle(new Blockly.FieldDropdown(DIRECTIONS), 'DIR'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(BlocklyApps.getMsg('Turtle_turnTooltip')); + } +}; + +Blockly.JavaScript['draw_turn'] = function(block) { + // Generate JavaScript for turning left or right. + var value = Blockly.JavaScript.valueToCode(block, 'VALUE', + Blockly.JavaScript.ORDER_NONE) || '0'; + return 'Turtle.' + block.getTitleValue('DIR') + + '(' + value + ', \'block_id_' + block.id + '\');\n'; +}; + +Blockly.Blocks['draw_width'] = { + // Block for setting the width. + init: function() { + this.setColour(160); + this.appendValueInput('WIDTH') + .setCheck('Number') + .appendTitle(BlocklyApps.getMsg('Turtle_setWidth')); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(BlocklyApps.getMsg('Turtle_widthTooltip')); + } +}; + +Blockly.JavaScript['draw_width'] = function(block) { + // Generate JavaScript for setting the width. + var width = Blockly.JavaScript.valueToCode(block, 'WIDTH', + Blockly.JavaScript.ORDER_NONE) || '1'; + return 'Turtle.penWidth(' + width + ', \'block_id_' + block.id + '\');\n'; +}; + +Blockly.Blocks['draw_pen'] = { + // Block for pen up/down. + init: function() { + var STATE = + [[BlocklyApps.getMsg('Turtle_penUp'), 'penUp'], + [BlocklyApps.getMsg('Turtle_penDown'), 'penDown']]; + this.setColour(160); + this.appendDummyInput() + .appendTitle(new Blockly.FieldDropdown(STATE), 'PEN'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(BlocklyApps.getMsg('Turtle_penTooltip')); + } +}; + +Blockly.JavaScript['draw_pen'] = function(block) { + // Generate JavaScript for pen up/down. + return 'Turtle.' + block.getTitleValue('PEN') + + '(\'block_id_' + block.id + '\');\n'; +}; + +Blockly.Blocks['draw_colour'] = { + // Block for setting the colour. + init: function() { + this.setColour(20); + this.appendValueInput('COLOUR') + .setCheck('Colour') + .appendTitle(BlocklyApps.getMsg('Turtle_setColour')); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(BlocklyApps.getMsg('Turtle_colourTooltip')); + } +}; + +Blockly.JavaScript['draw_colour'] = function(block) { + // Generate JavaScript for setting the colour. + var colour = Blockly.JavaScript.valueToCode(block, 'COLOUR', + Blockly.JavaScript.ORDER_NONE) || '\'#000000\''; + return 'Turtle.penColour(' + colour + ', \'block_id_' + + block.id + '\');\n'; +}; + +Blockly.Blocks['turtle_visibility'] = { + // Block for changing turtle visiblity. + init: function() { + var STATE = + [[BlocklyApps.getMsg('Turtle_hideTurtle'), 'hideTurtle'], + [BlocklyApps.getMsg('Turtle_showTurtle'), 'showTurtle']]; + this.setColour(160); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.appendDummyInput() + .appendTitle(new Blockly.FieldDropdown(STATE), 'VISIBILITY'); + this.setTooltip(BlocklyApps.getMsg('Turtle_turtleVisibilityTooltip')); + } +}; + +Blockly.JavaScript['turtle_visibility'] = function(block) { + // Generate JavaScript for changing turtle visibility. + return 'Turtle.' + block.getTitleValue('VISIBILITY') + + '(\'block_id_' + block.id + '\');\n'; +}; + +Blockly.Blocks['draw_print'] = { + // Block for printing text. + init: function() { + this.setHelpUrl(BlocklyApps.getMsg('Turtle_printHelpUrl')); + this.setColour(160); + this.appendValueInput('TEXT') + .appendTitle(BlocklyApps.getMsg('Turtle_print')); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(BlocklyApps.getMsg('Turtle_printTooltip')); + } +}; + +Blockly.JavaScript['draw_print'] = function(block) { + // Generate JavaScript for printing text. + var argument0 = String(Blockly.JavaScript.valueToCode(block, 'TEXT', + Blockly.JavaScript.ORDER_NONE) || '\'\''); + return 'Turtle.drawPrint(' + argument0 + ', \'block_id_' + + block.id + '\');\n'; +}; + +Blockly.Blocks['draw_font'] = { + // Block for setting the font. + init: function() { + var FONTLIST = // Common font names (intentionally not localized) + [['Arial', 'Arial'], ['Courier New', 'Courier New'], ['Georgia', 'Georgia'], + ['Impact', 'Impact'], ['Times New Roman', 'Times New Roman'], + ['Trebuchet MS', 'Trebuchet MS'], ['Verdana', 'Verdana']]; + var STYLE = + [[BlocklyApps.getMsg('Turtle_fontNormal'), 'normal'], + [BlocklyApps.getMsg('Turtle_fontItalic'), 'italic'], + [BlocklyApps.getMsg('Turtle_fontBold'), 'bold']]; + this.setHelpUrl(BlocklyApps.getMsg('Turtle_fontHelpUrl')); + this.setColour(160); + this.appendDummyInput() + .appendTitle(BlocklyApps.getMsg('Turtle_font')) + .appendTitle(new Blockly.FieldDropdown(FONTLIST), 'FONT'); + this.appendDummyInput() + .appendTitle(BlocklyApps.getMsg('Turtle_fontSize')) + .appendTitle(new Blockly.FieldTextInput('18', + Blockly.FieldTextInput.nonnegativeIntegerValidator), + 'FONTSIZE'); + this.appendDummyInput() + .appendTitle(new Blockly.FieldDropdown(STYLE), 'FONTSTYLE'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(BlocklyApps.getMsg('Turtle_fontTooltip')); + } +}; + +Blockly.JavaScript['draw_font'] = function(block) { + // Generate JavaScript for setting the font. + return 'Turtle.drawFont(\'' + block.getTitleValue('FONT') + '\',' + + Number(block.getTitleValue('FONTSIZE')) + ',\'' + + block.getTitleValue('FONTSTYLE') + '\', \'block_id_' + + block.id + '\');\n'; +}; diff --git a/apps/turtle/contest/cgci4i.png b/apps/turtle/contest/cgci4i.png new file mode 100644 index 000000000..5eb3567eb Binary files /dev/null and b/apps/turtle/contest/cgci4i.png differ diff --git a/apps/turtle/contest/d62h9e.png b/apps/turtle/contest/d62h9e.png new file mode 100644 index 000000000..0c506b5da Binary files /dev/null and b/apps/turtle/contest/d62h9e.png differ diff --git a/apps/turtle/contest/index.html b/apps/turtle/contest/index.html new file mode 100644 index 000000000..276472506 --- /dev/null +++ b/apps/turtle/contest/index.html @@ -0,0 +1,68 @@ + + + + + Blockly Turtle Graphics Contest + + + +
    +

    Blockly + Turtle Graphics Contest

    + +

    The contest is over and was a great success, with entries from around the world. See our Google+ post for results, and follow us to keep posted on future Blockly events and news.

    + +

    Please continue to play with Blockly's Turtle Graphics. Here are some ideas to get you started. Click on any image to see the Blockly source code.

    + + + + + + + + + + + +
    + + diff --git a/apps/turtle/contest/kvhuxu.png b/apps/turtle/contest/kvhuxu.png new file mode 100644 index 000000000..7807ef0ea Binary files /dev/null and b/apps/turtle/contest/kvhuxu.png differ diff --git a/apps/turtle/contest/link.png b/apps/turtle/contest/link.png new file mode 100644 index 000000000..c7512de1c Binary files /dev/null and b/apps/turtle/contest/link.png differ diff --git a/apps/turtle/contest/logo.png b/apps/turtle/contest/logo.png new file mode 100644 index 000000000..d61c7c620 Binary files /dev/null and b/apps/turtle/contest/logo.png differ diff --git a/apps/turtle/contest/qojqcx.png b/apps/turtle/contest/qojqcx.png new file mode 100644 index 000000000..928b1beb4 Binary files /dev/null and b/apps/turtle/contest/qojqcx.png differ diff --git a/apps/turtle/generated/af.js b/apps/turtle/generated/af.js new file mode 100644 index 000000000..049643314 --- /dev/null +++ b/apps/turtle/generated/af.js @@ -0,0 +1,50 @@ +// This file was automatically generated from common.soy. +// Please don't edit this file by hand. + +if (typeof apps == 'undefined') { var apps = {}; } + + +apps.messages = function(opt_data, opt_ignored, opt_ijData) { + return '
    a visual programming environmentBlocklySee generated JavaScript code.Save and link to blocks.Run the program defined by the blocks in the workspace.Run ProgramResetOKCancelLogicLoopsMathTextListsColourVariablesProceduresThere was a problem with the request.Share your blocks with this link:\\n\\n%1Sorry, \'%1\' doesn\'t correspond with any saved program.Could not load your saved file. Perhaps it was created with a different version of Blockly?listtext
    '; +}; + + +apps.dialog = function(opt_data, opt_ignored, opt_ijData) { + return '
    '; +}; + + +apps.codeDialog = function(opt_data, opt_ignored, opt_ijData) { + return '
    ' + apps.ok(null, null, opt_ijData) + '
    '; +}; + + +apps.storageDialog = function(opt_data, opt_ignored, opt_ijData) { + return '
    ' + apps.ok(null, null, opt_ijData) + '
    '; +}; + + +apps.ok = function(opt_data, opt_ignored, opt_ijData) { + return '
    '; +}; + +; +// This file was automatically generated from template.soy. +// Please don't edit this file by hand. + +if (typeof turtlepage == 'undefined') { var turtlepage = {}; } + + +turtlepage.messages = function(opt_data, opt_ignored, opt_ijData) { + return apps.messages(null, null, opt_ijData) + '
    Moves the turtle forward or backward by the specified amount.move forward bymove backward byTurns the turtle left or right by the specified number of degrees.turn right byturn left byChanges the width of the pen.set width toChanges the colour of the pen.set colour toLifts or lowers the pen, to stop or start drawing.pen uppen downMakes the turtle (circle and arrow) visible or invisible.hide turtleshow turtlehttp://en.wikipedia.org/wiki/PrintingDraws text in the turtle\'s direction at its location.printhttp://en.wikipedia.org/wiki/FontSets the font used by the print block.fontfont sizenormalbolditalicLeaving this page will result in the loss of your work.
    '; +}; + + +turtlepage.start = function(opt_data, opt_ignored, opt_ijData) { + return turtlepage.messages(null, null, opt_ijData) + '

    Blockly : Turtle Graphics

    + + + + + + + + diff --git a/apps/turtle/loading.gif b/apps/turtle/loading.gif new file mode 100644 index 000000000..56f6161fc Binary files /dev/null and b/apps/turtle/loading.gif differ diff --git a/apps/turtle/style.css b/apps/turtle/style.css new file mode 100644 index 000000000..396245913 --- /dev/null +++ b/apps/turtle/style.css @@ -0,0 +1,72 @@ +#containerCode { + direction: ltr; + font-size: large; + overflow: auto; + max-height: 400px; +} + +button.primary { + /* Can't use "text-align: start" due to IE. */ + text-align: left; +} +html[dir="RTL"] button.primary { + text-align: right; +} + +#toolbarDiv { + text-align: center; + width: 400px; + padding-top: 1em; +} +#blockly { + position: fixed; + bottom: 10px; +} +#display { + border: 1px solid #ccc; +} +#downloadImageLink { + display: none; +} +#languageMenu { + vertical-align: top; + margin-top: 12px; +} + +/* Slider. */ +.sliderTrack { + stroke: #aaa; + stroke-width: 6px; + stroke-linecap: round; +} +.sliderKnob { + fill: #ddd; + stroke: #bbc; + stroke-width: 1px; + stroke-linejoin: round; +} +.sliderKnob:hover { + fill: #eee; +} + +/* Sprited icons. */ +.icon21 { + height: 21px; + width: 21px; + background-image: url(icons.png); +} +.code { + background-position: -21px 0px; +} +.link { + background-position: 0px 0px; +} +.img { + background-position: -42px 0px; +} +.run { + background-position: -63px -21px; +} +.stop { + background-position: -63px 0px; +} diff --git a/apps/turtle/template.soy b/apps/turtle/template.soy new file mode 100644 index 000000000..3bbd3694b --- /dev/null +++ b/apps/turtle/template.soy @@ -0,0 +1,323 @@ +{namespace turtlepage} + +/** + * This is a Closure Template. + * + * To regenerate just en.js, run this command: + * java -jar ../_soy/SoyToJsSrcCompiler.jar --outputPathFormat generated/en.js --srcs ../common.soy,template.soy + * + * To regenerate all files, see: trunk/apps/template.soy. + */ + +/** + * Translated messages for use in JavaScript. + */ +{template .messages} + {call apps.messages /} +
    + // Block text and their associated tooltips and URLs (interleaved to + // assist with translation). + {msg meaning="Turtle.moveTooltip" desc="tooltip - In this and subsequent messages, 'turtle' refers to a stylized turtle on the screen to represent a position and direction. This imaginary turtle is carrying a pen in its tail, so moving the turtle draws a line (or curve, etc.). You are encouraged to play with the [https://blockly-demo.appspot.com/static/apps/turtle/index.html Turtle application] before doing this translation."}Moves the turtle forward or backward by the specified amount.{/msg} + {msg meaning="Turtle.moveForward" desc="[[Translating:Blockly#Drop-Down_Menus dropdown]] - Infinitive or imperative of a verb telling a turtle to move (walk) in the direction he/she is facing. This is followed by a number indicating how far (how many pixels) to go. Prefer a translation that has text in common with the translation of 'move backward'. See [[Translating:Blockly#Drop-Down_Menus]]."}move forward by{/msg} + {msg meaning="Turtle.moveBackward" desc="[[Translating:Blockly#Drop-Down_Menus dropdown]] - Infinitive or imperative of a verb telling a turtle to move (walk) in the direction opposite to where he/she is facing. This is followed by a number indicating how far (how many pixels) to go. Prefer a translation that has text in common with the translation of 'move forward'."}move backward by{/msg} + + {msg meaning="Turtle.turnTooltip" desc="'Left' means counter-clockwise/anti-clockwise, and 'right' means clockwise."}Turns the turtle left or right by the specified number of degrees.{/msg} + {msg meaning="Turtle.turnRight" desc="[[Translating:Blockly#Drop-Down_Menus dropdown]] - Infinitive or imperative of verb telling a turtle to rotate clockwise. This is followed by a number indicating how far (how many degrees) to turn. Prefer a translation that has text in common with the translation of 'turn left by'."}turn right by{/msg} + {msg meaning="Turtle.turnLeft" desc="[[Translating:Blockly#Drop-Down_Menus dropdown]] - Infinitive or imperative of verb telling a turtle to rotate counter-clockwise (anti-clockwise). This is followed by a number indicating how far (how many degrees) to turn. Prefer a translation that has text in common with the translation of 'turn right by'."}turn left by{/msg} + + {msg meaning="Turtle.widthTooltip" desc="tooltip"}Changes the width of the pen.{/msg} + {msg meaning="Turtle.setWidth" desc="block text - Infinitive or imperative of a verb to set the width of the lines that should be drawn in the future by an imaginary pen. This is followed by a number indicating the width in pixels (1 or greater)."}set width to{/msg} + + {msg meaning="Turtle.colourTooltip" desc="tooltip - Changes the colour of ink in the pen carried by the turtle."}Changes the colour of the pen.{/msg} + {msg meaning="Turtle.setColour" desc="block text - Infinitive or imperative of a verb to specify the colour of the lines that should be drawn in the future by an imaginary pen. This is followed by a block showing the colour"}set colour to{/msg} + + {msg meaning="Turtle.penTooltip" desc="tooltip - Lifting the pen off the writing surface prevents anything from being drawn. Lowering it (after it has been lifted) enables it to draw again."}Lifts or lowers the pen, to stop or start drawing.{/msg} + {msg meaning="Turtle.penUp" desc="block text - Infinitive or imperative of a verb to lift up a pen so that moving it leaves no mark on the writing surface."}pen up{/msg} + {msg meaning="Turtle.penDown" desc="block text - Infinitive or imperative of a verb to lower a raised pen so that moving it leaves a mark on the writing surface."}pen down{/msg} + + {msg meaning="Turtle.turtleVisibilityTooltip" desc="tooltip"}Makes the turtle (circle and arrow) visible or invisible.{/msg} + {msg meaning="Turtle.hideTurtle" desc="block text - Infinitive or imperative of a verb telling a turtle to hide itself (become invisible)."}hide turtle{/msg} + {msg meaning="Turtle.showTurtle" desc="block text - Infinitive or imperative of a verb telling a turtle to show itself (become visible after having been invisible)."}show turtle{/msg} + + {msg meaning="Turtle.printHelpUrl" desc="URL - Information about printing or typography."}http://en.wikipedia.org/wiki/Printing{/msg} + {msg meaning="Turtle.printTooltip" desc="tooltip - Note that 'print' refers to displaying text on the screen, not on an external printer."}Draws text in the turtle's direction at its location.{/msg} + {msg meaning="Turtle.print" desc="block text - Infinitive or imperative of a verb telling a turtle to display text on the screen. This is always followed by a block indicating what should be printed."}print{/msg} + + {msg meaning="Turtle.fontHelpUrl" desc="URL - Information about typographic fonts."}http://en.wikipedia.org/wiki/Font{/msg} + {msg meaning="Turtle.fontTooltip" desc="tooltip - This is shown on the block that lets the user specify the font [family], size, and style that should be used for subsequent displays of text."}Sets the font used by the print block.{/msg} + {msg meaning="Turtle.font" desc="block text - This precedes a dropdown menu specifying the typographic font [family] that should be used when displaying text."}font{/msg} + {msg meaning="Turtle.fontSize" desc="block text - This precedes a number specifying the size of the typographic font that should be used when displaying text. This appears in the same block as 'font', so that word should not be repeated."}font size{/msg} + {msg meaning="Turtle.fontNormal" desc="[[Translating:Blockly#Drop-Down_Menus dropdown]] - Specifies that a typographic font should be normal (neither in italics or bold)."}normal{/msg} + {msg meaning="Turtle.fontBold" desc="[[Translating:Blockly#Drop-Down_Menus dropdown]] - Specifies that a typographic font should be [http://en.wikipedia.org/wiki/Emphasis_(typography) bold]."}bold{/msg} + {msg meaning="Turtle.fontItalic" desc="[[Translating:Blockly#Drop-Down_Menus dropdown]] - Specifies that a typographic font should be [http://en.wikipedia.org/wiki/Italics italic]."}italic{/msg} + + // Misc text. + {msg meaning="Turtle.unloadWarning" desc="alert - This is shown if the user attempts to close the browser tab containing the page or navigate to a different page to prevent them from accidentally losing their program in progress."}Leaving this page will result in the loss of your work.{/msg} +
    +{/template} + +/** + * Web page structure. + */ +{template .start} + {call .messages /} + + + + + +
    +

    + + {msg meaning="Apps.blocklyMessage" desc="IBID"}Blockly{/msg} + {sp}:{sp} + {msg meaning="Turtle.title" desc="title - Specifies that this is Blockly's '''Turtle Graphics''' application. Should you wish to, you can read more about [http://en.wikipedia.org/wiki/Turtle_graphics turtle graphics]."} + Turtle Graphics + {/msg} + +

    +
    + +
    +
    + + +
    + + + + + + +
    + + + + + + + + + + + + + + + + + + +
    + +
    + + + + +
    + + + + + + + {call .toolbox /} +
    + + {call apps.dialog /} + {call apps.codeDialog /} + {call apps.storageDialog /} +{/template} + +/** + * Toolbox. + */ +{template .toolbox} + +{/template} diff --git a/apps/turtle/title.png b/apps/turtle/title.png new file mode 100644 index 000000000..9fcb7d473 Binary files /dev/null and b/apps/turtle/title.png differ diff --git a/apps/turtle/turtle.js b/apps/turtle/turtle.js new file mode 100644 index 000000000..0045d0d19 --- /dev/null +++ b/apps/turtle/turtle.js @@ -0,0 +1,412 @@ +/** + * Blockly Apps: Turtle Graphics + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview JavaScript for Blockly's Turtle application. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +/** + * Create a namespace for the application. + */ +var Turtle = {}; + +// Supported languages. +BlocklyApps.LANGUAGES = ['en', 'de', 'fa', 'hu', 'it', 'ru', 'uk', 'vi']; +BlocklyApps.LANG = BlocklyApps.getLang(); + +document.write('\n'); + +Turtle.HEIGHT = 400; +Turtle.WIDTH = 400; + +/** + * PID of animation task currently executing. + */ +Turtle.pid = 0; + +/** + * Should the turtle be drawn? + */ +Turtle.visible = true; + +/** + * Initialize Blockly and the turtle. Called on page load. + */ +Turtle.init = function() { + BlocklyApps.init(); + + var rtl = BlocklyApps.isRtl(); + var toolbox = document.getElementById('toolbox'); + Blockly.inject(document.getElementById('blockly'), + {path: '../../', + rtl: rtl, + toolbox: toolbox, + trashcan: true}); + + Blockly.JavaScript.INFINITE_LOOP_TRAP = ' BlocklyApps.checkTimeout(%1);\n'; + + // Add to reserved word list: API, local variables in execution evironment + // (execute) and the infinite loop detection function. + Blockly.JavaScript.addReservedWords('Turtle,code'); + + window.addEventListener('beforeunload', function(e) { + if (Blockly.mainWorkspace.getAllBlocks().length > 2) { + e.returnValue = BlocklyApps.getMsg('Turtle_unloadWarning'); // Gecko. + return BlocklyApps.getMsg('Turtle_unloadWarning'); // Webkit. + } + return null; + }); + var blocklyDiv = document.getElementById('blockly'); + var visualization = document.getElementById('visualization'); + var onresize = function(e) { + var top = visualization.offsetTop; + blocklyDiv.style.top = Math.max(10, top - window.scrollY) + 'px'; + blocklyDiv.style.left = rtl ? '10px' : '420px'; + blocklyDiv.style.width = (window.innerWidth - 440) + 'px'; + }; + window.addEventListener('scroll', function() { + onresize(); + Blockly.fireUiEvent(window, 'resize'); + }); + window.addEventListener('resize', onresize); + onresize(); + Blockly.fireUiEvent(window, 'resize'); + + // Hide download button if browser lacks support + // (http://caniuse.com/#feat=download). + if (!(goog.userAgent.GECKO || + (goog.userAgent.WEBKIT && !goog.userAgent.SAFARI))) { + document.getElementById('captureButton').className = 'disabled'; + } else { + BlocklyApps.bindClick('captureButton', Turtle.createImageLink); + } + + // Initialize the slider. + var sliderSvg = document.getElementById('slider'); + Turtle.speedSlider = new Slider(10, 35, 130, sliderSvg); + + var defaultXml = + '' + + ' ' + + ' ' + + ' ' + + ' 100' + + ' ' + + ' ' + + ' ' + + ''; + BlocklyApps.loadBlocks(defaultXml); + + Turtle.ctxDisplay = document.getElementById('display').getContext('2d'); + Turtle.ctxScratch = document.getElementById('scratch').getContext('2d'); + Turtle.reset(); + + BlocklyApps.bindClick('runButton', Turtle.runButtonClick); + BlocklyApps.bindClick('resetButton', Turtle.resetButtonClick); + + // Lazy-load the syntax-highlighting. + window.setTimeout(BlocklyApps.importPrettify, 1); +}; + +window.addEventListener('load', Turtle.init); + +/** + * Reset the turtle to the start position, clear the display, and kill any + * pending tasks. + */ +Turtle.reset = function() { + // Starting location and heading of the turtle. + Turtle.x = Turtle.HEIGHT / 2; + Turtle.y = Turtle.WIDTH / 2; + Turtle.heading = 0; + Turtle.penDownValue = true; + Turtle.visible = true; + + // Clear the display. + Turtle.ctxScratch.canvas.width = Turtle.ctxScratch.canvas.width; + Turtle.ctxScratch.strokeStyle = '#000000'; + Turtle.ctxScratch.fillStyle = '#000000'; + Turtle.ctxScratch.lineWidth = 1; + Turtle.ctxScratch.lineCap = 'round'; + Turtle.ctxScratch.font = 'normal 18pt Arial'; + Turtle.display(); + + // Kill any task. + if (Turtle.pid) { + window.clearTimeout(Turtle.pid); + } + Turtle.pid = 0; +}; + +/** + * Copy the scratch canvas to the display canvas. Add a turtle marker. + */ +Turtle.display = function() { + Turtle.ctxDisplay.globalCompositeOperation = 'copy'; + Turtle.ctxDisplay.drawImage(Turtle.ctxScratch.canvas, 0, 0); + Turtle.ctxDisplay.globalCompositeOperation = 'source-over'; + // Draw the turtle. + if (Turtle.visible) { + // Make the turtle the colour of the pen. + Turtle.ctxDisplay.strokeStyle = Turtle.ctxScratch.strokeStyle; + Turtle.ctxDisplay.fillStyle = Turtle.ctxScratch.fillStyle; + + // Draw the turtle body. + var radius = Turtle.ctxScratch.lineWidth / 2 + 10; + Turtle.ctxDisplay.beginPath(); + Turtle.ctxDisplay.arc(Turtle.x, Turtle.y, radius, 0, 2 * Math.PI, false); + Turtle.ctxDisplay.lineWidth = 3; + Turtle.ctxDisplay.stroke(); + + // Draw the turtle head. + var WIDTH = 0.3; + var HEAD_TIP = 10; + var ARROW_TIP = 4; + var BEND = 6; + var radians = 2 * Math.PI * Turtle.heading / 360; + var tipX = Turtle.x + (radius + HEAD_TIP) * Math.sin(radians); + var tipY = Turtle.y - (radius + HEAD_TIP) * Math.cos(radians); + radians -= WIDTH; + var leftX = Turtle.x + (radius + ARROW_TIP) * Math.sin(radians); + var leftY = Turtle.y - (radius + ARROW_TIP) * Math.cos(radians); + radians += WIDTH / 2; + var leftControlX = Turtle.x + (radius + BEND) * Math.sin(radians); + var leftControlY = Turtle.y - (radius + BEND) * Math.cos(radians); + radians += WIDTH; + var rightControlX = Turtle.x + (radius + BEND) * Math.sin(radians); + var rightControlY = Turtle.y - (radius + BEND) * Math.cos(radians); + radians += WIDTH / 2; + var rightX = Turtle.x + (radius + ARROW_TIP) * Math.sin(radians); + var rightY = Turtle.y - (radius + ARROW_TIP) * Math.cos(radians); + Turtle.ctxDisplay.beginPath(); + Turtle.ctxDisplay.moveTo(tipX, tipY); + Turtle.ctxDisplay.lineTo(leftX, leftY); + Turtle.ctxDisplay.bezierCurveTo(leftControlX, leftControlY, + rightControlX, rightControlY, rightX, rightY); + Turtle.ctxDisplay.closePath(); + Turtle.ctxDisplay.fill(); + } +}; + +/** + * Click the run button. Start the program. + */ +Turtle.runButtonClick = function() { + var runButton = document.getElementById('runButton'); + var resetButton = document.getElementById('resetButton'); + // Ensure that Reset button is at least as wide as Run button. + if (!resetButton.style.minWidth) { + resetButton.style.minWidth = runButton.offsetWidth + 'px'; + } + runButton.style.display = 'none'; + resetButton.style.display = 'inline'; + document.getElementById('spinner').style.visibility = 'visible'; + Blockly.mainWorkspace.traceOn(true); + Turtle.execute(); +}; + +/** + * Click the reset button. Reset the Turtle. + */ +Turtle.resetButtonClick = function() { + document.getElementById('runButton').style.display = 'inline'; + document.getElementById('resetButton').style.display = 'none'; + document.getElementById('spinner').style.visibility = 'hidden'; + Blockly.mainWorkspace.traceOn(false); + Turtle.reset(); +}; + + +/** + * Execute the user's code. Heaven help us... + */ +Turtle.execute = function() { + BlocklyApps.log = []; + BlocklyApps.ticks = 1000000; + + var code = Blockly.JavaScript.workspaceToCode(); + try { + eval(code); + } catch (e) { + // Null is thrown for infinite loop. + // Otherwise, abnormal termination is a user error. + if (e !== Infinity) { + alert(e); + } + } + + // BlocklyApps.log now contains a transcript of all the user's actions. + // Reset the graphic and animate the transcript. + Turtle.reset(); + Turtle.pid = window.setTimeout(Turtle.animate, 100); +}; + +/** + * Iterate through the recorded path and animate the turtle's actions. + */ +Turtle.animate = function() { + // All tasks should be complete now. Clean up the PID list. + Turtle.pid = 0; + + var tuple = BlocklyApps.log.shift(); + if (!tuple) { + document.getElementById('spinner').style.visibility = 'hidden'; + Blockly.mainWorkspace.highlightBlock(null); + return; + } + var command = tuple.shift(); + BlocklyApps.highlight(tuple.pop()); + Turtle.step(command, tuple); + Turtle.display(); + + // Scale the speed non-linearly, to give better precision at the fast end. + var stepSpeed = 1000 * Math.pow(1 - Turtle.speedSlider.getValue(), 2); + Turtle.pid = window.setTimeout(Turtle.animate, stepSpeed); +}; + +/** + * Execute one step. + * @param {string} command Logo-style command (e.g. 'FD' or 'RT'). + * @param {!Array} values List of arguments for the command. + */ +Turtle.step = function(command, values) { + switch (command) { + case 'FD': // Forward + if (Turtle.penDownValue) { + Turtle.ctxScratch.beginPath(); + Turtle.ctxScratch.moveTo(Turtle.x, Turtle.y); + } + var distance = values[0]; + if (distance) { + Turtle.x += distance * Math.sin(2 * Math.PI * Turtle.heading / 360); + Turtle.y -= distance * Math.cos(2 * Math.PI * Turtle.heading / 360); + var bump = 0; + } else { + // WebKit (unlike Gecko) draws nothing for a zero-length line. + var bump = 0.1; + } + if (Turtle.penDownValue) { + Turtle.ctxScratch.lineTo(Turtle.x, Turtle.y + bump); + Turtle.ctxScratch.stroke(); + } + break; + case 'RT': // Right Turn + Turtle.heading += values[0]; + Turtle.heading %= 360; + if (Turtle.heading < 0) { + Turtle.heading += 360; + } + break; + case 'DP': // Draw Print + Turtle.ctxScratch.save(); + Turtle.ctxScratch.translate(Turtle.x, Turtle.y); + Turtle.ctxScratch.rotate(2 * Math.PI * (Turtle.heading - 90) / 360); + Turtle.ctxScratch.fillText(values[0], 0, 0); + Turtle.ctxScratch.restore(); + break; + case 'DF': // Draw Font + Turtle.ctxScratch.font = values[2] + ' ' + values[1] + 'pt ' + values[0]; + break; + case 'PU': // Pen Up + Turtle.penDownValue = false; + break; + case 'PD': // Pen Down + Turtle.penDownValue = true; + break; + case 'PW': // Pen Width + Turtle.ctxScratch.lineWidth = values[0]; + break; + case 'PC': // Pen Colour + Turtle.ctxScratch.strokeStyle = values[0]; + Turtle.ctxScratch.fillStyle = values[0]; + break; + case 'HT': // Hide Turtle + Turtle.visible = false; + break; + case 'ST': // Show Turtle + Turtle.visible = true; + break; + } +}; + +/** + * Save an image of the SVG canvas. + */ +Turtle.createImageLink = function() { + var imgLink = document.getElementById('downloadImageLink'); + imgLink.setAttribute('href', + document.getElementById('display').toDataURL('image/png')); + var temp = window.onbeforeunload; + window.onbeforeunload = null; + imgLink.click(); + window.onbeforeunload = temp; +}; + +// Turtle API. + +Turtle.moveForward = function(distance, id) { + BlocklyApps.log.push(['FD', distance, id]); +}; + +Turtle.moveBackward = function(distance, id) { + BlocklyApps.log.push(['FD', -distance, id]); +}; + +Turtle.turnRight = function(angle, id) { + BlocklyApps.log.push(['RT', angle, id]); +}; + +Turtle.turnLeft = function(angle, id) { + BlocklyApps.log.push(['RT', -angle, id]); +}; + +Turtle.penUp = function(id) { + BlocklyApps.log.push(['PU', id]); +}; + +Turtle.penDown = function(id) { + BlocklyApps.log.push(['PD', id]); +}; + +Turtle.penWidth = function(width, id) { + BlocklyApps.log.push(['PW', Math.max(width, 0), id]); +}; + +Turtle.penColour = function(colour, id) { + BlocklyApps.log.push(['PC', colour, id]); +}; + +Turtle.hideTurtle = function(id) { + BlocklyApps.log.push(['HT', id]); +}; + +Turtle.showTurtle = function(id) { + BlocklyApps.log.push(['ST', id]); +}; + +Turtle.drawPrint = function(text, id) { + BlocklyApps.log.push(['DP', text, id]); +}; + +Turtle.drawFont = function(font, size, style, id) { + BlocklyApps.log.push(['DF', font, size, style, id]); +}; diff --git a/blockly_compressed.js b/blockly_compressed.js new file mode 100644 index 000000000..178081137 --- /dev/null +++ b/blockly_compressed.js @@ -0,0 +1,962 @@ +// Do not edit this file; automatically generated by build.py. +"use strict"; + +var COMPILED=!0,goog=goog||{};goog.global=this;goog.exportPath_=function(a,b,c){a=a.split(".");c=c||goog.global;a[0]in c||!c.execScript||c.execScript("var "+a[0]);for(var d;a.length&&(d=a.shift());)a.length||void 0===b?c=c[d]?c[d]:c[d]={}:c[d]=b};goog.define=function(a,b){var c=b;COMPILED||goog.global.CLOSURE_DEFINES&&Object.prototype.hasOwnProperty.call(goog.global.CLOSURE_DEFINES,a)&&(c=goog.global.CLOSURE_DEFINES[a]);goog.exportPath_(a,c)};goog.DEBUG=!0;goog.LOCALE="en";goog.TRUSTED_SITE=!0; +goog.provide=function(a){if(!COMPILED){if(goog.isProvided_(a))throw Error('Namespace "'+a+'" already declared.');delete goog.implicitNamespaces_[a];for(var b=a;(b=b.substring(0,b.lastIndexOf(".")))&&!goog.getObjectByName(b);)goog.implicitNamespaces_[b]=!0}goog.exportPath_(a)};goog.setTestOnly=function(a){if(COMPILED&&!goog.DEBUG)throw a=a||"",Error("Importing test-only code into non-debug environment"+a?": "+a:".");}; +COMPILED||(goog.isProvided_=function(a){return!goog.implicitNamespaces_[a]&&!!goog.getObjectByName(a)},goog.implicitNamespaces_={});goog.getObjectByName=function(a,b){for(var c=a.split("."),d=b||goog.global,e;e=c.shift();)if(goog.isDefAndNotNull(d[e]))d=d[e];else return null;return d};goog.globalize=function(a,b){var c=b||goog.global,d;for(d in a)c[d]=a[d]}; +goog.addDependency=function(a,b,c){if(goog.DEPENDENCIES_ENABLED){var d;a=a.replace(/\\/g,"/");for(var e=goog.dependencies_,f=0;d=b[f];f++)e.nameToPath[d]=a,a in e.pathToNames||(e.pathToNames[a]={}),e.pathToNames[a][d]=!0;for(d=0;b=c[d];d++)a in e.requires||(e.requires[a]={}),e.requires[a][b]=!0}};goog.ENABLE_DEBUG_LOADER=!0; +goog.require=function(a){if(!COMPILED&&!goog.isProvided_(a)){if(goog.ENABLE_DEBUG_LOADER){var b=goog.getPathFromDeps_(a);if(b){goog.included_[b]=!0;goog.writeScripts_();return}}a="goog.require could not find: "+a;goog.global.console&&goog.global.console.error(a);throw Error(a);}};goog.basePath="";goog.nullFunction=function(){};goog.identityFunction=function(a,b){return a};goog.abstractMethod=function(){throw Error("unimplemented abstract method");}; +goog.addSingletonGetter=function(a){a.getInstance=function(){if(a.instance_)return a.instance_;goog.DEBUG&&(goog.instantiatedSingletons_[goog.instantiatedSingletons_.length]=a);return a.instance_=new a}};goog.instantiatedSingletons_=[];goog.DEPENDENCIES_ENABLED=!COMPILED&&goog.ENABLE_DEBUG_LOADER; +goog.DEPENDENCIES_ENABLED&&(goog.included_={},goog.dependencies_={pathToNames:{},nameToPath:{},requires:{},visited:{},written:{}},goog.inHtmlDocument_=function(){var a=goog.global.document;return"undefined"!=typeof a&&"write"in a},goog.findBasePath_=function(){if(goog.global.CLOSURE_BASE_PATH)goog.basePath=goog.global.CLOSURE_BASE_PATH;else if(goog.inHtmlDocument_())for(var a=goog.global.document.getElementsByTagName("script"),b=a.length-1;0<=b;--b){var c=a[b].src,d=c.lastIndexOf("?"),d=-1==d?c.length: +d;if("base.js"==c.substr(d-7,7)){goog.basePath=c.substr(0,d-7);break}}},goog.importScript_=function(a){var b=goog.global.CLOSURE_IMPORT_SCRIPT||goog.writeScriptTag_;!goog.dependencies_.written[a]&&b(a)&&(goog.dependencies_.written[a]=!0)},goog.writeScriptTag_=function(a){if(goog.inHtmlDocument_()){var b=goog.global.document;if("complete"==b.readyState){if(/\bdeps.js$/.test(a))return!1;throw Error('Cannot write "'+a+'" after document load');}b.write(''); +// Load fresh Closure Library. +document.write(''); +document.write(''); diff --git a/blocks/colour.js b/blocks/colour.js new file mode 100644 index 000000000..6551de796 --- /dev/null +++ b/blocks/colour.js @@ -0,0 +1,99 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Colour blocks for Blockly. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Blocks.colour'); + +goog.require('Blockly.Blocks'); + + +Blockly.Blocks['colour_picker'] = { + // Colour picker. + init: function() { + this.setHelpUrl(Blockly.Msg.COLOUR_PICKER_HELPURL); + this.setColour(20); + this.appendDummyInput() + .appendTitle(new Blockly.FieldColour('#ff0000'), 'COLOUR'); + this.setOutput(true, 'Colour'); + this.setTooltip(Blockly.Msg.COLOUR_PICKER_TOOLTIP); + } +}; + +Blockly.Blocks['colour_random'] = { + // Random colour. + init: function() { + this.setHelpUrl(Blockly.Msg.COLOUR_RANDOM_HELPURL); + this.setColour(20); + this.appendDummyInput() + .appendTitle(Blockly.Msg.COLOUR_RANDOM_TITLE); + this.setOutput(true, 'Colour'); + this.setTooltip(Blockly.Msg.COLOUR_RANDOM_TOOLTIP); + } +}; + +Blockly.Blocks['colour_rgb'] = { + // Compose a colour from RGB components. + init: function() { + this.setHelpUrl(Blockly.Msg.COLOUR_RGB_HELPURL); + this.setColour(20); + this.appendValueInput('RED') + .setCheck('Number') + .setAlign(Blockly.ALIGN_RIGHT) + .appendTitle(Blockly.Msg.COLOUR_RGB_TITLE) + .appendTitle(Blockly.Msg.COLOUR_RGB_RED); + this.appendValueInput('GREEN') + .setCheck('Number') + .setAlign(Blockly.ALIGN_RIGHT) + .appendTitle(Blockly.Msg.COLOUR_RGB_GREEN); + this.appendValueInput('BLUE') + .setCheck('Number') + .setAlign(Blockly.ALIGN_RIGHT) + .appendTitle(Blockly.Msg.COLOUR_RGB_BLUE); + this.setOutput(true, 'Colour'); + this.setTooltip(Blockly.Msg.COLOUR_RGB_TOOLTIP); + } +}; + +Blockly.Blocks['colour_blend'] = { + // Blend two colours together. + init: function() { + this.setHelpUrl(Blockly.Msg.COLOUR_BLEND_HELPURL); + this.setColour(20); + this.appendValueInput('COLOUR1') + .setCheck('Colour') + .setAlign(Blockly.ALIGN_RIGHT) + .appendTitle(Blockly.Msg.COLOUR_BLEND_TITLE) + .appendTitle(Blockly.Msg.COLOUR_BLEND_COLOUR1); + this.appendValueInput('COLOUR2') + .setCheck('Colour') + .setAlign(Blockly.ALIGN_RIGHT) + .appendTitle(Blockly.Msg.COLOUR_BLEND_COLOUR2); + this.appendValueInput('RATIO') + .setCheck('Number') + .setAlign(Blockly.ALIGN_RIGHT) + .appendTitle(Blockly.Msg.COLOUR_BLEND_RATIO); + this.setOutput(true, 'Colour'); + this.setTooltip(Blockly.Msg.COLOUR_BLEND_TOOLTIP); + } +}; diff --git a/blocks/lists.js b/blocks/lists.js new file mode 100644 index 000000000..14599bcb7 --- /dev/null +++ b/blocks/lists.js @@ -0,0 +1,499 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview List blocks for Blockly. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Blocks.lists'); + +goog.require('Blockly.Blocks'); + + +Blockly.Blocks['lists_create_empty'] = { + // Create an empty list. + init: function() { + this.setHelpUrl(Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL); + this.setColour(260); + this.setOutput(true, 'Array'); + this.appendDummyInput() + .appendTitle(Blockly.Msg.LISTS_CREATE_EMPTY_TITLE); + this.setTooltip(Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP); + } +}; + +Blockly.Blocks['lists_create_with'] = { + // Create a list with any number of elements of any type. + init: function() { + this.setColour(260); + this.appendValueInput('ADD0') + .appendTitle(Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH); + this.appendValueInput('ADD1'); + this.appendValueInput('ADD2'); + this.setOutput(true, 'Array'); + this.setMutator(new Blockly.Mutator(['lists_create_with_item'])); + this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP); + this.itemCount_ = 3; + }, + mutationToDom: function(workspace) { + var container = document.createElement('mutation'); + container.setAttribute('items', this.itemCount_); + return container; + }, + domToMutation: function(container) { + for (var x = 0; x < this.itemCount_; x++) { + this.removeInput('ADD' + x); + } + this.itemCount_ = parseInt(container.getAttribute('items'), 10); + for (var x = 0; x < this.itemCount_; x++) { + var input = this.appendValueInput('ADD' + x); + if (x == 0) { + input.appendTitle(Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH); + } + } + if (this.itemCount_ == 0) { + this.appendDummyInput('EMPTY') + .appendTitle(Blockly.Msg.LISTS_CREATE_EMPTY_TITLE); + } + }, + decompose: function(workspace) { + var containerBlock = new Blockly.Block(workspace, + 'lists_create_with_container'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var x = 0; x < this.itemCount_; x++) { + var itemBlock = new Blockly.Block(workspace, 'lists_create_with_item'); + itemBlock.initSvg(); + connection.connect(itemBlock.previousConnection); + connection = itemBlock.nextConnection; + } + return containerBlock; + }, + compose: function(containerBlock) { + // Disconnect all input blocks and remove all inputs. + if (this.itemCount_ == 0) { + this.removeInput('EMPTY'); + } else { + for (var x = this.itemCount_ - 1; x >= 0; x--) { + this.removeInput('ADD' + x); + } + } + this.itemCount_ = 0; + // Rebuild the block's inputs. + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + while (itemBlock) { + var input = this.appendValueInput('ADD' + this.itemCount_); + if (this.itemCount_ == 0) { + input.appendTitle(Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH); + } + // Reconnect any child blocks. + if (itemBlock.valueConnection_) { + input.connection.connect(itemBlock.valueConnection_); + } + this.itemCount_++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + if (this.itemCount_ == 0) { + this.appendDummyInput('EMPTY') + .appendTitle(Blockly.Msg.LISTS_CREATE_EMPTY_TITLE); + } + }, + saveConnections: function(containerBlock) { + // Store a pointer to any connected child blocks. + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + var x = 0; + while (itemBlock) { + var input = this.getInput('ADD' + x); + itemBlock.valueConnection_ = input && input.connection.targetConnection; + x++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + } +}; + +Blockly.Blocks['lists_create_with_container'] = { + // Container. + init: function() { + this.setColour(260); + this.appendDummyInput() + .appendTitle(Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD); + this.appendStatementInput('STACK'); + this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP); + this.contextMenu = false; + } +}; + +Blockly.Blocks['lists_create_with_item'] = { + // Add items. + init: function() { + this.setColour(260); + this.appendDummyInput() + .appendTitle(Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP); + this.contextMenu = false; + } +}; + +Blockly.Blocks['lists_repeat'] = { + // Create a list with one element repeated. + init: function() { + this.setHelpUrl(Blockly.Msg.LISTS_REPEAT_HELPURL); + this.setColour(260); + this.setOutput(true, 'Array'); + this.interpolateMsg(Blockly.Msg.LISTS_REPEAT_TITLE, + ['ITEM', null, Blockly.ALIGN_RIGHT], + ['NUM', 'Number', Blockly.ALIGN_RIGHT], + Blockly.ALIGN_RIGHT); + this.setTooltip(Blockly.Msg.LISTS_REPEAT_TOOLTIP); + } +}; + +Blockly.Blocks['lists_length'] = { + // List length. + init: function() { + this.setHelpUrl(Blockly.Msg.LISTS_LENGTH_HELPURL); + this.setColour(260); + this.interpolateMsg(Blockly.Msg.LISTS_LENGTH_TITLE, + ['VALUE', ['Array', 'String'], Blockly.ALIGN_RIGHT], + Blockly.ALIGN_RIGHT); + this.setOutput(true, 'Number'); + this.setTooltip(Blockly.Msg.LISTS_LENGTH_TOOLTIP); + } +}; + +Blockly.Blocks['lists_isEmpty'] = { + // Is the list empty? + init: function() { + this.setHelpUrl(Blockly.Msg.LISTS_IS_EMPTY_HELPURL); + this.setColour(260); + this.interpolateMsg(Blockly.Msg.LISTS_IS_EMPTY_TITLE, + ['VALUE', ['Array', 'String'], Blockly.ALIGN_RIGHT], + Blockly.ALIGN_RIGHT) + this.setInputsInline(true); + this.setOutput(true, 'Boolean'); + this.setTooltip(Blockly.Msg.LISTS_TOOLTIP); + } +}; + +Blockly.Blocks['lists_indexOf'] = { + // Find an item in the list. + init: function() { + var OPERATORS = + [[Blockly.Msg.LISTS_INDEX_OF_FIRST, 'FIRST'], + [Blockly.Msg.LISTS_INDEX_OF_LAST, 'LAST']]; + this.setHelpUrl(Blockly.Msg.LISTS_INDEX_OF_HELPURL); + this.setColour(260); + this.setOutput(true, 'Number'); + this.appendValueInput('VALUE') + .setCheck('Array') + .appendTitle(Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST); + this.appendValueInput('FIND') + .appendTitle(new Blockly.FieldDropdown(OPERATORS), 'END'); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.LISTS_INDEX_OF_TOOLTIP); + } +}; + +Blockly.Blocks['lists_getIndex'] = { + // Get element at index. + init: function() { + var MODE = + [[Blockly.Msg.LISTS_GET_INDEX_GET, 'GET'], + [Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE, 'GET_REMOVE'], + [Blockly.Msg.LISTS_GET_INDEX_REMOVE, 'REMOVE']]; + this.WHERE_OPTIONS = + [[Blockly.Msg.LISTS_GET_INDEX_FROM_START, 'FROM_START'], + [Blockly.Msg.LISTS_GET_INDEX_FROM_END, 'FROM_END'], + [Blockly.Msg.LISTS_GET_INDEX_FIRST, 'FIRST'], + [Blockly.Msg.LISTS_GET_INDEX_LAST, 'LAST'], + [Blockly.Msg.LISTS_GET_INDEX_RANDOM, 'RANDOM']]; + this.setHelpUrl(Blockly.Msg.LISTS_GET_INDEX_HELPURL); + this.setColour(260); + var modeMenu = new Blockly.FieldDropdown(MODE, function(value) { + var isStatement = (value == 'REMOVE'); + this.sourceBlock_.updateStatement(isStatement); + }); + this.appendValueInput('VALUE') + .setCheck('Array') + .appendTitle(Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST); + this.appendDummyInput() + .appendTitle(modeMenu, 'MODE') + .appendTitle('', 'SPACE'); + this.appendDummyInput('AT'); + if (Blockly.Msg.LISTS_GET_INDEX_TAIL) { + this.appendDummyInput('TAIL') + .appendTitle(Blockly.Msg.LISTS_GET_INDEX_TAIL); + } + this.setInputsInline(true); + this.setOutput(true); + this.updateAt(true); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function() { + var combo = thisBlock.getTitleValue('MODE') + '_' + + thisBlock.getTitleValue('WHERE'); + return Blockly.Msg['LISTS_GET_INDEX_TOOLTIP_' + combo]; + }); + }, + mutationToDom: function() { + // Save whether the block is a statement or a value. + // Save whether there is an 'AT' input. + var container = document.createElement('mutation'); + var isStatement = !this.outputConnection; + container.setAttribute('statement', isStatement); + var isAt = this.getInput('AT').type == Blockly.INPUT_VALUE; + container.setAttribute('at', isAt); + return container; + }, + domToMutation: function(xmlElement) { + // Restore the block shape. + // Note: Until January 2013 this block did not have mutations, + // so 'statement' defaults to false and 'at' defaults to true. + var isStatement = (xmlElement.getAttribute('statement') == 'true'); + this.updateStatement(isStatement); + var isAt = (xmlElement.getAttribute('at') != 'false'); + this.updateAt(isAt); + }, + updateStatement: function(newStatement) { + // Switch between a value block and a statement block. + var oldStatement = !this.outputConnection; + if (newStatement != oldStatement) { + this.unplug(true, true); + if (newStatement) { + this.setOutput(false); + this.setPreviousStatement(true); + this.setNextStatement(true); + } else { + this.setPreviousStatement(false); + this.setNextStatement(false); + this.setOutput(true); + } + } + }, + updateAt: function(isAt) { + // Create or delete an input for the numeric index. + // Destroy old 'AT' and 'ORDINAL' inputs. + this.removeInput('AT'); + this.removeInput('ORDINAL', true); + // Create either a value 'AT' input or a dummy input. + if (isAt) { + this.appendValueInput('AT').setCheck('Number'); + if (Blockly.Msg.ORDINAL_NUMBER_SUFFIX) { + this.appendDummyInput('ORDINAL') + .appendTitle(Blockly.Msg.ORDINAL_NUMBER_SUFFIX); + } + } else { + this.appendDummyInput('AT'); + } + var menu = new Blockly.FieldDropdown(this.WHERE_OPTIONS, function(value) { + var newAt = (value == 'FROM_START') || (value == 'FROM_END'); + // The 'isAt' variable is available due to this function being a closure. + if (newAt != isAt) { + var block = this.sourceBlock_; + block.updateAt(newAt); + // This menu has been destroyed and replaced. Update the replacement. + block.setTitleValue(value, 'WHERE'); + return null; + } + return undefined; + }); + this.getInput('AT').appendTitle(menu, 'WHERE'); + if (Blockly.Msg.LISTS_GET_INDEX_TAIL) { + this.moveInputBefore('TAIL', null); + } + } +}; + +Blockly.Blocks['lists_setIndex'] = { + // Set element at index. + init: function() { + var MODE = + [[Blockly.Msg.LISTS_SET_INDEX_SET, 'SET'], + [Blockly.Msg.LISTS_SET_INDEX_INSERT, 'INSERT']]; + this.WHERE_OPTIONS = + [[Blockly.Msg.LISTS_GET_INDEX_FROM_START, 'FROM_START'], + [Blockly.Msg.LISTS_GET_INDEX_FROM_END, 'FROM_END'], + [Blockly.Msg.LISTS_GET_INDEX_FIRST, 'FIRST'], + [Blockly.Msg.LISTS_GET_INDEX_LAST, 'LAST'], + [Blockly.Msg.LISTS_GET_INDEX_RANDOM, 'RANDOM']]; + this.setHelpUrl(Blockly.Msg.LISTS_SET_INDEX_HELPURL); + this.setColour(260); + this.appendValueInput('LIST') + .setCheck('Array') + .appendTitle(Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST); + this.appendDummyInput() + .appendTitle(new Blockly.FieldDropdown(MODE), 'MODE') + .appendTitle('', 'SPACE'); + this.appendDummyInput('AT'); + this.appendValueInput('TO') + .appendTitle(Blockly.Msg.LISTS_SET_INDEX_INPUT_TO); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.LISTS_SET_INDEX_TOOLTIP); + this.updateAt(true); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function() { + var combo = thisBlock.getTitleValue('MODE') + '_' + + thisBlock.getTitleValue('WHERE'); + return Blockly.Msg['LISTS_SET_INDEX_TOOLTIP_' + combo]; + }); + }, + mutationToDom: function() { + // Save whether there is an 'AT' input. + var container = document.createElement('mutation'); + var isAt = this.getInput('AT').type == Blockly.INPUT_VALUE; + container.setAttribute('at', isAt); + return container; + }, + domToMutation: function(xmlElement) { + // Restore the block shape. + // Note: Until January 2013 this block did not have mutations, + // so 'at' defaults to true. + var isAt = (xmlElement.getAttribute('at') != 'false'); + this.updateAt(isAt); + }, + updateAt: function(isAt) { + // Create or delete an input for the numeric index. + // Destroy old 'AT' and 'ORDINAL' input. + this.removeInput('AT'); + this.removeInput('ORDINAL', true); + // Create either a value 'AT' input or a dummy input. + if (isAt) { + this.appendValueInput('AT').setCheck('Number'); + if (Blockly.Msg.ORDINAL_NUMBER_SUFFIX) { + this.appendDummyInput('ORDINAL') + .appendTitle(Blockly.Msg.ORDINAL_NUMBER_SUFFIX); + } + } else { + this.appendDummyInput('AT'); + } + var menu = new Blockly.FieldDropdown(this.WHERE_OPTIONS, function(value) { + var newAt = (value == 'FROM_START') || (value == 'FROM_END'); + // The 'isAt' variable is available due to this function being a closure. + if (newAt != isAt) { + var block = this.sourceBlock_; + block.updateAt(newAt); + // This menu has been destroyed and replaced. Update the replacement. + block.setTitleValue(value, 'WHERE'); + return null; + } + return undefined; + }); + this.moveInputBefore('AT', 'TO'); + if (this.getInput('ORDINAL')) { + this.moveInputBefore('ORDINAL', 'TO'); + } + + this.getInput('AT').appendTitle(menu, 'WHERE'); + } +}; + +Blockly.Blocks['lists_getSublist'] = { + // Get sublist. + init: function() { + this.WHERE_OPTIONS_1 = + [[Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START, 'FROM_START'], + [Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END, 'FROM_END'], + [Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST, 'FIRST']]; + this.WHERE_OPTIONS_2 = + [[Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START, 'FROM_START'], + [Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END, 'FROM_END'], + [Blockly.Msg.LISTS_GET_SUBLIST_END_LAST, 'LAST']]; + this.setHelpUrl(Blockly.Msg.LISTS_GET_SUBLIST_HELPURL); + this.setColour(260); + this.appendValueInput('LIST') + .setCheck('Array') + .appendTitle(Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST); + this.appendDummyInput('AT1'); + this.appendDummyInput('AT2'); + if (Blockly.Msg.LISTS_GET_SUBLIST_TAIL) { + this.appendDummyInput('TAIL') + .appendTitle(Blockly.Msg.LISTS_GET_SUBLIST_TAIL); + } + this.setInputsInline(true); + this.setOutput(true, 'Array'); + this.updateAt(1, true); + this.updateAt(2, true); + this.setTooltip(Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP); + }, + mutationToDom: function() { + // Save whether there are 'AT' inputs. + var container = document.createElement('mutation'); + var isAt1 = this.getInput('AT1').type == Blockly.INPUT_VALUE; + container.setAttribute('at1', isAt1); + var isAt2 = this.getInput('AT2').type == Blockly.INPUT_VALUE; + container.setAttribute('at2', isAt2); + return container; + }, + domToMutation: function(xmlElement) { + // Restore the block shape. + var isAt1 = (xmlElement.getAttribute('at1') == 'true'); + var isAt2 = (xmlElement.getAttribute('at2') == 'true'); + this.updateAt(1, isAt1); + this.updateAt(2, isAt2); + }, + updateAt: function(n, isAt) { + // Create or delete an input for the numeric index. + // Destroy old 'AT' and 'ORDINAL' inputs. + this.removeInput('AT' + n); + this.removeInput('ORDINAL' + n, true); + // Create either a value 'AT' input or a dummy input. + if (isAt) { + this.appendValueInput('AT' + n).setCheck('Number'); + if (Blockly.Msg.ORDINAL_NUMBER_SUFFIX) { + this.appendDummyInput('ORDINAL' + n) + .appendTitle(Blockly.Msg.ORDINAL_NUMBER_SUFFIX); + } + } else { + this.appendDummyInput('AT' + n); + } + var menu = new Blockly.FieldDropdown(this['WHERE_OPTIONS_' + n], + function(value) { + var newAt = (value == 'FROM_START') || (value == 'FROM_END'); + // The 'isAt' variable is available due to this function being a closure. + if (newAt != isAt) { + var block = this.sourceBlock_; + block.updateAt(n, newAt); + // This menu has been destroyed and replaced. Update the replacement. + block.setTitleValue(value, 'WHERE' + n); + return null; + } + return undefined; + }); + this.getInput('AT' + n) + .appendTitle(menu, 'WHERE' + n); + if (n == 1) { + this.moveInputBefore('AT1', 'AT2'); + if (this.getInput('ORDINAL1')) { + this.moveInputBefore('ORDINAL1', 'AT2'); + } + } + if (Blockly.Msg.LISTS_GET_SUBLIST_TAIL) { + this.moveInputBefore('TAIL', null); + } + } +}; diff --git a/blocks/logic.js b/blocks/logic.js new file mode 100644 index 000000000..46b098420 --- /dev/null +++ b/blocks/logic.js @@ -0,0 +1,350 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Logic blocks for Blockly. + * @author q.neutron@gmail.com (Quynh Neutron) + */ +'use strict'; + +goog.provide('Blockly.Blocks.logic'); + +goog.require('Blockly.Blocks'); + + +Blockly.Blocks['controls_if'] = { + // If/elseif/else condition. + init: function() { + this.setHelpUrl(Blockly.Msg.CONTROLS_IF_HELPURL); + this.setColour(210); + this.appendValueInput('IF0') + .setCheck('Boolean') + .appendTitle(Blockly.Msg.CONTROLS_IF_MSG_IF); + this.appendStatementInput('DO0') + .appendTitle(Blockly.Msg.CONTROLS_IF_MSG_THEN); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setMutator(new Blockly.Mutator(['controls_if_elseif', + 'controls_if_else'])); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function() { + if (!thisBlock.elseifCount_ && !thisBlock.elseCount_) { + return Blockly.Msg.CONTROLS_IF_TOOLTIP_1; + } else if (!thisBlock.elseifCount_ && thisBlock.elseCount_) { + return Blockly.Msg.CONTROLS_IF_TOOLTIP_2; + } else if (thisBlock.elseifCount_ && !thisBlock.elseCount_) { + return Blockly.Msg.CONTROLS_IF_TOOLTIP_3; + } else if (thisBlock.elseifCount_ && thisBlock.elseCount_) { + return Blockly.Msg.CONTROLS_IF_TOOLTIP_4; + } + return ''; + }); + this.elseifCount_ = 0; + this.elseCount_ = 0; + }, + mutationToDom: function() { + if (!this.elseifCount_ && !this.elseCount_) { + return null; + } + var container = document.createElement('mutation'); + if (this.elseifCount_) { + container.setAttribute('elseif', this.elseifCount_); + } + if (this.elseCount_) { + container.setAttribute('else', 1); + } + return container; + }, + domToMutation: function(xmlElement) { + this.elseifCount_ = parseInt(xmlElement.getAttribute('elseif'), 10); + this.elseCount_ = parseInt(xmlElement.getAttribute('else'), 10); + for (var x = 1; x <= this.elseifCount_; x++) { + this.appendValueInput('IF' + x) + .setCheck('Boolean') + .appendTitle(Blockly.Msg.CONTROLS_IF_MSG_ELSEIF); + this.appendStatementInput('DO' + x) + .appendTitle(Blockly.Msg.CONTROLS_IF_MSG_THEN); + } + if (this.elseCount_) { + this.appendStatementInput('ELSE') + .appendTitle(Blockly.Msg.CONTROLS_IF_MSG_ELSE); + } + }, + decompose: function(workspace) { + var containerBlock = new Blockly.Block(workspace, 'controls_if_if'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var x = 1; x <= this.elseifCount_; x++) { + var elseifBlock = new Blockly.Block(workspace, 'controls_if_elseif'); + elseifBlock.initSvg(); + connection.connect(elseifBlock.previousConnection); + connection = elseifBlock.nextConnection; + } + if (this.elseCount_) { + var elseBlock = new Blockly.Block(workspace, 'controls_if_else'); + elseBlock.initSvg(); + connection.connect(elseBlock.previousConnection); + } + return containerBlock; + }, + compose: function(containerBlock) { + // Disconnect the else input blocks and remove the inputs. + if (this.elseCount_) { + this.removeInput('ELSE'); + } + this.elseCount_ = 0; + // Disconnect all the elseif input blocks and remove the inputs. + for (var x = this.elseifCount_; x > 0; x--) { + this.removeInput('IF' + x); + this.removeInput('DO' + x); + } + this.elseifCount_ = 0; + // Rebuild the block's optional inputs. + var clauseBlock = containerBlock.getInputTargetBlock('STACK'); + while (clauseBlock) { + switch (clauseBlock.type) { + case 'controls_if_elseif': + this.elseifCount_++; + var ifInput = this.appendValueInput('IF' + this.elseifCount_) + .setCheck('Boolean') + .appendTitle(Blockly.Msg.CONTROLS_IF_MSG_ELSEIF); + var doInput = this.appendStatementInput('DO' + this.elseifCount_); + doInput.appendTitle(Blockly.Msg.CONTROLS_IF_MSG_THEN); + // Reconnect any child blocks. + if (clauseBlock.valueConnection_) { + ifInput.connection.connect(clauseBlock.valueConnection_); + } + if (clauseBlock.statementConnection_) { + doInput.connection.connect(clauseBlock.statementConnection_); + } + break; + case 'controls_if_else': + this.elseCount_++; + var elseInput = this.appendStatementInput('ELSE'); + elseInput.appendTitle(Blockly.Msg.CONTROLS_IF_MSG_ELSE); + // Reconnect any child blocks. + if (clauseBlock.statementConnection_) { + elseInput.connection.connect(clauseBlock.statementConnection_); + } + break; + default: + throw 'Unknown block type.'; + } + clauseBlock = clauseBlock.nextConnection && + clauseBlock.nextConnection.targetBlock(); + } + }, + saveConnections: function(containerBlock) { + // Store a pointer to any connected child blocks. + var clauseBlock = containerBlock.getInputTargetBlock('STACK'); + var x = 1; + while (clauseBlock) { + switch (clauseBlock.type) { + case 'controls_if_elseif': + var inputIf = this.getInput('IF' + x); + var inputDo = this.getInput('DO' + x); + clauseBlock.valueConnection_ = + inputIf && inputIf.connection.targetConnection; + clauseBlock.statementConnection_ = + inputDo && inputDo.connection.targetConnection; + x++; + break; + case 'controls_if_else': + var inputDo = this.getInput('ELSE'); + clauseBlock.statementConnection_ = + inputDo && inputDo.connection.targetConnection; + break; + default: + throw 'Unknown block type.'; + } + clauseBlock = clauseBlock.nextConnection && + clauseBlock.nextConnection.targetBlock(); + } + } +}; + +Blockly.Blocks['controls_if_if'] = { + // If condition. + init: function() { + this.setColour(210); + this.appendDummyInput() + .appendTitle(Blockly.Msg.CONTROLS_IF_IF_TITLE_IF); + this.appendStatementInput('STACK'); + this.setTooltip(Blockly.Msg.CONTROLS_IF_IF_TOOLTIP); + this.contextMenu = false; + } +}; + +Blockly.Blocks['controls_if_elseif'] = { + // Else-If condition. + init: function() { + this.setColour(210); + this.appendDummyInput() + .appendTitle(Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP); + this.contextMenu = false; + } +}; + +Blockly.Blocks['controls_if_else'] = { + // Else condition. + init: function() { + this.setColour(210); + this.appendDummyInput() + .appendTitle(Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE); + this.setPreviousStatement(true); + this.setTooltip(Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP); + this.contextMenu = false; + } +}; + +Blockly.Blocks['logic_compare'] = { + // Comparison operator. + init: function() { + if (Blockly.RTL) { + var OPERATORS = [ + ['=', 'EQ'], + ['\u2260', 'NEQ'], + ['>', 'LT'], + ['\u2265', 'LTE'], + ['<', 'GT'], + ['\u2264', 'GTE'] + ]; + } else { + var OPERATORS = [ + ['=', 'EQ'], + ['\u2260', 'NEQ'], + ['<', 'LT'], + ['\u2264', 'LTE'], + ['>', 'GT'], + ['\u2265', 'GTE'] + ]; + } + this.setHelpUrl(Blockly.Msg.LOGIC_COMPARE_HELPURL); + this.setColour(210); + this.setOutput(true, 'Boolean'); + this.appendValueInput('A'); + this.appendValueInput('B') + .appendTitle(new Blockly.FieldDropdown(OPERATORS), 'OP'); + this.setInputsInline(true); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function() { + var op = thisBlock.getTitleValue('OP'); + var TOOLTIPS = { + EQ: Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ, + NEQ: Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ, + LT: Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT, + LTE: Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE, + GT: Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT, + GTE: Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE + }; + return TOOLTIPS[op]; + }); + } +}; + +Blockly.Blocks['logic_operation'] = { + // Logical operations: 'and', 'or'. + init: function() { + var OPERATORS = + [[Blockly.Msg.LOGIC_OPERATION_AND, 'AND'], + [Blockly.Msg.LOGIC_OPERATION_OR, 'OR']]; + this.setHelpUrl(Blockly.Msg.LOGIC_OPERATION_HELPURL); + this.setColour(210); + this.setOutput(true, 'Boolean'); + this.appendValueInput('A') + .setCheck('Boolean'); + this.appendValueInput('B') + .setCheck('Boolean') + .appendTitle(new Blockly.FieldDropdown(OPERATORS), 'OP'); + this.setInputsInline(true); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function() { + var op = thisBlock.getTitleValue('OP'); + var TOOLTIPS = { + AND: Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND, + OR: Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR + }; + return thisBlock.TOOLTIPS[op]; + }); + } +}; + + +Blockly.Blocks['logic_negate'] = { + // Negation. + init: function() { + this.setHelpUrl(Blockly.Msg.LOGIC_NEGATE_HELPURL); + this.setColour(210); + this.setOutput(true, 'Boolean'); + this.interpolateMsg(Blockly.Msg.LOGIC_NEGATE_TITLE, + ['BOOL', 'Boolean', Blockly.ALIGN_RIGHT], + Blockly.ALIGN_RIGHT) + this.setTooltip(Blockly.Msg.LOGIC_NEGATE_TOOLTIP); + } +}; + +Blockly.Blocks['logic_boolean'] = { + // Boolean data type: true and false. + init: function() { + var BOOLEANS = + [[Blockly.Msg.LOGIC_BOOLEAN_TRUE, 'TRUE'], + [Blockly.Msg.LOGIC_BOOLEAN_FALSE, 'FALSE']]; + this.setHelpUrl(Blockly.Msg.LOGIC_BOOLEAN_HELPURL); + this.setColour(210); + this.setOutput(true, 'Boolean'); + this.appendDummyInput() + .appendTitle(new Blockly.FieldDropdown(BOOLEANS), 'BOOL'); + this.setTooltip(Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP); + } +}; + +Blockly.Blocks['logic_null'] = { + // Null data type. + init: function() { + this.setHelpUrl(Blockly.Msg.LOGIC_NULL_HELPURL); + this.setColour(210); + this.setOutput(true); + this.appendDummyInput() + .appendTitle(Blockly.Msg.LOGIC_NULL); + this.setTooltip(Blockly.Msg.LOGIC_NULL_TOOLTIP); + } +}; + +Blockly.Blocks['logic_ternary'] = { + // Ternary operator. + init: function() { + this.setHelpUrl(Blockly.Msg.LOGIC_TERNARY_HELPURL); + this.setColour(210); + this.appendValueInput('IF') + .setCheck('Boolean') + .appendTitle(Blockly.Msg.LOGIC_TERNARY_CONDITION); + this.appendValueInput('THEN') + .appendTitle(Blockly.Msg.LOGIC_TERNARY_IF_TRUE); + this.appendValueInput('ELSE') + .appendTitle(Blockly.Msg.LOGIC_TERNARY_IF_FALSE); + this.setOutput(true); + this.setTooltip(Blockly.Msg.LOGIC_TERNARY_TOOLTIP); + } +}; diff --git a/blocks/loops.js b/blocks/loops.js new file mode 100644 index 000000000..22a5ddd18 --- /dev/null +++ b/blocks/loops.js @@ -0,0 +1,224 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Loop blocks for Blockly. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Blocks.loops'); + +goog.require('Blockly.Blocks'); + + +Blockly.Blocks['controls_repeat'] = { + // Repeat n times (internal number). + init: function() { + this.setHelpUrl(Blockly.Msg.CONTROLS_REPEAT_HELPURL); + this.setColour(120); + this.appendDummyInput() + .appendTitle(Blockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT) + .appendTitle(new Blockly.FieldTextInput('10', + Blockly.FieldTextInput.nonnegativeIntegerValidator), 'TIMES') + .appendTitle(Blockly.Msg.CONTROLS_REPEAT_TITLE_TIMES); + this.appendStatementInput('DO') + .appendTitle(Blockly.Msg.CONTROLS_REPEAT_INPUT_DO); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.CONTROLS_REPEAT_TOOLTIP); + } +}; + +Blockly.Blocks['controls_repeat_ext'] = { + // Repeat n times (external number). + init: function() { + this.setHelpUrl(Blockly.Msg.CONTROLS_REPEAT_HELPURL); + this.setColour(120); + this.interpolateMsg(Blockly.Msg.CONTROLS_REPEAT_TITLE, + ['TIMES', 'Number', Blockly.ALIGN_RIGHT], + Blockly.ALIGN_RIGHT); + this.appendStatementInput('DO') + .appendTitle(Blockly.Msg.CONTROLS_REPEAT_INPUT_DO); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.CONTROLS_REPEAT_TOOLTIP); + } +}; + +Blockly.Blocks['controls_whileUntil'] = { + // Do while/until loop. + init: function() { + var OPERATORS = + [[Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE, 'WHILE'], + [Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL, 'UNTIL']]; + this.setHelpUrl(Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL); + this.setColour(120); + this.appendValueInput('BOOL') + .setCheck('Boolean') + .appendTitle(new Blockly.FieldDropdown(OPERATORS), 'MODE'); + this.appendStatementInput('DO') + .appendTitle(Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO); + this.setPreviousStatement(true); + this.setNextStatement(true); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function() { + var op = thisBlock.getTitleValue('MODE'); + var TOOLTIPS = { + WHILE: Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE, + UNTIL: Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL + }; + return TOOLTIPS[op]; + }); + } +}; + +Blockly.Blocks['controls_for'] = { + // For loop. + init: function() { + this.setHelpUrl(Blockly.Msg.CONTROLS_FOR_HELPURL); + this.setColour(120); + this.appendDummyInput() + .appendTitle(Blockly.Msg.CONTROLS_FOR_INPUT_WITH) + .appendTitle(new Blockly.FieldVariable(null), 'VAR'); + this.interpolateMsg(Blockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY, + ['FROM', 'Number', Blockly.ALIGN_RIGHT], + ['TO', 'Number', Blockly.ALIGN_RIGHT], + ['BY', 'Number', Blockly.ALIGN_RIGHT], + Blockly.ALIGN_RIGHT); + this.appendStatementInput('DO') + .appendTitle(Blockly.Msg.CONTROLS_FOR_INPUT_DO); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function() { + return Blockly.Msg.CONTROLS_FOR_TOOLTIP.replace('%1', + thisBlock.getTitleValue('VAR')); + }); + }, + getVars: function() { + return [this.getTitleValue('VAR')]; + }, + renameVar: function(oldName, newName) { + if (Blockly.Names.equals(oldName, this.getTitleValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + }, + customContextMenu: function(options) { + var option = {enabled: true}; + var name = this.getTitleValue('VAR'); + option.text = Blockly.Msg.VARIABLES_SET_CREATE_GET.replace('%1', name); + var xmlTitle = goog.dom.createDom('title', null, name); + xmlTitle.setAttribute('name', 'VAR'); + var xmlBlock = goog.dom.createDom('block', null, xmlTitle); + xmlBlock.setAttribute('type', 'variables_get'); + option.callback = Blockly.ContextMenu.callbackFactory(this, xmlBlock); + options.push(option); + } +}; + +Blockly.Blocks['controls_forEach'] = { + // For each loop. + init: function() { + this.setHelpUrl(Blockly.Msg.CONTROLS_FOREACH_HELPURL); + this.setColour(120); + this.appendValueInput('LIST') + .setCheck('Array') + .appendTitle(Blockly.Msg.CONTROLS_FOREACH_INPUT_ITEM) + .appendTitle(new Blockly.FieldVariable(null), 'VAR') + .appendTitle(Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST); + if (Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL) { + this.appendDummyInput() + .appendTitle(Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL); + this.setInputsInline(true); + } + this.appendStatementInput('DO') + .appendTitle(Blockly.Msg.CONTROLS_FOREACH_INPUT_DO); + this.setPreviousStatement(true); + this.setNextStatement(true); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function() { + return Blockly.Msg.CONTROLS_FOREACH_TOOLTIP.replace('%1', + thisBlock.getTitleValue('VAR')); + }); + }, + getVars: function() { + return [this.getTitleValue('VAR')]; + }, + renameVar: function(oldName, newName) { + if (Blockly.Names.equals(oldName, this.getTitleValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + }, + customContextMenu: Blockly.Blocks['controls_for'].customContextMenu +}; + +Blockly.Blocks['controls_flow_statements'] = { + // Flow statements: continue, break. + init: function() { + var OPERATORS = + [[Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK, 'BREAK'], + [Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE, 'CONTINUE']]; + this.setHelpUrl(Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL); + this.setColour(120); + this.appendDummyInput() + .appendTitle(new Blockly.FieldDropdown(OPERATORS), 'FLOW'); + this.setPreviousStatement(true); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function() { + var op = thisBlock.getTitleValue('FLOW'); + var TOOLTIPS = { + BREAK: Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK, + CONTINUE: Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE + }; + return thisBlock.TOOLTIPS[op]; + }); + }, + onchange: function() { + if (!this.workspace) { + // Block has been deleted. + return; + } + var legal = false; + // Is the block nested in a control statement? + var block = this; + do { + if (block.type == 'controls_repeat' || + block.type == 'controls_repeat_ext' || + block.type == 'controls_forEach' || + block.type == 'controls_for' || + block.type == 'controls_whileUntil') { + legal = true; + break; + } + block = block.getSurroundParent(); + } while (block); + if (legal) { + this.setWarningText(null); + } else { + this.setWarningText(Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING); + } + } +}; diff --git a/blocks/math.js b/blocks/math.js new file mode 100644 index 000000000..6301ea8d9 --- /dev/null +++ b/blocks/math.js @@ -0,0 +1,364 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Math blocks for Blockly. + * @author q.neutron@gmail.com (Quynh Neutron) + */ +'use strict'; + +goog.provide('Blockly.Blocks.math'); + +goog.require('Blockly.Blocks'); + + +Blockly.Blocks['math_number'] = { + // Numeric value. + init: function() { + this.setHelpUrl(Blockly.Msg.MATH_NUMBER_HELPURL); + this.setColour(230); + this.appendDummyInput() + .appendTitle(new Blockly.FieldTextInput('0', + Blockly.FieldTextInput.numberValidator), 'NUM'); + this.setOutput(true, 'Number'); + this.setTooltip(Blockly.Msg.MATH_NUMBER_TOOLTIP); + } +}; + +Blockly.Blocks['math_arithmetic'] = { + // Basic arithmetic operator. + init: function() { + var OPERATORS = + [[Blockly.Msg.MATH_ADDITION_SYMBOL, 'ADD'], + [Blockly.Msg.MATH_SUBTRACTION_SYMBOL, 'MINUS'], + [Blockly.Msg.MATH_MULTIPLICATION_SYMBOL, 'MULTIPLY'], + [Blockly.Msg.MATH_DIVISION_SYMBOL, 'DIVIDE'], + [Blockly.Msg.MATH_POWER_SYMBOL, 'POWER']]; + this.setHelpUrl(Blockly.Msg.MATH_ARITHMETIC_HELPURL); + this.setColour(230); + this.setOutput(true, 'Number'); + this.appendValueInput('A') + .setCheck('Number'); + this.appendValueInput('B') + .setCheck('Number') + .appendTitle(new Blockly.FieldDropdown(OPERATORS), 'OP'); + this.setInputsInline(true); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function() { + var mode = thisBlock.getTitleValue('OP'); + var TOOLTIPS = { + ADD: Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD, + MINUS: Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS, + MULTIPLY: Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY, + DIVIDE: Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE, + POWER: Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER + }; + return TOOLTIPS[mode]; + }); + } +}; + +Blockly.Blocks['math_single'] = { + // Advanced math operators with single operand. + init: function() { + var OPERATORS = + [[Blockly.Msg.MATH_SINGLE_OP_ROOT, 'ROOT'], + [Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE, 'ABS'], + ['-', 'NEG'], + ['ln', 'LN'], + ['log10', 'LOG10'], + ['e^', 'EXP'], + ['10^', 'POW10']]; + this.setHelpUrl(Blockly.Msg.MATH_SINGLE_HELPURL); + this.setColour(230); + this.setOutput(true, 'Number'); + this.appendValueInput('NUM') + .setCheck('Number') + .appendTitle(new Blockly.FieldDropdown(OPERATORS), 'OP'); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function() { + var mode = thisBlock.getTitleValue('OP'); + var TOOLTIPS = { + ROOT: Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT, + ABS: Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS, + NEG: Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG, + LN: Blockly.Msg.MATH_SINGLE_TOOLTIP_LN, + LOG10: Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10, + EXP: Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP, + POW10: Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 + }; + return TOOLTIPS[mode]; + }); + } +}; + +Blockly.Blocks['math_trig'] = { + // Trigonometry operators. + init: function() { + var OPERATORS = + [[Blockly.Msg.MATH_TRIG_SIN, 'SIN'], + [Blockly.Msg.MATH_TRIG_COS, 'COS'], + [Blockly.Msg.MATH_TRIG_TAN, 'TAN'], + [Blockly.Msg.MATH_TRIG_ASIN, 'ASIN'], + [Blockly.Msg.MATH_TRIG_ACOS, 'ACOS'], + [Blockly.Msg.MATH_TRIG_ATAN, 'ATAN']]; + this.setHelpUrl(Blockly.Msg.MATH_TRIG_HELPURL); + this.setColour(230); + this.setOutput(true, 'Number'); + this.appendValueInput('NUM') + .setCheck('Number') + .appendTitle(new Blockly.FieldDropdown(OPERATORS), 'OP'); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function() { + var mode = thisBlock.getTitleValue('OP'); + var TOOLTIPS = { + SIN: Blockly.Msg.MATH_TRIG_TOOLTIP_SIN, + COS: Blockly.Msg.MATH_TRIG_TOOLTIP_COS, + TAN: Blockly.Msg.MATH_TRIG_TOOLTIP_TAN, + ASIN: Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN, + ACOS: Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS, + ATAN: Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN + }; + return TOOLTIPS[mode]; + }); + } +}; + +Blockly.Blocks['math_constant'] = { + // Constants: PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), INFINITY. + init: function() { + var CONSTANTS = + [['\u03c0', 'PI'], + ['e', 'E'], + ['\u03c6', 'GOLDEN_RATIO'], + ['sqrt(2)', 'SQRT2'], + ['sqrt(\u00bd)', 'SQRT1_2'], + ['\u221e', 'INFINITY']]; + this.setHelpUrl(Blockly.Msg.MATH_CONSTANT_HELPURL); + this.setColour(230); + this.setOutput(true, 'Number'); + this.appendDummyInput() + .appendTitle(new Blockly.FieldDropdown(CONSTANTS), 'CONSTANT'); + this.setTooltip(Blockly.Msg.MATH_CONSTANT_TOOLTIP); + } +}; + +Blockly.Blocks['math_number_property'] = { + // Check if a number is even, odd, prime, whole, positive, or negative + // or if it is divisible by certain number. Returns true or false. + init: function() { + var PROPERTIES = + [[Blockly.Msg.MATH_IS_EVEN, 'EVEN'], + [Blockly.Msg.MATH_IS_ODD, 'ODD'], + [Blockly.Msg.MATH_IS_PRIME, 'PRIME'], + [Blockly.Msg.MATH_IS_WHOLE, 'WHOLE'], + [Blockly.Msg.MATH_IS_POSITIVE, 'POSITIVE'], + [Blockly.Msg.MATH_IS_NEGATIVE, 'NEGATIVE'], + [Blockly.Msg.MATH_IS_DIVISIBLE_BY, 'DIVISIBLE_BY']]; + this.setColour(230); + this.appendValueInput('NUMBER_TO_CHECK') + .setCheck('Number'); + var dropdown = new Blockly.FieldDropdown(PROPERTIES, function(option) { + var divisorInput = (option == 'DIVISIBLE_BY'); + this.sourceBlock_.updateShape(divisorInput); + }); + this.appendDummyInput() + .appendTitle(dropdown, 'PROPERTY'); + this.setInputsInline(true); + this.setOutput(true, 'Boolean'); + this.setTooltip(Blockly.Msg.MATH_IS_TOOLTIP); + }, + mutationToDom: function() { + // Save whether the 'divisorInput' should be true of false (present or not). + var container = document.createElement('mutation'); + var divisorInput = (this.getTitleValue('PROPERTY') == 'DIVISIBLE_BY'); + container.setAttribute('divisor_input', divisorInput); + return container; + }, + domToMutation: function(xmlElement) { + // Restore the 'divisorInput'. + var divisorInput = (xmlElement.getAttribute('divisor_input') == 'true'); + this.updateShape(divisorInput); + }, + updateShape: function(divisorInput) { + // Add or remove a Value Input. + var inputExists = this.getInput('DIVISOR'); + if (divisorInput) { + if (!inputExists) { + this.appendValueInput('DIVISOR') + .setCheck('Number'); + } + } else if (inputExists) { + this.removeInput('DIVISOR'); + } + } +}; + +Blockly.Blocks['math_change'] = { + // Add to a variable in place. + init: function() { + this.setHelpUrl(Blockly.Msg.MATH_CHANGE_HELPURL); + this.setColour(230); + this.appendValueInput('DELTA') + .setCheck('Number') + .appendTitle(Blockly.Msg.MATH_CHANGE_TITLE_CHANGE) + .appendTitle(new Blockly.FieldVariable( + Blockly.Msg.MATH_CHANGE_TITLE_ITEM), 'VAR') + .appendTitle(Blockly.Msg.MATH_CHANGE_INPUT_BY); + this.setPreviousStatement(true); + this.setNextStatement(true); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function() { + return Blockly.Msg.MATH_CHANGE_TOOLTIP.replace('%1', + thisBlock.getTitleValue('VAR')); + }); + }, + getVars: function() { + return [this.getTitleValue('VAR')]; + }, + renameVar: function(oldName, newName) { + if (Blockly.Names.equals(oldName, this.getTitleValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + } +}; + +Blockly.Blocks['math_round'] = { + // Rounding functions. + init: function() { + var OPERATORS = + [[Blockly.Msg.MATH_ROUND_OPERATOR_ROUND, 'ROUND'], + [Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP, 'ROUNDUP'], + [Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN, 'ROUNDDOWN']]; + this.setHelpUrl(Blockly.Msg.MATH_ROUND_HELPURL); + this.setColour(230); + this.setOutput(true, 'Number'); + this.appendValueInput('NUM') + .setCheck('Number') + .appendTitle(new Blockly.FieldDropdown(OPERATORS), 'OP'); + this.setTooltip(Blockly.Msg.MATH_ROUND_TOOLTIP); + } +}; + +Blockly.Blocks['math_on_list'] = { + // Evaluate a list of numbers to return sum, average, min, max, etc. + // Some functions also work on text (min, max, mode, median). + init: function() { + var OPERATORS = + [[Blockly.Msg.MATH_ONLIST_OPERATOR_SUM, 'SUM'], + [Blockly.Msg.MATH_ONLIST_OPERATOR_MIN, 'MIN'], + [Blockly.Msg.MATH_ONLIST_OPERATOR_MAX, 'MAX'], + [Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE, 'AVERAGE'], + [Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN, 'MEDIAN'], + [Blockly.Msg.MATH_ONLIST_OPERATOR_MODE, 'MODE'], + [Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV, 'STD_DEV'], + [Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM, 'RANDOM']]; + // Assign 'this' to a variable for use in the closure below. + var thisBlock = this; + this.setHelpUrl(Blockly.Msg.MATH_ONLIST_HELPURL); + this.setColour(230); + this.setOutput(true, 'Number'); + var dropdown = new Blockly.FieldDropdown(OPERATORS, function(newOp) { + if (newOp == 'MODE') { + thisBlock.outputConnection.setCheck('Array'); + } else { + thisBlock.outputConnection.setCheck('Number'); + } + }); + this.appendValueInput('LIST') + .setCheck('Array') + .appendTitle(dropdown, 'OP'); + this.setTooltip(function() { + var mode = thisBlock.getTitleValue('OP'); + var TOOLTIPS = { + SUM: Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM, + MIN: Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN, + MAX: Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX, + AVERAGE: Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE, + MEDIAN: Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN, + MODE: Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE, + STD_DEV: Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV, + RANDOM: Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM + }; + return TOOLTIPS[mode]; + }); + } +}; + +Blockly.Blocks['math_modulo'] = { + // Remainder of a division. + init: function() { + this.setHelpUrl(Blockly.Msg.MATH_MODULO_HELPURL); + this.setColour(230); + this.setOutput(true, 'Number'); + this.interpolateMsg(Blockly.Msg.MATH_MODULO_TITLE, + ['DIVIDEND', 'Number', Blockly.ALIGN_RIGHT], + ['DIVISOR', 'Number', Blockly.ALIGN_RIGHT], + Blockly.ALIGN_RIGHT); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MATH_MODULO_TOOLTIP); + } +}; + +Blockly.Blocks['math_constrain'] = { + // Constrain a number between two limits. + init: function() { + this.setHelpUrl(Blockly.Msg.MATH_CONSTRAIN_HELPURL); + this.setColour(230); + this.setOutput(true, 'Number'); + this.interpolateMsg(Blockly.Msg.MATH_CONSTRAIN_TITLE, + ['VALUE', 'Number', Blockly.ALIGN_RIGHT], + ['LOW', 'Number', Blockly.ALIGN_RIGHT], + ['HIGH', 'Number', Blockly.ALIGN_RIGHT], + Blockly.ALIGN_RIGHT) + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MATH_CONSTRAIN_TOOLTIP); + } +}; + +Blockly.Blocks['math_random_int'] = { + // Random integer between [X] and [Y]. + init: function() { + this.setHelpUrl(Blockly.Msg.MATH_RANDOM_INT_HELPURL); + this.setColour(230); + this.setOutput(true, 'Number'); + this.interpolateMsg(Blockly.Msg.MATH_RANDOM_INT_TITLE, + ['FROM', 'Number', Blockly.ALIGN_RIGHT], + ['TO', 'Number', Blockly.ALIGN_RIGHT], + Blockly.ALIGN_RIGHT); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MATH_RANDOM_INT_TOOLTIP); + } +}; + +Blockly.Blocks['math_random_float'] = { + // Random fraction between 0 and 1. + init: function() { + this.setHelpUrl(Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL); + this.setColour(230); + this.setOutput(true, 'Number'); + this.appendDummyInput() + .appendTitle(Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM); + this.setTooltip(Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP); + } +}; diff --git a/blocks/procedures.js b/blocks/procedures.js new file mode 100644 index 000000000..68edbb092 --- /dev/null +++ b/blocks/procedures.js @@ -0,0 +1,517 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Procedure blocks for Blockly. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Blocks.procedures'); + +goog.require('Blockly.Blocks'); + + +Blockly.Blocks['procedures_defnoreturn'] = { + // Define a procedure with no return value. + init: function() { + this.setHelpUrl(Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL); + this.setColour(290); + var name = Blockly.Procedures.findLegalName( + Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE, this); + this.appendDummyInput() + .appendTitle(Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE) + .appendTitle(new Blockly.FieldTextInput(name, + Blockly.Procedures.rename), 'NAME') + .appendTitle('', 'PARAMS'); + this.appendStatementInput('STACK') + .appendTitle(Blockly.Msg.PROCEDURES_DEFNORETURN_DO); + this.setMutator(new Blockly.Mutator(['procedures_mutatorarg'])); + this.setTooltip(Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP); + this.arguments_ = []; + }, + updateParams_: function() { + // Check for duplicated arguments. + var badArg = false; + var hash = {}; + for (var x = 0; x < this.arguments_.length; x++) { + if (hash['arg_' + this.arguments_[x].toLowerCase()]) { + badArg = true; + break; + } + hash['arg_' + this.arguments_[x].toLowerCase()] = true; + } + if (badArg) { + this.setWarningText(Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING); + } else { + this.setWarningText(null); + } + // Merge the arguments into a human-readable list. + var paramString = ''; + if (this.arguments_.length) { + paramString = Blockly.Msg.PROCEDURES_BEFORE_PARAMS + + ' ' + this.arguments_.join(', '); + } + this.setTitleValue(paramString, 'PARAMS'); + }, + mutationToDom: function() { + var container = document.createElement('mutation'); + for (var x = 0; x < this.arguments_.length; x++) { + var parameter = document.createElement('arg'); + parameter.setAttribute('name', this.arguments_[x]); + container.appendChild(parameter); + } + return container; + }, + domToMutation: function(xmlElement) { + this.arguments_ = []; + for (var x = 0, childNode; childNode = xmlElement.childNodes[x]; x++) { + if (childNode.nodeName.toLowerCase() == 'arg') { + this.arguments_.push(childNode.getAttribute('name')); + } + } + this.updateParams_(); + }, + decompose: function(workspace) { + var containerBlock = new Blockly.Block(workspace, + 'procedures_mutatorcontainer'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var x = 0; x < this.arguments_.length; x++) { + var paramBlock = new Blockly.Block(workspace, 'procedures_mutatorarg'); + paramBlock.initSvg(); + paramBlock.setTitleValue(this.arguments_[x], 'NAME'); + // Store the old location. + paramBlock.oldLocation = x; + connection.connect(paramBlock.previousConnection); + connection = paramBlock.nextConnection; + } + // Initialize procedure's callers with blank IDs. + Blockly.Procedures.mutateCallers(this.getTitleValue('NAME'), + this.workspace, this.arguments_, null); + return containerBlock; + }, + compose: function(containerBlock) { + this.arguments_ = []; + this.paramIds_ = []; + var paramBlock = containerBlock.getInputTargetBlock('STACK'); + while (paramBlock) { + this.arguments_.push(paramBlock.getTitleValue('NAME')); + this.paramIds_.push(paramBlock.id); + paramBlock = paramBlock.nextConnection && + paramBlock.nextConnection.targetBlock(); + } + this.updateParams_(); + Blockly.Procedures.mutateCallers(this.getTitleValue('NAME'), + this.workspace, this.arguments_, this.paramIds_); + }, + dispose: function() { + // Dispose of any callers. + var name = this.getTitleValue('NAME'); + Blockly.Procedures.disposeCallers(name, this.workspace); + // Call parent's destructor. + Blockly.Block.prototype.dispose.apply(this, arguments); + }, + getProcedureDef: function() { + // Return the name of the defined procedure, + // a list of all its arguments, + // and that it DOES NOT have a return value. + return [this.getTitleValue('NAME'), this.arguments_, false]; + }, + getVars: function() { + return this.arguments_; + }, + renameVar: function(oldName, newName) { + var change = false; + for (var x = 0; x < this.arguments_.length; x++) { + if (Blockly.Names.equals(oldName, this.arguments_[x])) { + this.arguments_[x] = newName; + change = true; + } + } + if (change) { + this.updateParams_(); + // Update the mutator's variables if the mutator is open. + if (this.mutator.isVisible_()) { + var blocks = this.mutator.workspace_.getAllBlocks(); + for (var x = 0, block; block = blocks[x]; x++) { + if (block.type == 'procedures_mutatorarg' && + Blockly.Names.equals(oldName, block.getTitleValue('NAME'))) { + block.setTitleValue(newName, 'NAME'); + } + } + } + } + }, + customContextMenu: function(options) { + // Add option to create caller. + var option = {enabled: true}; + var name = this.getTitleValue('NAME'); + option.text = Blockly.Msg.PROCEDURES_CREATE_DO.replace('%1', name); + + var xmlMutation = goog.dom.createDom('mutation'); + xmlMutation.setAttribute('name', name); + for (var x = 0; x < this.arguments_.length; x++) { + var xmlArg = goog.dom.createDom('arg'); + xmlArg.setAttribute('name', this.arguments_[x]); + xmlMutation.appendChild(xmlArg); + } + var xmlBlock = goog.dom.createDom('block', null, xmlMutation); + xmlBlock.setAttribute('type', this.callType_); + option.callback = Blockly.ContextMenu.callbackFactory(this, xmlBlock); + + options.push(option); + // Add options to create getters for each parameter. + for (var x = 0; x < this.arguments_.length; x++) { + var option = {enabled: true}; + var name = this.arguments_[x]; + option.text = Blockly.Msg.VARIABLES_SET_CREATE_GET.replace('%1', name); + var xmlTitle = goog.dom.createDom('title', null, name); + xmlTitle.setAttribute('name', 'VAR'); + var xmlBlock = goog.dom.createDom('block', null, xmlTitle); + xmlBlock.setAttribute('type', 'variables_get'); + option.callback = Blockly.ContextMenu.callbackFactory(this, xmlBlock); + options.push(option); + } + }, + callType_: 'procedures_callnoreturn' +}; + +Blockly.Blocks['procedures_defreturn'] = { + // Define a procedure with a return value. + init: function() { + this.setHelpUrl(Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL); + this.setColour(290); + var name = Blockly.Procedures.findLegalName( + Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE, this); + this.appendDummyInput() + .appendTitle(Blockly.Msg.PROCEDURES_DEFRETURN_TITLE) + .appendTitle(new Blockly.FieldTextInput(name, + Blockly.Procedures.rename), 'NAME') + .appendTitle('', 'PARAMS'); + this.appendStatementInput('STACK') + .appendTitle(Blockly.Msg.PROCEDURES_DEFRETURN_DO); + this.appendValueInput('RETURN') + .setAlign(Blockly.ALIGN_RIGHT) + .appendTitle(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN); + this.setMutator(new Blockly.Mutator(['procedures_mutatorarg'])); + this.setTooltip(Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP); + this.arguments_ = []; + }, + updateParams_: Blockly.Blocks['procedures_defnoreturn'].updateParams_, + mutationToDom: Blockly.Blocks['procedures_defnoreturn'].mutationToDom, + domToMutation: Blockly.Blocks['procedures_defnoreturn'].domToMutation, + decompose: Blockly.Blocks['procedures_defnoreturn'].decompose, + compose: Blockly.Blocks['procedures_defnoreturn'].compose, + dispose: Blockly.Blocks['procedures_defnoreturn'].dispose, + getProcedureDef: function() { + // Return the name of the defined procedure, + // a list of all its arguments, + // and that it DOES have a return value. + return [this.getTitleValue('NAME'), this.arguments_, true]; + }, + getVars: Blockly.Blocks['procedures_defnoreturn'].getVars, + renameVar: Blockly.Blocks['procedures_defnoreturn'].renameVar, + customContextMenu: Blockly.Blocks['procedures_defnoreturn'].customContextMenu, + callType_: 'procedures_callreturn' +}; + +Blockly.Blocks['procedures_mutatorcontainer'] = { + // Procedure container (for mutator dialog). + init: function() { + this.setColour(290); + this.appendDummyInput() + .appendTitle(Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE); + this.appendStatementInput('STACK'); + this.setTooltip(''); + this.contextMenu = false; + } +}; + +Blockly.Blocks['procedures_mutatorarg'] = { + // Procedure argument (for mutator dialog). + init: function() { + this.setColour(290); + this.appendDummyInput() + .appendTitle(Blockly.Msg.PROCEDURES_MUTATORARG_TITLE) + .appendTitle(new Blockly.FieldTextInput('x', this.validator), 'NAME'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(''); + this.contextMenu = false; + }, + validator: function(newVar) { + // Merge runs of whitespace. Strip leading and trailing whitespace. + // Beyond this, all names are legal. + newVar = newVar.replace(/[\s\xa0]+/g, ' ').replace(/^ | $/g, ''); + return newVar || null; + } +}; + +Blockly.Blocks['procedures_callnoreturn'] = { + // Call a procedure with no return value. + init: function() { + this.setHelpUrl(Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL); + this.setColour(290); + this.appendDummyInput() + .appendTitle(Blockly.Msg.PROCEDURES_CALLNORETURN_CALL) + .appendTitle('', 'NAME'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP); + this.arguments_ = []; + this.quarkConnections_ = null; + this.quarkArguments_ = null; + }, + getProcedureCall: function() { + return this.getTitleValue('NAME'); + }, + renameProcedure: function(oldName, newName) { + if (Blockly.Names.equals(oldName, this.getTitleValue('NAME'))) { + this.setTitleValue(newName, 'NAME'); + this.setTooltip( + (this.outputConnection ? Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP + : Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP) + .replace('%1', newName)); + } + }, + setProcedureParameters: function(paramNames, paramIds) { + // Data structures for parameters on each call block: + // this.arguments = ['x', 'y'] + // Existing param names. + // paramNames = ['x', 'y', 'z'] + // New param names. + // paramIds = ['piua', 'f8b_', 'oi.o'] + // IDs of params (consistent for each parameter through the life of a + // mutator, regardless of param renaming). + // this.quarkConnections_ {piua: null, f8b_: Blockly.Connection} + // Look-up of paramIds to connections plugged into the call block. + // this.quarkArguments_ = ['piua', 'f8b_'] + // Existing param IDs. + // Note that quarkConnections_ may include IDs that no longer exist, but + // which might reappear if a param is reattached in the mutator. + if (!paramIds) { + // Reset the quarks (a mutator is about to open). + this.quarkConnections_ = {}; + this.quarkArguments_ = null; + return; + } + if (paramIds.length != paramNames.length) { + throw 'Error: paramNames and paramIds must be the same length.'; + } + if (!this.quarkArguments_) { + // Initialize tracking for this block. + this.quarkConnections_ = {}; + if (paramNames.join('\n') == this.arguments_.join('\n')) { + // No change to the parameters, allow quarkConnections_ to be + // populated with the existing connections. + this.quarkArguments_ = paramIds; + } else { + this.quarkArguments_ = []; + } + } + // Switch off rendering while the block is rebuilt. + var savedRendered = this.rendered; + this.rendered = false; + // Update the quarkConnections_ with existing connections. + for (var x = this.arguments_.length - 1; x >= 0; x--) { + var input = this.getInput('ARG' + x); + if (input) { + var connection = input.connection.targetConnection; + this.quarkConnections_[this.quarkArguments_[x]] = connection; + // Disconnect all argument blocks and remove all inputs. + this.removeInput('ARG' + x); + } + } + // Rebuild the block's arguments. + this.arguments_ = [].concat(paramNames); + this.quarkArguments_ = paramIds; + for (var x = 0; x < this.arguments_.length; x++) { + var input = this.appendValueInput('ARG' + x) + .setAlign(Blockly.ALIGN_RIGHT) + .appendTitle(this.arguments_[x]); + if (this.quarkArguments_) { + // Reconnect any child blocks. + var quarkName = this.quarkArguments_[x]; + if (quarkName in this.quarkConnections_) { + var connection = this.quarkConnections_[quarkName]; + if (!connection || connection.targetConnection || + connection.sourceBlock_.workspace != this.workspace) { + // Block no longer exists or has been attached elsewhere. + delete this.quarkConnections_[quarkName]; + } else { + input.connection.connect(connection); + } + } + } + } + // Restore rendering and show the changes. + this.rendered = savedRendered; + if (this.rendered) { + this.render(); + } + }, + mutationToDom: function() { + // Save the name and arguments (none of which are editable). + var container = document.createElement('mutation'); + container.setAttribute('name', this.getTitleValue('NAME')); + for (var x = 0; x < this.arguments_.length; x++) { + var parameter = document.createElement('arg'); + parameter.setAttribute('name', this.arguments_[x]); + container.appendChild(parameter); + } + return container; + }, + domToMutation: function(xmlElement) { + // Restore the name and parameters. + var name = xmlElement.getAttribute('name'); + this.setTitleValue(name, 'NAME'); + this.setTooltip( + (this.outputConnection ? Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP + : Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP).replace('%1', name)); + var def = Blockly.Procedures.getDefinition(name, this.workspace); + if (def && def.mutator.isVisible()) { + // Initialize caller with the mutator's IDs. + this.setProcedureParameters(def.arguments_, def.paramIds_); + } else { + this.arguments_ = []; + for (var x = 0, childNode; childNode = xmlElement.childNodes[x]; x++) { + if (childNode.nodeName.toLowerCase() == 'arg') { + this.arguments_.push(childNode.getAttribute('name')); + } + } + // For the second argument (paramIds) use the arguments list as a dummy + // list. + this.setProcedureParameters(this.arguments_, this.arguments_); + } + }, + renameVar: function(oldName, newName) { + for (var x = 0; x < this.arguments_.length; x++) { + if (Blockly.Names.equals(oldName, this.arguments_[x])) { + this.arguments_[x] = newName; + this.getInput('ARG' + x).titleRow[0].setText(newName); + } + } + }, + customContextMenu: function(options) { + // Add option to find caller. + var option = {enabled: true}; + option.text = Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF; + var name = this.getTitleValue('NAME'); + var workspace = this.workspace; + option.callback = function() { + var def = Blockly.Procedures.getDefinition(name, workspace); + def && def.select(); + }; + options.push(option); + } +}; + +Blockly.Blocks['procedures_callreturn'] = { + // Call a procedure with a return value. + init: function() { + this.setHelpUrl(Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL); + this.setColour(290); + this.appendDummyInput() + .appendTitle(Blockly.Msg.PROCEDURES_CALLRETURN_CALL) + .appendTitle('', 'NAME'); + this.setOutput(true); + this.setTooltip(Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP); + this.arguments_ = []; + this.quarkConnections_ = null; + this.quarkArguments_ = null; + }, + getProcedureCall: Blockly.Blocks['procedures_callnoreturn'].getProcedureCall, + renameProcedure: Blockly.Blocks['procedures_callnoreturn'].renameProcedure, + setProcedureParameters: + Blockly.Blocks['procedures_callnoreturn'].setProcedureParameters, + mutationToDom: Blockly.Blocks['procedures_callnoreturn'].mutationToDom, + domToMutation: Blockly.Blocks['procedures_callnoreturn'].domToMutation, + renameVar: Blockly.Blocks['procedures_callnoreturn'].renameVar, + customContextMenu: Blockly.Blocks['procedures_callnoreturn'].customContextMenu +}; + +Blockly.Blocks['procedures_ifreturn'] = { + // Conditionally return value from a procedure. + init: function() { + this.setHelpUrl('http://c2.com/cgi/wiki?GuardClause'); + this.setColour(290); + this.appendValueInput('CONDITION') + .setCheck('Boolean') + .appendTitle(Blockly.Msg.CONTROLS_IF_MSG_IF); + this.appendValueInput('VALUE') + .appendTitle(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP); + this.hasReturnValue_ = true; + }, + mutationToDom: function() { + // Save whether this block has a return value. + var container = document.createElement('mutation'); + container.setAttribute('value', Number(this.hasReturnValue_)); + return container; + }, + domToMutation: function(xmlElement) { + // Restore whether this block has a return value. + var value = xmlElement.getAttribute('value'); + this.hasReturnValue_ = (value == 1); + if (!this.hasReturnValue_) { + this.removeInput('VALUE'); + this.appendDummyInput('VALUE') + .appendTitle(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN); + } + }, + onchange: function() { + if (!this.workspace) { + // Block has been deleted. + return; + } + var legal = false; + // Is the block nested in a procedure? + var block = this; + do { + if (block.type == 'procedures_defnoreturn' || + block.type == 'procedures_defreturn') { + legal = true; + break; + } + block = block.getSurroundParent(); + } while (block); + if (legal) { + // If needed, toggle whether this block has a return value. + if (block.type == 'procedures_defnoreturn' && this.hasReturnValue_) { + this.removeInput('VALUE'); + this.appendDummyInput('VALUE') + .appendTitle(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN); + this.hasReturnValue_ = false; + } else if (block.type == 'procedures_defreturn' && + !this.hasReturnValue_) { + this.removeInput('VALUE'); + this.appendValueInput('VALUE') + .appendTitle(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN); + this.hasReturnValue_ = true; + } + this.setWarningText(null); + } else { + this.setWarningText(Blockly.Msg.PROCEDURES_IFRETURN_WARNING); + } + } +}; diff --git a/blocks/text.js b/blocks/text.js new file mode 100644 index 000000000..060973081 --- /dev/null +++ b/blocks/text.js @@ -0,0 +1,484 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Text blocks for Blockly. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Blocks.text'); + +goog.require('Blockly.Blocks'); + + +Blockly.Blocks['text'] = { + // Text value. + init: function() { + this.setHelpUrl(Blockly.Msg.TEXT_TEXT_HELPURL); + this.setColour(160); + this.appendDummyInput() + .appendTitle(new Blockly.FieldImage(Blockly.pathToBlockly + + 'media/quote0.png', 12, 12)) + .appendTitle(new Blockly.FieldTextInput(''), 'TEXT') + .appendTitle(new Blockly.FieldImage(Blockly.pathToBlockly + + 'media/quote1.png', 12, 12)); + this.setOutput(true, 'String'); + this.setTooltip(Blockly.Msg.TEXT_TEXT_TOOLTIP); + } +}; + +Blockly.Blocks['text_join'] = { + // Create a string made up of any number of elements of any type. + init: function() { + this.setHelpUrl(Blockly.Msg.TEXT_JOIN_HELPURL); + this.setColour(160); + this.appendValueInput('ADD0') + .appendTitle(Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH); + this.appendValueInput('ADD1'); + this.setOutput(true, 'String'); + this.setMutator(new Blockly.Mutator(['text_create_join_item'])); + this.setTooltip(Blockly.Msg.TEXT_JOIN_TOOLTIP); + this.itemCount_ = 2; + }, + mutationToDom: function() { + var container = document.createElement('mutation'); + container.setAttribute('items', this.itemCount_); + return container; + }, + domToMutation: function(xmlElement) { + for (var x = 0; x < this.itemCount_; x++) { + this.removeInput('ADD' + x); + } + this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); + for (var x = 0; x < this.itemCount_; x++) { + var input = this.appendValueInput('ADD' + x); + if (x == 0) { + input.appendTitle(Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH); + } + } + if (this.itemCount_ == 0) { + this.appendDummyInput('EMPTY') + .appendTitle(new Blockly.FieldImage(Blockly.pathToBlockly + + 'media/quote0.png', 12, 12)) + .appendTitle(new Blockly.FieldImage(Blockly.pathToBlockly + + 'media/quote1.png', 12, 12)); + } + }, + decompose: function(workspace) { + var containerBlock = new Blockly.Block(workspace, + 'text_create_join_container'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var x = 0; x < this.itemCount_; x++) { + var itemBlock = new Blockly.Block(workspace, 'text_create_join_item'); + itemBlock.initSvg(); + connection.connect(itemBlock.previousConnection); + connection = itemBlock.nextConnection; + } + return containerBlock; + }, + compose: function(containerBlock) { + // Disconnect all input blocks and remove all inputs. + if (this.itemCount_ == 0) { + this.removeInput('EMPTY'); + } else { + for (var x = this.itemCount_ - 1; x >= 0; x--) { + this.removeInput('ADD' + x); + } + } + this.itemCount_ = 0; + // Rebuild the block's inputs. + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + while (itemBlock) { + var input = this.appendValueInput('ADD' + this.itemCount_); + if (this.itemCount_ == 0) { + input.appendTitle(Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH); + } + // Reconnect any child blocks. + if (itemBlock.valueConnection_) { + input.connection.connect(itemBlock.valueConnection_); + } + this.itemCount_++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + if (this.itemCount_ == 0) { + this.appendDummyInput('EMPTY') + .appendTitle(new Blockly.FieldImage(Blockly.pathToBlockly + + 'media/quote0.png', 12, 12)) + .appendTitle(new Blockly.FieldImage(Blockly.pathToBlockly + + 'media/quote1.png', 12, 12)); + } + }, + saveConnections: function(containerBlock) { + // Store a pointer to any connected child blocks. + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + var x = 0; + while (itemBlock) { + var input = this.getInput('ADD' + x); + itemBlock.valueConnection_ = input && input.connection.targetConnection; + x++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + } +}; + +Blockly.Blocks['text_create_join_container'] = { + // Container. + init: function() { + this.setColour(160); + this.appendDummyInput() + .appendTitle(Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN); + this.appendStatementInput('STACK'); + this.setTooltip(Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP); + this.contextMenu = false; + } +}; + +Blockly.Blocks['text_create_join_item'] = { + // Add items. + init: function() { + this.setColour(160); + this.appendDummyInput() + .appendTitle(Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP); + this.contextMenu = false; + } +}; + +Blockly.Blocks['text_append'] = { + // Append to a variable in place. + init: function() { + this.setHelpUrl(Blockly.Msg.TEXT_APPEND_HELPURL); + this.setColour(160); + this.appendValueInput('TEXT') + .appendTitle(Blockly.Msg.TEXT_APPEND_TO) + .appendTitle(new Blockly.FieldVariable( + Blockly.Msg.TEXT_APPEND_VARIABLE), 'VAR') + .appendTitle(Blockly.Msg.TEXT_APPEND_APPENDTEXT); + this.setPreviousStatement(true); + this.setNextStatement(true); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function() { + return Blockly.Msg.TEXT_APPEND_TOOLTIP.replace('%1', + thisBlock.getTitleValue('VAR')); + }); + }, + getVars: function() { + return [this.getTitleValue('VAR')]; + }, + renameVar: function(oldName, newName) { + if (Blockly.Names.equals(oldName, this.getTitleValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + } +}; + +Blockly.Blocks['text_length'] = { + // String length. + init: function() { + this.setHelpUrl(Blockly.Msg.TEXT_LENGTH_HELPURL); + this.setColour(160); + this.interpolateMsg(Blockly.Msg.TEXT_LENGTH_TITLE, + ['VALUE', ['String', 'Array'], Blockly.ALIGN_RIGHT], + Blockly.ALIGN_RIGHT); + this.setOutput(true, 'Number'); + this.setTooltip(Blockly.Msg.TEXT_LENGTH_TOOLTIP); + } +}; + +Blockly.Blocks['text_isEmpty'] = { + // Is the string null? + init: function() { + this.setHelpUrl(Blockly.Msg.TEXT_ISEMPTY_HELPURL); + this.setColour(160); + this.interpolateMsg(Blockly.Msg.TEXT_ISEMPTY_TITLE, + ['VALUE', ['String', 'Array'], Blockly.ALIGN_RIGHT], + Blockly.ALIGN_RIGHT); + this.setOutput(true, 'Boolean'); + this.setTooltip(Blockly.Msg.TEXT_ISEMPTY_TOOLTIP); + } +}; + +Blockly.Blocks['text_indexOf'] = { + // Find a substring in the text. + init: function() { + var OPERATORS = + [[Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST, 'FIRST'], + [Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST, 'LAST']]; + this.setHelpUrl(Blockly.Msg.TEXT_INDEXOF_HELPURL); + this.setColour(160); + this.setOutput(true, 'Number'); + this.appendValueInput('VALUE') + .setCheck('String') + .appendTitle(Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT); + this.appendValueInput('FIND') + .setCheck('String') + .appendTitle(new Blockly.FieldDropdown(OPERATORS), 'END'); + if (Blockly.Msg.TEXT_INDEXOF_TAIL) { + this.appendDummyInput().appendTitle(Blockly.Msg.TEXT_INDEXOF_TAIL); + } + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.TEXT_INDEXOF_TOOLTIP); + } +}; + +Blockly.Blocks['text_charAt'] = { + // Get a character from the string. + init: function() { + this.WHERE_OPTIONS = + [[Blockly.Msg.TEXT_CHARAT_FROM_START, 'FROM_START'], + [Blockly.Msg.TEXT_CHARAT_FROM_END, 'FROM_END'], + [Blockly.Msg.TEXT_CHARAT_FIRST, 'FIRST'], + [Blockly.Msg.TEXT_CHARAT_LAST, 'LAST'], + [Blockly.Msg.TEXT_CHARAT_RANDOM, 'RANDOM']]; + this.setHelpUrl(Blockly.Msg.TEXT_CHARAT_HELPURL); + this.setColour(160); + this.setOutput(true, 'String'); + this.appendValueInput('VALUE') + .setCheck('String') + .appendTitle(Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT); + this.appendDummyInput('AT'); + this.setInputsInline(true); + this.updateAt(true); + this.setTooltip(Blockly.Msg.TEXT_CHARAT_TOOLTIP); + }, + mutationToDom: function() { + // Save whether there is an 'AT' input. + var container = document.createElement('mutation'); + var isAt = this.getInput('AT').type == Blockly.INPUT_VALUE; + container.setAttribute('at', isAt); + return container; + }, + domToMutation: function(xmlElement) { + // Restore the 'AT' input. + // Note: Until January 2013 this block did not have mutations, + // so 'at' defaults to true. + var isAt = (xmlElement.getAttribute('at') != 'false'); + this.updateAt(isAt); + }, + updateAt: function(isAt) { + // Create or delete an input for the numeric index. + // Destroy old 'AT' and 'ORDINAL' inputs. + this.removeInput('AT'); + this.removeInput('ORDINAL', true); + // Create either a value 'AT' input or a dummy input. + if (isAt) { + this.appendValueInput('AT').setCheck('Number'); + if (Blockly.Msg.ORDINAL_NUMBER_SUFFIX) { + this.appendDummyInput('ORDINAL') + .appendTitle(Blockly.Msg.ORDINAL_NUMBER_SUFFIX); + } + } else { + this.appendDummyInput('AT'); + } + if (Blockly.Msg.TEXT_CHARAT_TAIL) { + this.removeInput('TAIL', true); + this.appendDummyInput('TAIL') + .appendTitle(Blockly.Msg.TEXT_CHARAT_TAIL); + } + var menu = new Blockly.FieldDropdown(this.WHERE_OPTIONS, function(value) { + var newAt = (value == 'FROM_START') || (value == 'FROM_END'); + // The 'isAt' variable is available due to this function being a closure. + if (newAt != isAt) { + var block = this.sourceBlock_; + block.updateAt(newAt); + // This menu has been destroyed and replaced. Update the replacement. + block.setTitleValue(value, 'WHERE'); + return null; + } + return undefined; + }); + this.getInput('AT').appendTitle(menu, 'WHERE'); + } +}; + +Blockly.Blocks['text_getSubstring'] = { + // Get substring. + init: function() { + this.WHERE_OPTIONS_1 = + [[Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START, 'FROM_START'], + [Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END, 'FROM_END'], + [Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST, 'FIRST']]; + this.WHERE_OPTIONS_2 = + [[Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START, 'FROM_START'], + [Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END, 'FROM_END'], + [Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST, 'LAST']]; + this.setHelpUrl(Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL); + this.setColour(160); + this.appendValueInput('STRING') + .setCheck('String') + .appendTitle(Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT); + this.appendDummyInput('AT1'); + this.appendDummyInput('AT2'); + if (Blockly.Msg.TEXT_GET_SUBSTRING_TAIL) { + this.appendDummyInput('TAIL') + .appendTitle(Blockly.Msg.TEXT_GET_SUBSTRING_TAIL); + } + this.setInputsInline(true); + this.setOutput(true, 'String'); + this.updateAt(1, true); + this.updateAt(2, true); + this.setTooltip(Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP); + }, + mutationToDom: function() { + // Save whether there are 'AT' inputs. + var container = document.createElement('mutation'); + var isAt1 = this.getInput('AT1').type == Blockly.INPUT_VALUE; + container.setAttribute('at1', isAt1); + var isAt2 = this.getInput('AT2').type == Blockly.INPUT_VALUE; + container.setAttribute('at2', isAt2); + return container; + }, + domToMutation: function(xmlElement) { + // Restore the block shape. + var isAt1 = (xmlElement.getAttribute('at1') == 'true'); + var isAt2 = (xmlElement.getAttribute('at2') == 'true'); + this.updateAt(1, isAt1); + this.updateAt(2, isAt2); + }, + updateAt: function(n, isAt) { + // Create or delete an input for the numeric index. + // Destroy old 'AT' and 'ORDINAL' inputs. + this.removeInput('AT' + n); + this.removeInput('ORDINAL' + n, true); + // Create either a value 'AT' input or a dummy input. + if (isAt) { + this.appendValueInput('AT' + n).setCheck('Number'); + if (Blockly.Msg.ORDINAL_NUMBER_SUFFIX) { + this.appendDummyInput('ORDINAL' + n) + .appendTitle(Blockly.Msg.ORDINAL_NUMBER_SUFFIX); + } + } else { + this.appendDummyInput('AT' + n); + } + // Move tail, if present, to end of block. + if (n == 2 && Blockly.Msg.TEXT_GET_SUBSTRING_TAIL) { + this.removeInput('TAIL', true); + this.appendDummyInput('TAIL') + .appendTitle(Blockly.Msg.TEXT_GET_SUBSTRING_TAIL); + } + var menu = new Blockly.FieldDropdown(this['WHERE_OPTIONS_' + n], + function(value) { + var newAt = (value == 'FROM_START') || (value == 'FROM_END'); + // The 'isAt' variable is available due to this function being a closure. + if (newAt != isAt) { + var block = this.sourceBlock_; + block.updateAt(n, newAt); + // This menu has been destroyed and replaced. Update the replacement. + block.setTitleValue(value, 'WHERE' + n); + return null; + } + return undefined; + }); + this.getInput('AT' + n) + .appendTitle(menu, 'WHERE' + n); + if (n == 1) { + this.moveInputBefore('AT1', 'AT2'); + } + } +}; + +Blockly.Blocks['text_changeCase'] = { + // Change capitalization. + init: function() { + var OPERATORS = + [[Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE, 'UPPERCASE'], + [Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE, 'LOWERCASE'], + [Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE, 'TITLECASE']]; + this.setHelpUrl(Blockly.Msg.TEXT_CHANGECASE_HELPURL); + this.setColour(160); + this.appendValueInput('TEXT') + .setCheck('String') + .appendTitle(new Blockly.FieldDropdown(OPERATORS), 'CASE'); + this.setOutput(true, 'String'); + this.setTooltip(Blockly.Msg.TEXT_CHANGECASE_TOOLTIP); + } +}; + +Blockly.Blocks['text_trim'] = { + // Trim spaces. + init: function() { + var OPERATORS = + [[Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH, 'BOTH'], + [Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT, 'LEFT'], + [Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT, 'RIGHT']]; + this.setHelpUrl(Blockly.Msg.TEXT_TRIM_HELPURL); + this.setColour(160); + this.appendValueInput('TEXT') + .setCheck('String') + .appendTitle(new Blockly.FieldDropdown(OPERATORS), 'MODE'); + this.setOutput(true, 'String'); + this.setTooltip(Blockly.Msg.TEXT_TRIM_TOOLTIP); + } +}; + +Blockly.Blocks['text_print'] = { + // Print statement. + init: function() { + this.setHelpUrl(Blockly.Msg.TEXT_PRINT_HELPURL); + this.setColour(160); + this.interpolateMsg(Blockly.Msg.TEXT_PRINT_TITLE, + ['TEXT', null, Blockly.ALIGN_RIGHT], + Blockly.ALIGN_RIGHT); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.TEXT_PRINT_TOOLTIP); + } +}; + +Blockly.Blocks['text_prompt'] = { + // Prompt function. + init: function() { + var TYPES = + [[Blockly.Msg.TEXT_PROMPT_TYPE_TEXT, 'TEXT'], + [Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER, 'NUMBER']]; + // Assign 'this' to a variable for use in the closure below. + var thisBlock = this; + this.setHelpUrl(Blockly.Msg.TEXT_PROMPT_HELPURL); + this.setColour(160); + var dropdown = new Blockly.FieldDropdown(TYPES, function(newOp) { + if (newOp == 'NUMBER') { + thisBlock.outputConnection.setCheck('Number'); + } else { + thisBlock.outputConnection.setCheck('String'); + } + }); + this.appendDummyInput() + .appendTitle(dropdown, 'TYPE') + .appendTitle(new Blockly.FieldImage(Blockly.pathToBlockly + + 'media/quote0.png', 12, 12)) + .appendTitle(new Blockly.FieldTextInput(''), 'TEXT') + .appendTitle(new Blockly.FieldImage(Blockly.pathToBlockly + + 'media/quote1.png', 12, 12)); + this.setOutput(true, 'String'); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function() { + return (thisBlock.getTitleValue('TYPE') == 'TEXT') ? + Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT : + Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER; + }); + } +}; diff --git a/blocks/variables.js b/blocks/variables.js new file mode 100644 index 000000000..c24803b51 --- /dev/null +++ b/blocks/variables.js @@ -0,0 +1,92 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Variable blocks for Blockly. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Blocks.variables'); + +goog.require('Blockly.Blocks'); + + +Blockly.Blocks['variables_get'] = { + // Variable getter. + init: function() { + this.setHelpUrl(Blockly.Msg.VARIABLES_GET_HELPURL); + this.setColour(330); + this.appendDummyInput() + .appendTitle(Blockly.Msg.VARIABLES_GET_TITLE) + .appendTitle(new Blockly.FieldVariable( + Blockly.Msg.VARIABLES_GET_ITEM), 'VAR') + .appendTitle(Blockly.Msg.VARIABLES_GET_TAIL); + this.setOutput(true); + this.setTooltip(Blockly.Msg.VARIABLES_GET_TOOLTIP); + this.contextMenuMsg_ = Blockly.Msg.VARIABLES_GET_CREATE_SET; + this.contextMenuType_ = 'variables_set'; + }, + getVars: function() { + return [this.getTitleValue('VAR')]; + }, + renameVar: function(oldName, newName) { + if (Blockly.Names.equals(oldName, this.getTitleValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + }, + customContextMenu: function(options) { + var option = {enabled: true}; + var name = this.getTitleValue('VAR'); + option.text = this.contextMenuMsg_.replace('%1', name); + var xmlTitle = goog.dom.createDom('title', null, name); + xmlTitle.setAttribute('name', 'VAR'); + var xmlBlock = goog.dom.createDom('block', null, xmlTitle); + xmlBlock.setAttribute('type', this.contextMenuType_); + option.callback = Blockly.ContextMenu.callbackFactory(this, xmlBlock); + options.push(option); + } +}; + +Blockly.Blocks['variables_set'] = { + // Variable setter. + init: function() { + this.setHelpUrl(Blockly.Msg.VARIABLES_SET_HELPURL); + this.setColour(330); + this.appendValueInput('VALUE') + .appendTitle(Blockly.Msg.VARIABLES_SET_TITLE) + .appendTitle(new Blockly.FieldVariable( + Blockly.Msg.VARIABLES_SET_ITEM), 'VAR') + .appendTitle(Blockly.Msg.VARIABLES_SET_TAIL); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.VARIABLES_SET_TOOLTIP); + this.contextMenuMsg_ = Blockly.Msg.VARIABLES_SET_CREATE_GET; + this.contextMenuType_ = 'variables_get'; + }, + getVars: function() { + return [this.getTitleValue('VAR')]; + }, + renameVar: function(oldName, newName) { + if (Blockly.Names.equals(oldName, this.getTitleValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + }, + customContextMenu: Blockly.Blocks['variables_get'].customContextMenu +}; diff --git a/blocks_compressed.js b/blocks_compressed.js new file mode 100644 index 000000000..d255da580 --- /dev/null +++ b/blocks_compressed.js @@ -0,0 +1,129 @@ +// Do not edit this file; automatically generated by build.py. +"use strict"; + +Blockly.Blocks.text={};Blockly.Blocks.text={init:function(){this.setHelpUrl(Blockly.Msg.TEXT_TEXT_HELPURL);this.setColour(160);this.appendDummyInput().appendTitle(new Blockly.FieldImage(Blockly.pathToBlockly+"media/quote0.png",12,12)).appendTitle(new Blockly.FieldTextInput(""),"TEXT").appendTitle(new Blockly.FieldImage(Blockly.pathToBlockly+"media/quote1.png",12,12));this.setOutput(!0,"String");this.setTooltip(Blockly.Msg.TEXT_TEXT_TOOLTIP)}}; +Blockly.Blocks.text_join={init:function(){this.setHelpUrl(Blockly.Msg.TEXT_JOIN_HELPURL);this.setColour(160);this.appendValueInput("ADD0").appendTitle(Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH);this.appendValueInput("ADD1");this.setOutput(!0,"String");this.setMutator(new Blockly.Mutator(["text_create_join_item"]));this.setTooltip(Blockly.Msg.TEXT_JOIN_TOOLTIP);this.itemCount_=2},mutationToDom:function(){var a=document.createElement("mutation");a.setAttribute("items",this.itemCount_);return a},domToMutation:function(a){for(var b= +0;b","LT"],["\u2265","LTE"],["<","GT"],["\u2264","GTE"]]:[["=","EQ"],["\u2260","NEQ"],["<","LT"],["\u2264","LTE"],[">","GT"],["\u2265","GTE"]];this.setHelpUrl(Blockly.Msg.LOGIC_COMPARE_HELPURL);this.setColour(210);this.setOutput(!0,"Boolean");this.appendValueInput("A");this.appendValueInput("B").appendTitle(new Blockly.FieldDropdown(a),"OP");this.setInputsInline(!0);var b=this;this.setTooltip(function(){var a= +b.getTitleValue("OP");return{EQ:Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ,NEQ:Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ,LT:Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT,LTE:Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE,GT:Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT,GTE:Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE}[a]})}}; +Blockly.Blocks.logic_operation={init:function(){var a=[[Blockly.Msg.LOGIC_OPERATION_AND,"AND"],[Blockly.Msg.LOGIC_OPERATION_OR,"OR"]];this.setHelpUrl(Blockly.Msg.LOGIC_OPERATION_HELPURL);this.setColour(210);this.setOutput(!0,"Boolean");this.appendValueInput("A").setCheck("Boolean");this.appendValueInput("B").setCheck("Boolean").appendTitle(new Blockly.FieldDropdown(a),"OP");this.setInputsInline(!0);var b=this;this.setTooltip(function(){var a=b.getTitleValue("OP");return b.TOOLTIPS[a]})}}; +Blockly.Blocks.logic_negate={init:function(){this.setHelpUrl(Blockly.Msg.LOGIC_NEGATE_HELPURL);this.setColour(210);this.setOutput(!0,"Boolean");this.interpolateMsg(Blockly.Msg.LOGIC_NEGATE_TITLE,["BOOL","Boolean",Blockly.ALIGN_RIGHT],Blockly.ALIGN_RIGHT);this.setTooltip(Blockly.Msg.LOGIC_NEGATE_TOOLTIP)}}; +Blockly.Blocks.logic_boolean={init:function(){var a=[[Blockly.Msg.LOGIC_BOOLEAN_TRUE,"TRUE"],[Blockly.Msg.LOGIC_BOOLEAN_FALSE,"FALSE"]];this.setHelpUrl(Blockly.Msg.LOGIC_BOOLEAN_HELPURL);this.setColour(210);this.setOutput(!0,"Boolean");this.appendDummyInput().appendTitle(new Blockly.FieldDropdown(a),"BOOL");this.setTooltip(Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP)}}; +Blockly.Blocks.logic_null={init:function(){this.setHelpUrl(Blockly.Msg.LOGIC_NULL_HELPURL);this.setColour(210);this.setOutput(!0);this.appendDummyInput().appendTitle(Blockly.Msg.LOGIC_NULL);this.setTooltip(Blockly.Msg.LOGIC_NULL_TOOLTIP)}}; +Blockly.Blocks.logic_ternary={init:function(){this.setHelpUrl(Blockly.Msg.LOGIC_TERNARY_HELPURL);this.setColour(210);this.appendValueInput("IF").setCheck("Boolean").appendTitle(Blockly.Msg.LOGIC_TERNARY_CONDITION);this.appendValueInput("THEN").appendTitle(Blockly.Msg.LOGIC_TERNARY_IF_TRUE);this.appendValueInput("ELSE").appendTitle(Blockly.Msg.LOGIC_TERNARY_IF_FALSE);this.setOutput(!0);this.setTooltip(Blockly.Msg.LOGIC_TERNARY_TOOLTIP)}};Blockly.Blocks.lists={};Blockly.Blocks.lists_create_empty={init:function(){this.setHelpUrl(Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL);this.setColour(260);this.setOutput(!0,"Array");this.appendDummyInput().appendTitle(Blockly.Msg.LISTS_CREATE_EMPTY_TITLE);this.setTooltip(Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP)}}; +Blockly.Blocks.lists_create_with={init:function(){this.setColour(260);this.appendValueInput("ADD0").appendTitle(Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH);this.appendValueInput("ADD1");this.appendValueInput("ADD2");this.setOutput(!0,"Array");this.setMutator(new Blockly.Mutator(["lists_create_with_item"]));this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP);this.itemCount_=3},mutationToDom:function(a){a=document.createElement("mutation");a.setAttribute("items",this.itemCount_);return a},domToMutation:function(a){for(var b= +0;b.js for every language defined in msg/js/.json. + +import errno, glob, httplib, json, os, re, subprocess, sys, threading, urllib + +def import_path(fullpath): + """Import a file with full path specification. + Allows one to import from any directory, something __import__ does not do. + + Args: + fullpath: Path and filename of import. + + Returns: + An imported module. + """ + path, filename = os.path.split(fullpath) + filename, ext = os.path.splitext(filename) + sys.path.append(path) + module = __import__(filename) + reload(module) # Might be out of date + del sys.path[-1] + return module + + +HEADER = ('// Do not edit this file; automatically generated by build.py.\n' + '"use strict";\n') + + +class Gen_uncompressed(threading.Thread): + """Generate a JavaScript file that loads Blockly's raw files. + Runs in a separate thread. + """ + def __init__(self, search_paths): + threading.Thread.__init__(self) + self.search_paths = search_paths + + def run(self): + target_filename = 'blockly_uncompressed.js' + f = open(target_filename, 'w') + f.write(HEADER) + f.write(""" +window.BLOCKLY_DIR = (function() { + // Find name of current directory. + var scripts = document.getElementsByTagName('script'); + var re = new RegExp('(.+)[\/]blockly_uncompressed\.js$'); + for (var x = 0, script; script = scripts[x]; x++) { + var match = re.exec(script.src); + if (match) { + return match[1]; + } + } + alert('Could not detect Blockly\\'s directory name.'); + return ''; +})(); + +window.BLOCKLY_BOOT = function() { +// Execute after Closure has loaded. +if (!window.goog) { + alert('Error: Closure not found. Read this:\\n' + + 'http://code.google.com/p/blockly/wiki/Closure\\n'); +} + +// Build map of all dependencies (used and unused). +var dir = window.BLOCKLY_DIR.match(/[^\\/]+$/)[0]; +""") + add_dependency = [] + base_path = calcdeps.FindClosureBasePath(self.search_paths) + for dep in calcdeps.BuildDependenciesFromFiles(self.search_paths): + add_dependency.append(calcdeps.GetDepsLine(dep, base_path)) + add_dependency = '\n'.join(add_dependency) + # Find the Blockly directory name and replace it with a JS variable. + # This allows blockly_uncompressed.js to be compiled on one computer and be + # used on another, even if the directory name differs. + m = re.search('[\\/]([^\\/]+)[\\/]core[\\/]blockly.js', add_dependency) + add_dependency = re.sub('([\\/])' + re.escape(m.group(1)) + + '([\\/]core[\\/])', '\\1" + dir + "\\2', add_dependency) + f.write(add_dependency + '\n') + + provides = [] + for dep in calcdeps.BuildDependenciesFromFiles(self.search_paths): + if not dep.filename.startswith(os.pardir + os.sep): # '../' + provides.extend(dep.provides) + provides.sort() + f.write('\n') + f.write('// Load Blockly.\n') + for provide in provides: + f.write('goog.require(\'%s\');\n' % provide) + + f.write(""" +delete window.BLOCKLY_DIR; +delete window.BLOCKLY_BOOT; +}; + +// Delete any existing Closure (e.g. Soy's nogoog_shim). +document.write(''); +// Load fresh Closure Library. +document.write(''); +document.write(''); +""") + f.close() + print('SUCCESS: ' + target_filename) + + +class Gen_compressed(threading.Thread): + """Generate a JavaScript file that contains all of Blockly's core and all + required parts of Closure, compiled together. + Uses the Closure Compiler's online API. + Runs in a separate thread. + """ + def __init__(self, search_paths): + threading.Thread.__init__(self) + self.search_paths = search_paths + + def run(self): + self.gen_core() + self.gen_blocks() + self.gen_generator('javascript') + self.gen_generator('python') + + def gen_core(self): + target_filename = 'blockly_compressed.js' + # Define the parameters for the POST request. + params = [ + ('compilation_level', 'SIMPLE_OPTIMIZATIONS'), + ('use_closure_library', 'true'), + ('output_format', 'json'), + ('output_info', 'compiled_code'), + ('output_info', 'warnings'), + ('output_info', 'errors'), + ('output_info', 'statistics'), + ] + + # Read in all the source files. + filenames = calcdeps.CalculateDependencies(self.search_paths, + [os.path.join('core', 'blockly.js')]) + for filename in filenames: + # Filter out the Closure files (the compiler will add them). + if filename.startswith(os.pardir + os.sep): # '../' + continue + f = open(filename) + params.append(('js_code', ''.join(f.readlines()))) + f.close() + + self.do_compile(params, target_filename, filenames, '') + + def gen_blocks(self): + target_filename = 'blocks_compressed.js' + # Define the parameters for the POST request. + params = [ + ('compilation_level', 'SIMPLE_OPTIMIZATIONS'), + ('output_format', 'json'), + ('output_info', 'compiled_code'), + ('output_info', 'warnings'), + ('output_info', 'errors'), + ('output_info', 'statistics'), + ] + + # Read in all the source files. + # Add Blockly.Blocks to be compatible with the compiler. + params.append(('js_code', "goog.provide('Blockly.Blocks');")) + filenames = glob.glob(os.path.join('blocks', '*.js')) + for filename in filenames: + f = open(filename) + params.append(('js_code', ''.join(f.readlines()))) + f.close() + + # Remove Blockly.Blocks to be compatible with Blockly. + remove = "var Blockly={Blocks:{}};" + self.do_compile(params, target_filename, filenames, remove) + + def gen_generator(self, language): + target_filename = language + '_compressed.js' + # Define the parameters for the POST request. + params = [ + ('compilation_level', 'SIMPLE_OPTIMIZATIONS'), + ('output_format', 'json'), + ('output_info', 'compiled_code'), + ('output_info', 'warnings'), + ('output_info', 'errors'), + ('output_info', 'statistics'), + ] + + # Read in all the source files. + # Add Blockly.Generator to be compatible with the compiler. + params.append(('js_code', "goog.provide('Blockly.Generator');")) + filenames = glob.glob( + os.path.join('generators', language, '*.js')) + filenames.insert(0, os.path.join('generators', language + '.js')) + for filename in filenames: + f = open(filename) + params.append(('js_code', ''.join(f.readlines()))) + f.close() + filenames.insert(0, '[goog.provide]') + + # Remove Blockly.Generator to be compatible with Blockly. + remove = "var Blockly={Generator:{}};" + self.do_compile(params, target_filename, filenames, remove) + + def do_compile(self, params, target_filename, filenames, remove): + # Send the request to Google. + headers = { "Content-type": "application/x-www-form-urlencoded" } + conn = httplib.HTTPConnection('closure-compiler.appspot.com') + conn.request('POST', '/compile', urllib.urlencode(params), headers) + response = conn.getresponse() + json_str = response.read() + conn.close() + + # Parse the JSON response. + json_data = json.loads(json_str) + + def file_lookup(name): + if not name.startswith('Input_'): + return '???' + n = int(name[6:]) + return filenames[n] + + if json_data.has_key('serverErrors'): + errors = json_data['serverErrors'] + for error in errors: + print 'SERVER ERROR: %s' % target_filename + print error['error'] + elif json_data.has_key('errors'): + errors = json_data['errors'] + for error in errors: + print('FATAL ERROR') + print(error['error']) + print('%s at line %d:' % ( + file_lookup(error['file']), error['lineno'])) + print(error['line']) + print((' ' * error['charno']) + '^') + sys.exit(1) + else: + if json_data.has_key('warnings'): + warnings = json_data['warnings'] + for warning in warnings: + print('WARNING') + print(warning['warning']) + print('%s at line %d:' % ( + file_lookup(warning['file']), warning['lineno'])) + print(warning['line']) + print((' ' * warning['charno']) + '^') + print() + + if not json_data.has_key('compiledCode'): + print('FATAL ERROR: Compiler did not return compiledCode.') + sys.exit(1) + + code = HEADER + '\n' + json_data['compiledCode'] + code = code.replace(remove, '') + + stats = json_data['statistics'] + original_b = stats['originalSize'] + compressed_b = stats['compressedSize'] + if original_b > 0 and compressed_b > 0: + f = open(target_filename, 'w') + f.write(code) + f.close() + + original_kb = int(original_b / 1024 + 0.5) + compressed_kb = int(compressed_b / 1024 + 0.5) + ratio = int(float(compressed_b) / float(original_b) * 100 + 0.5) + print('SUCCESS: ' + target_filename) + print('Size changed from %d KB to %d KB (%d%%).' % ( + original_kb, compressed_kb, ratio)) + else: + print 'UNKNOWN ERROR' + + +class Gen_langfiles(threading.Thread): + """Generate JavaScript file for each natural language supported. + + Runs in a separate thread. + """ + + def __init__(self): + threading.Thread.__init__(self) + + def _rebuild(self, srcs, dests): + # Determine whether any of the files in srcs is newer than any in dests. + try: + return (max(os.path.getmtime(src) for src in srcs) > + min(os.path.getmtime(dest) for dest in dests)) + except OSError, e: + # Was a file not found? + if e.errno == errno.ENOENT: + # If it was a source file, we can't proceed. + if e.filename in srcs: + print('Source file missing: ' + e.filename) + sys.exit(1) + else: + # If a destination file was missing, rebuild. + return True + else: + print('Error checking file creation times: ' + e) + + def run(self): + # The files msg/json/{en,qqq,synonyms}.json depend on msg/messages.js. + if self._rebuild([os.path.join('msg', 'messages.js')], + [os.path.join('msg', 'json', f) for f in + ['en.json', 'qqq.json', 'synonyms.json']]): + try: + subprocess.check_call([ + os.path.join('i18n', 'js_to_json.py'), + '--input_file', 'msg/messages.js', + '--output_dir', 'msg/json/', + '--quiet']) + except (subprocess.CalledProcessError, OSError), e: + # Documentation for subprocess.check_call says that CalledProcessError + # will be raised on failure, but I found that OSError is also possible. + print('Error running i18n/js_to_json.py: ', e) + sys.exit(1) + + # Checking whether it is necessary to rebuild the js files would be a lot of + # work since we would have to compare each .json file with each + # .js file. Rebuilding is easy and cheap, so just go ahead and do it. + try: + # Use create_messages.py to create .js files from .json files. + cmd = [ + os.path.join('i18n', 'create_messages.py'), + '--source_lang_file', os.path.join('msg', 'json', 'en.json'), + '--source_synonym_file', os.path.join('msg', 'json', 'synonyms.json'), + '--key_file', os.path.join('msg', 'json', 'keys.json'), + '--output_dir', os.path.join('msg', 'js'), + '--quiet'] + json_files = glob.glob(os.path.join('msg', 'json', '*.json')) + json_files = [file for file in json_files if not + (file.endswith(('keys.json', 'synonyms.json', 'qqq.json')))] + cmd.extend(json_files) + subprocess.check_call(cmd) + except (subprocess.CalledProcessError, OSError), e: + print('Error running i18n/create_messages.py: ', e) + sys.exit(1) + + # Output list of .js files created. + for f in json_files: + # This assumes the path to the current directory does not contain 'json'. + f = f.replace('json', 'js') + if os.path.isfile(f): + print('SUCCESS: ' + f) + else: + print('FAILED to create ' + f) + + +if __name__ == '__main__': + try: + calcdeps = import_path(os.path.join(os.path.pardir, + 'closure-library-read-only', 'closure', 'bin', 'calcdeps.py')) + except ImportError: + print("""Error: Closure not found. Read this: +http://code.google.com/p/blockly/wiki/Closure""") + sys.exit(1) + search_paths = calcdeps.ExpandDirectories( + ['core', os.path.join(os.path.pardir, 'closure-library-read-only')]) + + # Run both tasks in parallel threads. + # Uncompressed is limited by processor speed. + # Compressed is limited by network and server speed. + Gen_uncompressed(search_paths).start() + Gen_compressed(search_paths).start() + + # This is run locally in a separate thread. + Gen_langfiles().start() diff --git a/codereview.settings b/codereview.settings new file mode 100644 index 000000000..615c21885 --- /dev/null +++ b/codereview.settings @@ -0,0 +1,3 @@ +CODE_REVIEW_SERVER: codereview.appspot.com +VIEW_VC: http://code.google.com/p/blockly/source/detail?r= +CC_LIST: diff --git a/core/block.js b/core/block.js new file mode 100644 index 000000000..05b18592f --- /dev/null +++ b/core/block.js @@ -0,0 +1,1644 @@ +/** + * Visual Blocks Editor + * + * Copyright 2011 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview The class representing one block. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Block'); + +goog.require('Blockly.BlockSvg'); +goog.require('Blockly.Blocks'); +goog.require('Blockly.Comment'); +goog.require('Blockly.Connection'); +goog.require('Blockly.ContextMenu'); +goog.require('Blockly.Input'); +goog.require('Blockly.Msg'); +goog.require('Blockly.Mutator'); +goog.require('Blockly.Warning'); +goog.require('Blockly.Workspace'); +goog.require('Blockly.Xml'); +goog.require('goog.asserts'); +goog.require('goog.string'); +goog.require('goog.Timer'); + + +/** + * Unique ID counter for created blocks. + * @private + */ +Blockly.uidCounter_ = 0; + +/** + * Class for one block. + * @param {!Blockly.Workspace} workspace The new block's workspace. + * @param {?string} prototypeName Name of the language object containing + * type-specific functions for this block. + * @constructor + */ +Blockly.Block = function(workspace, prototypeName) { + this.id = ++Blockly.uidCounter_; + this.outputConnection = null; + this.nextConnection = null; + this.previousConnection = null; + this.inputList = []; + this.inputsInline = false; + this.rendered = false; + this.disabled = false; + this.tooltip = ''; + this.contextMenu = true; + + this.parentBlock_ = null; + this.childBlocks_ = []; + this.deletable_ = true; + this.movable_ = true; + this.editable_ = true; + this.collapsed_ = false; + + this.workspace = workspace; + this.isInFlyout = workspace.isFlyout; + + workspace.addTopBlock(this); + + // Copy the type-specific functions and data from the prototype. + if (prototypeName) { + this.type = prototypeName; + var prototype = Blockly.Blocks[prototypeName]; + goog.asserts.assertObject(prototype, + 'Error: "%s" is an unknown language block.', prototypeName); + goog.mixin(this, prototype); + } + // Call an initialization function, if it exists. + if (goog.isFunction(this.init)) { + this.init(); + } + // Bind an onchange function, if it exists. + if (goog.isFunction(this.onchange)) { + Blockly.bindEvent_(workspace.getCanvas(), 'blocklyWorkspaceChange', this, + this.onchange); + } +}; + +/** + * Pointer to SVG representation of the block. + * @type {Blockly.BlockSvg} + * @private + */ +Blockly.Block.prototype.svg_ = null; + +/** + * Block's mutator icon (if any). + * @type {Blockly.Mutator} + */ +Blockly.Block.prototype.mutator = null; + +/** + * Block's comment icon (if any). + * @type {Blockly.Comment} + */ +Blockly.Block.prototype.comment = null; + +/** + * Block's warning icon (if any). + * @type {Blockly.Warning} + */ +Blockly.Block.prototype.warning = null; + +/** + * Returns a list of mutator, comment, and warning icons. + * @return {!Array} List of icons. + */ +Blockly.Block.prototype.getIcons = function() { + var icons = []; + if (this.mutator) { + icons.push(this.mutator); + } + if (this.comment) { + icons.push(this.comment); + } + if (this.warning) { + icons.push(this.warning); + } + return icons; +}; + +/** + * Create and initialize the SVG representation of the block. + */ +Blockly.Block.prototype.initSvg = function() { + this.svg_ = new Blockly.BlockSvg(this); + this.svg_.init(); + if (!Blockly.readOnly) { + Blockly.bindEvent_(this.svg_.getRootElement(), 'mousedown', this, + this.onMouseDown_); + } + this.workspace.getCanvas().appendChild(this.svg_.getRootElement()); +}; + +/** + * Return the root node of the SVG or null if none exists. + * @return {Element} The root SVG node (probably a group). + */ +Blockly.Block.prototype.getSvgRoot = function() { + return this.svg_ && this.svg_.getRootElement(); +}; + +/** + * Is the mouse dragging a block? + * 0 - No drag operation. + * 1 - Still inside the sticky DRAG_RADIUS. + * 2 - Freely draggable. + * @private + */ +Blockly.Block.dragMode_ = 0; + +/** + * Wrapper function called when a mouseUp occurs during a drag operation. + * @type {Array.} + * @private + */ +Blockly.Block.onMouseUpWrapper_ = null; + +/** + * Wrapper function called when a mouseMove occurs during a drag operation. + * @type {Array.} + * @private + */ +Blockly.Block.onMouseMoveWrapper_ = null; + +/** + * Stop binding to the global mouseup and mousemove events. + * @private + */ +Blockly.Block.terminateDrag_ = function() { + if (Blockly.Block.onMouseUpWrapper_) { + Blockly.unbindEvent_(Blockly.Block.onMouseUpWrapper_); + Blockly.Block.onMouseUpWrapper_ = null; + } + if (Blockly.Block.onMouseMoveWrapper_) { + Blockly.unbindEvent_(Blockly.Block.onMouseMoveWrapper_); + Blockly.Block.onMouseMoveWrapper_ = null; + } + var selected = Blockly.selected; + if (Blockly.Block.dragMode_ == 2) { + // Terminate a drag operation. + if (selected) { + // Update the connection locations. + var xy = selected.getRelativeToSurfaceXY(); + var dx = xy.x - selected.startDragX; + var dy = xy.y - selected.startDragY; + selected.moveConnections_(dx, dy); + delete selected.draggedBubbles_; + selected.setDragging_(false); + selected.render(); + goog.Timer.callOnce( + selected.bumpNeighbours_, Blockly.BUMP_DELAY, selected); + // Fire an event to allow scrollbars to resize. + Blockly.fireUiEvent(window, 'resize'); + } + } + if (selected) { + selected.workspace.fireChangeEvent(); + } + Blockly.Block.dragMode_ = 0; +}; + +/** + * Select this block. Highlight it visually. + */ +Blockly.Block.prototype.select = function() { + goog.asserts.assertObject(this.svg_, 'Block is not rendered.'); + if (Blockly.selected) { + // Unselect any previously selected block. + Blockly.selected.unselect(); + } + Blockly.selected = this; + this.svg_.addSelect(); + Blockly.fireUiEvent(this.workspace.getCanvas(), 'blocklySelectChange'); +}; + +/** + * Unselect this block. Remove its highlighting. + */ +Blockly.Block.prototype.unselect = function() { + goog.asserts.assertObject(this.svg_, 'Block is not rendered.'); + Blockly.selected = null; + this.svg_.removeSelect(); + Blockly.fireUiEvent(this.workspace.getCanvas(), 'blocklySelectChange'); +}; + +/** + * Dispose of this block. + * @param {boolean} healStack If true, then try to heal any gap by connecting + * the next statement with the previous statement. Otherwise, dispose of + * all children of this block. + * @param {boolean} animate If true, show a disposal animation and sound. + */ +Blockly.Block.prototype.dispose = function(healStack, animate) { + // Switch off rerendering. + this.rendered = false; + this.unplug(healStack); + + if (animate && this.svg_) { + this.svg_.disposeUiEffect(); + } + + //This block is now at the top of the workspace. + // Remove this block from the workspace's list of top-most blocks. + this.workspace.removeTopBlock(this); + this.workspace = null; + + // Just deleting this block from the DOM would result in a memory leak as + // well as corruption of the connection database. Therefore we must + // methodically step through the blocks and carefully disassemble them. + + if (Blockly.selected == this) { + Blockly.selected = null; + // If there's a drag in-progress, unlink the mouse events. + Blockly.terminateDrag_(); + } + + // First, dispose of all my children. + for (var x = this.childBlocks_.length - 1; x >= 0; x--) { + this.childBlocks_[x].dispose(false); + } + // Then dispose of myself. + var icons = this.getIcons(); + for (var x = 0; x < icons.length; x++) { + icons[x].dispose(); + } + // Dispose of all inputs and their titles. + for (var x = 0, input; input = this.inputList[x]; x++) { + input.dispose(); + } + this.inputList = []; + // Dispose of any remaining connections (next/previous/output). + var connections = this.getConnections_(true); + for (var x = 0; x < connections.length; x++) { + var connection = connections[x]; + if (connection.targetConnection) { + connection.disconnect(); + } + connections[x].dispose(); + } + // Dispose of the SVG and break circular references. + if (this.svg_) { + this.svg_.dispose(); + this.svg_ = null; + } +}; + +/** + * Unplug this block from its superior block. If this block is a statement, + * optionally reconnect the block underneath with the block on top. + * @param {boolean} healStack Disconnect child statement and reconnect stack. + * @param {boolean} bump Move the unplugged block sideways a short distance. + */ +Blockly.Block.prototype.unplug = function(healStack, bump) { + bump = bump && !!this.getParent(); + if (this.outputConnection) { + if (this.outputConnection.targetConnection) { + // Disconnect from any superior block. + this.setParent(null); + } + } else { + var previousTarget = null; + if (this.previousConnection && this.previousConnection.targetConnection) { + // Remember the connection that any next statements need to connect to. + previousTarget = this.previousConnection.targetConnection; + // Detach this block from the parent's tree. + this.setParent(null); + } + if (healStack && this.nextConnection && + this.nextConnection.targetConnection) { + // Disconnect the next statement. + var nextTarget = this.nextConnection.targetConnection; + var nextBlock = this.nextConnection.targetBlock(); + nextBlock.setParent(null); + if (previousTarget) { + // Attach the next statement to the previous statement. + previousTarget.connect(nextTarget); + } + } + } + if (bump) { + // Bump the block sideways. + var dx = Blockly.SNAP_RADIUS * (Blockly.RTL ? -1 : 1); + var dy = Blockly.SNAP_RADIUS * 2; + this.moveBy(dx, dy); + } +}; + +/** + * Return the coordinates of the top-left corner of this block relative to the + * drawing surface's origin (0,0). + * @return {!Object} Object with .x and .y properties. + */ +Blockly.Block.prototype.getRelativeToSurfaceXY = function() { + var x = 0; + var y = 0; + if (this.svg_) { + var element = this.svg_.getRootElement(); + do { + // Loop through this block and every parent. + var xy = Blockly.getRelativeXY_(element); + x += xy.x; + y += xy.y; + element = element.parentNode; + } while (element && element != this.workspace.getCanvas()); + } + return {x: x, y: y}; +}; + +/** + * Move a block by a relative offset. + * @param {number} dx Horizontal offset. + * @param {number} dy Vertical offset. + */ +Blockly.Block.prototype.moveBy = function(dx, dy) { + var xy = this.getRelativeToSurfaceXY(); + this.svg_.getRootElement().setAttribute('transform', + 'translate(' + (xy.x + dx) + ', ' + (xy.y + dy) + ')'); + this.moveConnections_(dx, dy); +}; + +/** + * Returns a bounding box describing the dimensions of this block. + * @return {!Object} Object with height and width properties. + */ +Blockly.Block.prototype.getHeightWidth = function() { + try { + var bBox = this.getSvgRoot().getBBox(); + var height = bBox.height; + } catch (e) { + // Firefox has trouble with hidden elements (Bug 528969). + return {height: 0, width: 0}; + } + if (Blockly.BROKEN_CONTROL_POINTS) { + /* HACK: + WebKit bug 67298 causes control points to be included in the reported + bounding box. The render functions (below) add two 5px spacer control + points that we need to subtract. + */ + height -= 10; + if (this.nextConnection) { + // Bottom control point partially masked by lower tab. + height += 4; + } + } + // Subtract one from the height due to the shadow. + height -= 1; + return {height: height, width: bBox.width}; +}; + +/** + * Handle a mouse-down on an SVG block. + * @param {!Event} e Mouse down event. + * @private + */ +Blockly.Block.prototype.onMouseDown_ = function(e) { + if (this.isInFlyout) { + return; + } + // Update Blockly's knowledge of its own location. + Blockly.svgResize(); + Blockly.terminateDrag_(); + this.select(); + Blockly.hideChaff(); + if (Blockly.isRightButton(e)) { + // Right-click. + if (Blockly.ContextMenu) { + this.showContextMenu_(Blockly.mouseToSvg(e)); + } + } else if (!this.isMovable()) { + // Allow unmovable blocks to be selected and context menued, but not + // dragged. Let this event bubble up to document, so the workspace may be + // dragged instead. + return; + } else { + // Left-click (or middle click) + Blockly.removeAllRanges(); + Blockly.setCursorHand_(true); + // Look up the current translation and record it. + var xy = this.getRelativeToSurfaceXY(); + this.startDragX = xy.x; + this.startDragY = xy.y; + // Record the current mouse position. + this.startDragMouseX = e.clientX; + this.startDragMouseY = e.clientY; + Blockly.Block.dragMode_ = 1; + Blockly.Block.onMouseUpWrapper_ = Blockly.bindEvent_(document, + 'mouseup', this, this.onMouseUp_); + Blockly.Block.onMouseMoveWrapper_ = Blockly.bindEvent_(document, + 'mousemove', this, this.onMouseMove_); + // Build a list of bubbles that need to be moved and where they started. + this.draggedBubbles_ = []; + var descendants = this.getDescendants(); + for (var x = 0, descendant; descendant = descendants[x]; x++) { + var icons = descendant.getIcons(); + for (var y = 0; y < icons.length; y++) { + var data = icons[y].getIconLocation(); + data.bubble = icons[y]; + this.draggedBubbles_.push(data); + } + } + } + // This event has been handled. No need to bubble up to the document. + e.stopPropagation(); +}; + +/** + * Handle a mouse-up anywhere in the SVG pane. Is only registered when a + * block is clicked. We can't use mouseUp on the block since a fast-moving + * cursor can briefly escape the block before it catches up. + * @param {!Event} e Mouse up event. + * @private + */ +Blockly.Block.prototype.onMouseUp_ = function(e) { + Blockly.terminateDrag_(); + if (Blockly.selected && Blockly.highlightedConnection_) { + // Connect two blocks together. + Blockly.localConnection_.connect(Blockly.highlightedConnection_); + if (this.svg_) { + // Trigger a connection animation. + // Determine which connection is inferior (lower in the source stack). + var inferiorConnection; + if (Blockly.localConnection_.isSuperior()) { + inferiorConnection = Blockly.highlightedConnection_; + } else { + inferiorConnection = Blockly.localConnection_; + } + inferiorConnection.sourceBlock_.svg_.connectionUiEffect(); + } + if (this.workspace.trashcan && this.workspace.trashcan.isOpen) { + // Don't throw an object in the trash can if it just got connected. + this.workspace.trashcan.close(); + } + } else if (this.workspace.trashcan && this.workspace.trashcan.isOpen) { + var trashcan = this.workspace.trashcan; + goog.Timer.callOnce(trashcan.close, 100, trashcan); + Blockly.selected.dispose(false, true); + // Dropping a block on the trash can will usually cause the workspace to + // resize to contain the newly positioned block. Force a second resize now + // that the block has been deleted. + Blockly.fireUiEvent(window, 'resize'); + } + if (Blockly.highlightedConnection_) { + Blockly.highlightedConnection_.unhighlight(); + Blockly.highlightedConnection_ = null; + } +}; + +/** + * Load the block's help page in a new window. + * @private + */ +Blockly.Block.prototype.showHelp_ = function() { + var url = goog.isFunction(this.helpUrl) ? this.helpUrl() : this.helpUrl; + if (url) { + window.open(url); + } +}; + +/** + * Duplicate this block and its children. + * @return {!Blockly.Block} The duplicate. + * @private + */ +Blockly.Block.prototype.duplicate_ = function() { + // Create a duplicate via XML. + var xmlBlock = Blockly.Xml.blockToDom_(this); + Blockly.Xml.deleteNext(xmlBlock); + var newBlock = Blockly.Xml.domToBlock_( + /** @type {!Blockly.Workspace} */ (this.workspace), xmlBlock); + // Move the duplicate next to the old block. + var xy = this.getRelativeToSurfaceXY(); + if (Blockly.RTL) { + xy.x -= Blockly.SNAP_RADIUS; + } else { + xy.x += Blockly.SNAP_RADIUS; + } + xy.y += Blockly.SNAP_RADIUS * 2; + newBlock.moveBy(xy.x, xy.y); + return newBlock; +}; + +/** + * Show the context menu for this block. + * @param {!Object} xy Coordinates of mouse click, contains x and y properties. + * @private + */ +Blockly.Block.prototype.showContextMenu_ = function(xy) { + if (Blockly.readOnly || !this.contextMenu) { + return; + } + // Save the current block in a variable for use in closures. + var block = this; + var options = []; + + if (this.isDeletable() && !block.isInFlyout) { + // Option to duplicate this block. + var duplicateOption = { + text: Blockly.Msg.DUPLICATE_BLOCK, + enabled: true, + callback: function() { + block.duplicate_(); + } + }; + if (this.getDescendants().length > this.workspace.remainingCapacity()) { + duplicateOption.enabled = false; + } + options.push(duplicateOption); + + if (Blockly.Comment && !this.collapsed_) { + // Option to add/remove a comment. + var commentOption = {enabled: true}; + if (this.comment) { + commentOption.text = Blockly.Msg.REMOVE_COMMENT; + commentOption.callback = function() { + block.setCommentText(null); + }; + } else { + commentOption.text = Blockly.Msg.ADD_COMMENT; + commentOption.callback = function() { + block.setCommentText(''); + }; + } + options.push(commentOption); + } + + // Option to make block inline. + if (!this.collapsed_) { + for (var i = 0; i < this.inputList.length; i++) { + if (this.inputList[i].type == Blockly.INPUT_VALUE) { + // Only display this option if there is a value input on the block. + var inlineOption = {enabled: true}; + inlineOption.text = this.inputsInline ? Blockly.Msg.EXTERNAL_INPUTS : + Blockly.Msg.INLINE_INPUTS; + inlineOption.callback = function() { + block.setInputsInline(!block.inputsInline); + }; + options.push(inlineOption); + break; + } + } + } + + if (Blockly.collapse) { + // Option to collapse/expand block. + if (this.collapsed_) { + var expandOption = {enabled: true}; + expandOption.text = Blockly.Msg.EXPAND_BLOCK; + expandOption.callback = function() { + block.setCollapsed(false); + }; + options.push(expandOption); + } else { + var collapseOption = {enabled: true}; + collapseOption.text = Blockly.Msg.COLLAPSE_BLOCK; + collapseOption.callback = function() { + block.setCollapsed(true); + }; + options.push(collapseOption); + } + } + + // Option to disable/enable block. + var disableOption = { + text: this.disabled ? + Blockly.Msg.ENABLE_BLOCK : Blockly.Msg.DISABLE_BLOCK, + enabled: !this.getInheritedDisabled(), + callback: function() { + block.setDisabled(!block.disabled); + } + }; + options.push(disableOption); + + // Option to delete this block. + // Count the number of blocks that are nested in this block. + var descendantCount = this.getDescendants().length; + if (block.nextConnection && block.nextConnection.targetConnection) { + // Blocks in the current stack would survive this block's deletion. + descendantCount -= this.nextConnection.targetBlock(). + getDescendants().length; + } + var deleteOption = { + text: descendantCount == 1 ? Blockly.Msg.DELETE_BLOCK : + Blockly.Msg.DELETE_X_BLOCKS.replace('%1', descendantCount), + enabled: true, + callback: function() { + block.dispose(true, true); + } + }; + options.push(deleteOption); + } + + // Option to get help. + var url = goog.isFunction(this.helpUrl) ? this.helpUrl() : this.helpUrl; + var helpOption = {enabled: !!url}; + helpOption.text = Blockly.Msg.HELP; + helpOption.callback = function() { + block.showHelp_(); + }; + options.push(helpOption); + + // Allow the block to add or modify options. + if (this.customContextMenu && !block.isInFlyout) { + this.customContextMenu(options); + } + + Blockly.ContextMenu.show(xy, options); +}; + +/** + * Returns all connections originating from this block. + * @param {boolean} all If true, return all connections even hidden ones. + * Otherwise return those that are visible. + * @return {!Array.} Array of connections. + * @private + */ +Blockly.Block.prototype.getConnections_ = function(all) { + var myConnections = []; + if (all || this.rendered) { + if (this.outputConnection) { + myConnections.push(this.outputConnection); + } + if (this.nextConnection) { + myConnections.push(this.nextConnection); + } + if (this.previousConnection) { + myConnections.push(this.previousConnection); + } + if (all || !this.collapsed_) { + for (var x = 0, input; input = this.inputList[x]; x++) { + if (input.connection) { + myConnections.push(input.connection); + } + } + } + } + return myConnections; +}; + +/** + * Move the connections for this block and all blocks attached under it. + * Also update any attached bubbles. + * @param {number} dx Horizontal offset from current location. + * @param {number} dy Vertical offset from current location. + * @private + */ +Blockly.Block.prototype.moveConnections_ = function(dx, dy) { + if (!this.rendered) { + // Rendering is required to lay out the blocks. + // This is probably an invisible block attached to a collapsed block. + return; + } + var myConnections = this.getConnections_(false); + for (var x = 0; x < myConnections.length; x++) { + myConnections[x].moveBy(dx, dy); + } + var icons = this.getIcons(); + for (var x = 0; x < icons.length; x++) { + icons[x].computeIconLocation(); + } + + // Recurse through all blocks attached under this one. + for (var x = 0; x < this.childBlocks_.length; x++) { + this.childBlocks_[x].moveConnections_(dx, dy); + } +}; + +/** + * Recursively adds or removes the dragging class to this node and its children. + * @param {boolean} adding True if adding, false if removing. + * @private + */ +Blockly.Block.prototype.setDragging_ = function(adding) { + if (adding) { + this.svg_.addDragging(); + } else { + this.svg_.removeDragging(); + } + // Recurse through all blocks attached under this one. + for (var x = 0; x < this.childBlocks_.length; x++) { + this.childBlocks_[x].setDragging_(adding); + } +}; + +/** + * Drag this block to follow the mouse. + * @param {!Event} e Mouse move event. + * @private + */ +Blockly.Block.prototype.onMouseMove_ = function(e) { + if (e.type == 'mousemove' && e.clientX <= 1 && e.clientY == 0 && + e.button == 0) { + /* HACK: + Safari Mobile 6.0 and Chrome for Android 18.0 fire rogue mousemove events + on certain touch actions. Ignore events with these signatures. + This may result in a one-pixel blind spot in other browsers, + but this shouldn't be noticable. */ + e.stopPropagation(); + return; + } + Blockly.removeAllRanges(); + var dx = e.clientX - this.startDragMouseX; + var dy = e.clientY - this.startDragMouseY; + if (Blockly.Block.dragMode_ == 1) { + // Still dragging within the sticky DRAG_RADIUS. + var dr = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)); + if (dr > Blockly.DRAG_RADIUS) { + // Switch to unrestricted dragging. + Blockly.Block.dragMode_ = 2; + // Push this block to the very top of the stack. + this.setParent(null); + this.setDragging_(true); + } + } + if (Blockly.Block.dragMode_ == 2) { + // Unrestricted dragging. + var x = this.startDragX + dx; + var y = this.startDragY + dy; + this.svg_.getRootElement().setAttribute('transform', + 'translate(' + x + ', ' + y + ')'); + // Drag all the nested bubbles. + for (var i = 0; i < this.draggedBubbles_.length; i++) { + var commentData = this.draggedBubbles_[i]; + commentData.bubble.setIconLocation(commentData.x + dx, + commentData.y + dy); + } + + // Check to see if any of this block's connections are within range of + // another block's connection. + var myConnections = this.getConnections_(false); + var closestConnection = null; + var localConnection = null; + var radiusConnection = Blockly.SNAP_RADIUS; + for (var i = 0; i < myConnections.length; i++) { + var myConnection = myConnections[i]; + var neighbour = myConnection.closest(radiusConnection, dx, dy); + if (neighbour.connection) { + closestConnection = neighbour.connection; + localConnection = myConnection; + radiusConnection = neighbour.radius; + } + } + + // Remove connection highlighting if needed. + if (Blockly.highlightedConnection_ && + Blockly.highlightedConnection_ != closestConnection) { + Blockly.highlightedConnection_.unhighlight(); + Blockly.highlightedConnection_ = null; + Blockly.localConnection_ = null; + } + // Add connection highlighting if needed. + if (closestConnection && + closestConnection != Blockly.highlightedConnection_) { + closestConnection.highlight(); + Blockly.highlightedConnection_ = closestConnection; + Blockly.localConnection_ = localConnection; + } + // Flip the trash can lid if needed. + if (this.workspace.trashcan && this.isDeletable()) { + this.workspace.trashcan.onMouseMove(e); + } + } + // This event has been handled. No need to bubble up to the document. + e.stopPropagation(); +}; + +/** + * Bump unconnected blocks out of alignment. Two blocks which aren't actually + * connected should not coincidentally line up on screen. + * @private + */ +Blockly.Block.prototype.bumpNeighbours_ = function() { + if (Blockly.Block.dragMode_ != 0) { + // Don't bump blocks during a drag. + return; + } + var rootBlock = this.getRootBlock(); + if (rootBlock.isInFlyout) { + // Don't move blocks around in a flyout. + return; + } + // Loop though every connection on this block. + var myConnections = this.getConnections_(false); + for (var x = 0; x < myConnections.length; x++) { + var connection = myConnections[x]; + // Spider down from this block bumping all sub-blocks. + if (connection.targetConnection && connection.isSuperior()) { + connection.targetBlock().bumpNeighbours_(); + } + + var neighbours = connection.neighbours_(Blockly.SNAP_RADIUS); + for (var y = 0; y < neighbours.length; y++) { + var otherConnection = neighbours[y]; + // If both connections are connected, that's probably fine. But if + // either one of them is unconnected, then there could be confusion. + if (!connection.targetConnection || !otherConnection.targetConnection) { + // Only bump blocks if they are from different tree structures. + if (otherConnection.sourceBlock_.getRootBlock() != rootBlock) { + // Always bump the inferior block. + if (connection.isSuperior()) { + otherConnection.bumpAwayFrom_(connection); + } else { + connection.bumpAwayFrom_(otherConnection); + } + } + } + } + } +}; + +/** + * Return the parent block or null if this block is at the top level. + * @return {Blockly.Block} The block that holds the current block. + */ +Blockly.Block.prototype.getParent = function() { + // Look at the DOM to see if we are nested in another block. + return this.parentBlock_; +}; + +/** + * Return the parent block that surrounds the current block, or null if this + * block has no surrounding block. A parent block might just be the previous + * statement, whereas the surrounding block is an if statement, while loop, etc. + * @return {Blockly.Block} The block that surrounds the current block. + */ +Blockly.Block.prototype.getSurroundParent = function() { + var block = this; + while (true) { + do { + var prevBlock = block; + block = block.getParent(); + if (!block) { + // Ran off the top. + return null; + } + } while (block.nextConnection && + block.nextConnection.targetBlock() == prevBlock); + // This block is an enclosing parent, not just a statement in a stack. + return block; + } +}; + +/** + * Return the top-most block in this block's tree. + * This will return itself if this block is at the top level. + * @return {!Blockly.Block} The root block. + */ +Blockly.Block.prototype.getRootBlock = function() { + var rootBlock; + var block = this; + do { + rootBlock = block; + block = rootBlock.parentBlock_; + } while (block); + return rootBlock; +}; + +/** + * Find all the blocks that are directly nested inside this one. + * Includes value and block inputs, as well as any following statement. + * Excludes any connection on an output tab or any preceding statement. + * @return {!Array.} Array of blocks. + */ +Blockly.Block.prototype.getChildren = function() { + return this.childBlocks_; +}; + +/** + * Set parent of this block to be a new block or null. + * @param {Blockly.Block} newParent New parent block. + */ +Blockly.Block.prototype.setParent = function(newParent) { + if (this.parentBlock_) { + // Remove this block from the old parent's child list. + var children = this.parentBlock_.childBlocks_; + for (var child, x = 0; child = children[x]; x++) { + if (child == this) { + children.splice(x, 1); + break; + } + } + // Move this block up the DOM. Keep track of x/y translations. + var xy = this.getRelativeToSurfaceXY(); + this.workspace.getCanvas().appendChild(this.svg_.getRootElement()); + this.svg_.getRootElement().setAttribute('transform', + 'translate(' + xy.x + ', ' + xy.y + ')'); + + // Disconnect from superior blocks. + this.parentBlock_ = null; + if (this.previousConnection && this.previousConnection.targetConnection) { + this.previousConnection.disconnect(); + } + if (this.outputConnection && this.outputConnection.targetConnection) { + this.outputConnection.disconnect(); + } + // This block hasn't actually moved on-screen, so there's no need to update + // its connection locations. + } else { + // Remove this block from the workspace's list of top-most blocks. + this.workspace.removeTopBlock(this); + } + + this.parentBlock_ = newParent; + if (newParent) { + // Add this block to the new parent's child list. + newParent.childBlocks_.push(this); + + var oldXY = this.getRelativeToSurfaceXY(); + if (newParent.svg_ && this.svg_) { + newParent.svg_.getRootElement().appendChild(this.svg_.getRootElement()); + } + var newXY = this.getRelativeToSurfaceXY(); + // Move the connections to match the child's new position. + this.moveConnections_(newXY.x - oldXY.x, newXY.y - oldXY.y); + } else { + this.workspace.addTopBlock(this); + } +}; + +/** + * Find all the blocks that are directly or indirectly nested inside this one. + * Includes this block in the list. + * Includes value and block inputs, as well as any following statements. + * Excludes any connection on an output tab or any preceding statements. + * @return {!Array.} Flattened array of blocks. + */ +Blockly.Block.prototype.getDescendants = function() { + var blocks = [this]; + for (var child, x = 0; child = this.childBlocks_[x]; x++) { + blocks = blocks.concat(child.getDescendants()); + } + return blocks; +}; + +/** + * Get whether this block is deletable or not. + * @return {boolean} True if deletable. + */ +Blockly.Block.prototype.isDeletable = function() { + return this.deletable_ && !Blockly.readOnly; +}; + +/** + * Set whether this block is deletable or not. + * @param {boolean} deletable True if deletable. + */ +Blockly.Block.prototype.setDeletable = function(deletable) { + this.deletable_ = deletable; + this.svg_ && this.svg_.updateMovable(); +}; + +/** + * Get whether this block is movable or not. + * @return {boolean} True if movable. + */ +Blockly.Block.prototype.isMovable = function() { + return this.movable_ && !Blockly.readOnly; +}; + +/** + * Set whether this block is movable or not. + * @param {boolean} movable True if movable. + */ +Blockly.Block.prototype.setMovable = function(movable) { + this.movable_ = movable; +}; + +/** + * Get whether this block is editable or not. + * @return {boolean} True if editable. + */ +Blockly.Block.prototype.isEditable = function() { + return this.editable_ && !Blockly.readOnly; +}; + +/** + * Set whether this block is editable or not. + * @param {boolean} editable True if editable. + */ +Blockly.Block.prototype.setEditable = function(editable) { + this.editable_ = editable; + for (var x = 0, input; input = this.inputList[x]; x++) { + for (var y = 0, title; title = input.titleRow[y]; y++) { + title.updateEditable(); + } + } + var icons = this.getIcons(); + for (var x = 0; x < icons.length; x++) { + icons[x].updateEditable(); + } +}; + +/** + * Set the URL of this block's help page. + * @param {string|Function} url URL string for block help, or function that + * returns a URL. Null for no help. + */ +Blockly.Block.prototype.setHelpUrl = function(url) { + this.helpUrl = url; +}; + +/** + * Get the colour of a block. + * @return {number} HSV hue value. + */ +Blockly.Block.prototype.getColour = function() { + return this.colourHue_; +}; + +/** + * Change the colour of a block. + * @param {number} colourHue HSV hue value. + */ +Blockly.Block.prototype.setColour = function(colourHue) { + this.colourHue_ = colourHue; + if (this.svg_) { + this.svg_.updateColour(); + } + var icons = this.getIcons(); + for (var x = 0; x < icons.length; x++) { + icons[x].updateColour(); + } + if (this.rendered) { + // Bump every dropdown to change its colour. + for (var x = 0, input; input = this.inputList[x]; x++) { + for (var y = 0, title; title = input.titleRow[y]; y++) { + title.setText(null); + } + } + this.render(); + } +}; + +/** + * Returns the named title from a block. + * @param {string} name The name of the title. + * @return {Blockly.Field} Named title, or null if title does not exist. + * @private + */ +Blockly.Block.prototype.getTitle_ = function(name) { + for (var x = 0, input; input = this.inputList[x]; x++) { + for (var y = 0, title; title = input.titleRow[y]; y++) { + if (title.name === name) { + return title; + } + } + } + return null; +}; + +/** + * Returns the language-neutral value from the title of a block. + * @param {string} name The name of the title. + * @return {?string} Value from the title or null if title does not exist. + */ +Blockly.Block.prototype.getTitleValue = function(name) { + var title = this.getTitle_(name); + if (title) { + return title.getValue(); + } + return null; +}; + +/** + * Change the title value for a block (e.g. 'CHOOSE' or 'REMOVE'). + * @param {string} newValue Value to be the new title. + * @param {string} name The name of the title. + */ +Blockly.Block.prototype.setTitleValue = function(newValue, name) { + var title = this.getTitle_(name); + goog.asserts.assertObject(title, 'Title "%s" not found.', name); + title.setValue(newValue); +}; + +/** + * Change the tooltip text for a block. + * @param {string|!Element} newTip Text for tooltip or a parent element to + * link to for its tooltip. + */ +Blockly.Block.prototype.setTooltip = function(newTip) { + this.tooltip = newTip; +}; + +/** + * Set whether this block can chain onto the bottom of another block. + * @param {boolean} newBoolean True if there can be a previous statement. + * @param {string|Array.|null} opt_check Statement type or list of + * statement types. Null or undefined if any type could be connected. + */ +Blockly.Block.prototype.setPreviousStatement = function(newBoolean, opt_check) { + if (this.previousConnection) { + goog.asserts.assert(!this.previousConnection.targetConnection, + 'Must disconnect previous statement before removing connection.'); + this.previousConnection.dispose(); + this.previousConnection = null; + } + if (newBoolean) { + goog.asserts.assert(!this.outputConnection, + 'Remove output connection prior to adding previous connection.'); + if (opt_check === undefined) { + opt_check = null; + } + this.previousConnection = + new Blockly.Connection(this, Blockly.PREVIOUS_STATEMENT); + this.previousConnection.setCheck(opt_check); + } + if (this.rendered) { + this.render(); + this.bumpNeighbours_(); + } +}; + +/** + * Set whether another block can chain onto the bottom of this block. + * @param {boolean} newBoolean True if there can be a next statement. + * @param {string|Array.|null} opt_check Statement type or list of + * statement types. Null or undefined if any type could be connected. + */ +Blockly.Block.prototype.setNextStatement = function(newBoolean, opt_check) { + if (this.nextConnection) { + goog.asserts.assert(!this.nextConnection.targetConnection, + 'Must disconnect next statement before removing connection.'); + this.nextConnection.dispose(); + this.nextConnection = null; + } + if (newBoolean) { + if (opt_check === undefined) { + opt_check = null; + } + this.nextConnection = + new Blockly.Connection(this, Blockly.NEXT_STATEMENT); + this.nextConnection.setCheck(opt_check); + } + if (this.rendered) { + this.render(); + this.bumpNeighbours_(); + } +}; + +/** + * Set whether this block returns a value. + * @param {boolean} newBoolean True if there is an output. + * @param {string|Array.|null} opt_check Returned type or list of + * returned types. Null or undefined if any type could be returned + * (e.g. variable get). + */ +Blockly.Block.prototype.setOutput = function(newBoolean, opt_check) { + if (this.outputConnection) { + goog.asserts.assert(!this.outputConnection.targetConnection, + 'Must disconnect output value before removing connection.'); + this.outputConnection.dispose(); + this.outputConnection = null; + } + if (newBoolean) { + goog.asserts.assert(!this.previousConnection, + 'Remove previous connection prior to adding output connection.'); + if (opt_check === undefined) { + opt_check = null; + } + this.outputConnection = + new Blockly.Connection(this, Blockly.OUTPUT_VALUE); + this.outputConnection.setCheck(opt_check); + } + if (this.rendered) { + this.render(); + this.bumpNeighbours_(); + } +}; + +/** + * Set whether value inputs are arranged horizontally or vertically. + * @param {boolean} newBoolean True if inputs are horizontal. + */ +Blockly.Block.prototype.setInputsInline = function(newBoolean) { + this.inputsInline = newBoolean; + if (this.rendered) { + this.render(); + this.bumpNeighbours_(); + this.workspace.fireChangeEvent(); + } +}; + +/** + * Set whether the block is disabled or not. + * @param {boolean} disabled True if disabled. + */ +Blockly.Block.prototype.setDisabled = function(disabled) { + if (this.disabled == disabled) { + return; + } + this.disabled = disabled; + this.svg_.updateDisabled(); + this.workspace.fireChangeEvent(); +}; + +/** + * Get whether the block is disabled or not due to parents. + * The block's own disabled property is not considered. + * @return {boolean} True if disabled. + */ +Blockly.Block.prototype.getInheritedDisabled = function() { + var block = this; + while (true) { + block = block.getSurroundParent(); + if (!block) { + // Ran off the top. + return false; + } else if (block.disabled) { + return true; + } + } +}; + +/** + * Get whether the block is collapsed or not. + * @return {boolean} True if collapsed. + */ +Blockly.Block.prototype.isCollapsed = function() { + return this.collapsed_; +}; + +/** + * Set whether the block is collapsed or not. + * @param {boolean} collapsed True if collapsed. + */ +Blockly.Block.prototype.setCollapsed = function(collapsed) { + if (this.collapsed_ == collapsed) { + return; + } + this.collapsed_ = collapsed; + var renderList = []; + // Show/hide the inputs. + for (var x = 0, input; input = this.inputList[x]; x++) { + renderList = renderList.concat(input.setVisible(!collapsed)); + } + + var COLLAPSED_INPUT_NAME = '_TEMP_COLLAPSED_INPUT'; + if (collapsed) { + var icons = this.getIcons(); + for (var x = 0; x < icons.length; x++) { + icons[x].setVisible(false); + } + var text = this.toString(Blockly.COLLAPSE_CHARS); + this.appendDummyInput(COLLAPSED_INPUT_NAME).appendTitle(text); + } else { + this.removeInput(COLLAPSED_INPUT_NAME) + } + + if (!renderList.length) { + // No child blocks, just render this block. + renderList[0] = this; + } + if (this.rendered) { + for (var x = 0, block; block = renderList[x]; x++) { + block.render(); + } + this.bumpNeighbours_(); + } +}; + +/** + * Create a human-readable text representation of this block and any children. + * @param {?number} opt_maxLength Truncate the string to this length. + * @return {string} Text of block. + */ +Blockly.Block.prototype.toString = function(opt_maxLength) { + var text = []; + for (var x = 0, input; input = this.inputList[x]; x++) { + for (var y = 0, title; title = input.titleRow[y]; y++) { + text.push(title.getText()); + } + if (input.connection) { + var child = input.connection.targetBlock(); + if (child) { + text.push(child.toString()); + } else { + text.push('?'); + } + } + } + text = goog.string.trim(text.join(' ')) || '???'; + if (opt_maxLength) { + // TODO: Improve truncation so that text from this block is given priority. + // TODO: Handle FieldImage better. + text = goog.string.truncate(text, opt_maxLength); + } + return text; +} + +/** + * Shortcut for appending a value input row. + * @param {string} name Language-neutral identifier which may used to find this + * input again. Should be unique to this block. + * @return {!Blockly.Input} The input object created. + */ +Blockly.Block.prototype.appendValueInput = function(name) { + return this.appendInput_(Blockly.INPUT_VALUE, name); +}; + +/** + * Shortcut for appending a statement input row. + * @param {string} name Language-neutral identifier which may used to find this + * input again. Should be unique to this block. + * @return {!Blockly.Input} The input object created. + */ +Blockly.Block.prototype.appendStatementInput = function(name) { + return this.appendInput_(Blockly.NEXT_STATEMENT, name); +}; + +/** + * Shortcut for appending a dummy input row. + * @param {string} opt_name Language-neutral identifier which may used to find + * this input again. Should be unique to this block. + * @return {!Blockly.Input} The input object created. + */ +Blockly.Block.prototype.appendDummyInput = function(opt_name) { + return this.appendInput_(Blockly.DUMMY_INPUT, opt_name || ''); +}; + +/** + * Interpolate a message string, creating titles and inputs. + * @param {string} msg The message string to parse. %1, %2, etc. are symbols + * for value inputs. + * @param {!Array.|number} var_args A series of tuples that + * each specify the value inputs to create. Each tuple has three values: + * the input name, its check type, and its title's alignment. The last + * parameter is not a tuple, but just an alignment for any trailing dummy + * input. This last parameter is mandatory; there may be any number of + * tuples (though the number of tuples must match the symbols in msg). + */ +Blockly.Block.prototype.interpolateMsg = function(msg, var_args) { + // Remove the msg from the start and the dummy alignment from the end of args. + goog.asserts.assertString(msg); + var dummyAlign = arguments.length - 1; + goog.asserts.assertNumber(dummyAlign); + + var tokens = msg.split(/(%\d)/); + for (var i = 0; i < tokens.length; i += 2) { + var text = goog.string.trim(tokens[i]); + var symbol = tokens[i + 1]; + if (symbol) { + // Value input. + var digit = parseInt(symbol.charAt(1), 10); + var tuple = arguments[digit]; + goog.asserts.assertArray(tuple, + 'Message symbol "%s" is out of range.', symbol); + this.appendValueInput(tuple[0]) + .setCheck(tuple[1]) + .setAlign(tuple[2]) + .appendTitle(text); + arguments[digit] = null; // Inputs may not be reused. + } else if (text) { + // Trailing dummy input. + this.appendDummyInput() + .setAlign(dummyAlign) + .appendTitle(text); + } + } + // Verify that all inputs were used. + for (var i = 1; i < arguments.length - 1; i++) { + goog.asserts.assert(arguments[i] === null, + 'Input "%%s" not used in message: "%s"', i, msg); + } + // Make the inputs inline unless there is only one input and + // no text follows it. + this.setInputsInline(!msg.match(/%1\s*$/)) +}; + +/** + * Add a value input, statement input or local variable to this block. + * @param {number} type Either Blockly.INPUT_VALUE or Blockly.NEXT_STATEMENT or + * Blockly.DUMMY_INPUT. + * @param {string} name Language-neutral identifier which may used to find this + * input again. Should be unique to this block. + * @return {!Blockly.Input} The input object created. + * @private + */ +Blockly.Block.prototype.appendInput_ = function(type, name) { + var connection = null; + if (type == Blockly.INPUT_VALUE || type == Blockly.NEXT_STATEMENT) { + connection = new Blockly.Connection(this, type); + } + var input = new Blockly.Input(type, name, this, connection); + // Append input to list. + this.inputList.push(input); + if (this.rendered) { + this.render(); + // Adding an input will cause the block to change shape. + this.bumpNeighbours_(); + } + return input; +}; + +/** + * Move an input to a different location on this block. + * @param {string} name The name of the input to move. + * @param {string} refName Name of input that should be after the moved input, + * or null to be the input at the end. + */ +Blockly.Block.prototype.moveInputBefore = function(name, refName) { + goog.asserts.assert(name != refName, 'Can\'t move "%s" to itself.', name); + // Find both inputs. + var inputIndex = -1; + var refIndex = refName ? -1 : this.inputList.length; + for (var x = 0, input; input = this.inputList[x]; x++) { + if (input.name == name) { + inputIndex = x; + if (refIndex != -1) { + break; + } + } else if (refName && input.name == refName) { + refIndex = x; + if (inputIndex != -1) { + break; + } + } + } + goog.asserts.assert(inputIndex != -1, 'Named input "%s" not found.', name); + goog.asserts.assert(refIndex && refIndex != -1, + 'Reference input "%s" not found.', refName); + // Remove input. + this.inputList.splice(inputIndex, 1); + if (inputIndex < refIndex) { + refIndex--; + } + // Reinsert input. + this.inputList.splice(refIndex, 0, input); + if (this.rendered) { + this.render(); + // Moving an input will cause the block to change shape. + this.bumpNeighbours_(); + } +}; + +/** + * Remove an input from this block. + * @param {string} name The name of the input. + * @param {boolean} opt_quiet True to prevent error if input is not present. + * @throws {goog.asserts.AssertionError} if the input is not present and + * opt_quiet is not true. + */ +Blockly.Block.prototype.removeInput = function(name, opt_quiet) { + for (var x = 0, input; input = this.inputList[x]; x++) { + if (input.name == name) { + if (input.connection && input.connection.targetConnection) { + // Disconnect any attached block. + input.connection.targetBlock().setParent(null); + } + input.dispose(); + this.inputList.splice(x, 1); + if (this.rendered) { + this.render(); + // Removing an input will cause the block to change shape. + this.bumpNeighbours_(); + } + return; + } + } + if (!opt_quiet) { + goog.asserts.fail('Input "%s" not found.', name); + } +}; + +/** + * Fetches the named input object. + * @param {string} name The name of the input. + * @return {Object} The input object, or null of the input does not exist. + */ +Blockly.Block.prototype.getInput = function(name) { + for (var x = 0, input; input = this.inputList[x]; x++) { + if (input.name == name) { + return input; + } + } + // This input does not exist. + return null; +}; + +/** + * Fetches the block attached to the named input. + * @param {string} name The name of the input. + * @return {Blockly.Block} The attached value block, or null if the input is + * either disconnected or if the input does not exist. + */ +Blockly.Block.prototype.getInputTargetBlock = function(name) { + var input = this.getInput(name); + return input && input.connection && input.connection.targetBlock(); +}; + +/** + * Give this block a mutator dialog. + * @param {Blockly.Mutator} mutator A mutator dialog instance or null to remove. + */ +Blockly.Block.prototype.setMutator = function(mutator) { + if (this.mutator && this.mutator !== mutator) { + this.mutator.dispose(); + } + if (mutator) { + mutator.block_ = this; + this.mutator = mutator; + if (this.svg_) { + mutator.createIcon(); + } + } +}; + +/** + * Returns the comment on this block (or '' if none). + * @return {string} Block's comment. + */ +Blockly.Block.prototype.getCommentText = function() { + if (this.comment) { + var comment = this.comment.getText(); + // Trim off trailing whitespace. + return comment.replace(/\s+$/, '').replace(/ +\n/g, '\n'); + } + return ''; +}; + +/** + * Set this block's comment text. + * @param {?string} text The text, or null to delete. + */ +Blockly.Block.prototype.setCommentText = function(text) { + var changedState = false; + if (goog.isString(text)) { + if (!this.comment) { + this.comment = new Blockly.Comment(this); + changedState = true; + } + this.comment.setText(/** @type {string} */ (text)); + } else { + if (this.comment) { + this.comment.dispose(); + changedState = true; + } + } + if (this.rendered) { + this.render(); + if (changedState) { + // Adding or removing a comment icon will cause the block to change shape. + this.bumpNeighbours_(); + } + } +}; + +/** + * Set this block's warning text. + * @param {?string} text The text, or null to delete. + */ +Blockly.Block.prototype.setWarningText = function(text) { + if (this.isInFlyout) { + text = null; + } + var changedState = false; + if (goog.isString(text)) { + if (!this.warning) { + this.warning = new Blockly.Warning(this); + changedState = true; + } + this.warning.setText(/** @type {string} */ (text)); + } else { + if (this.warning) { + this.warning.dispose(); + changedState = true; + } + } + if (changedState && this.rendered) { + this.render(); + // Adding or removing a warning icon will cause the block to change shape. + this.bumpNeighbours_(); + } +}; + +/** + * Render the block. + * Lays out and reflows a block based on its contents and settings. + */ +Blockly.Block.prototype.render = function() { + goog.asserts.assertObject(this.svg_, + 'Uninitialized block cannot be rendered. Call block.initSvg()'); + this.svg_.render(); +}; diff --git a/core/block_svg.js b/core/block_svg.js new file mode 100644 index 000000000..c6903ab98 --- /dev/null +++ b/core/block_svg.js @@ -0,0 +1,1130 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Methods for graphically rendering a block as SVG. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.BlockSvg'); + +goog.require('goog.userAgent'); + + +/** + * Class for a block's SVG representation. + * @param {!Blockly.Block} block The underlying block object. + * @constructor + */ +Blockly.BlockSvg = function(block) { + this.block_ = block; + // Create core elements for the block. + this.svgGroup_ = Blockly.createSvgElement('g', {}, null); + this.svgPathDark_ = Blockly.createSvgElement('path', + {'class': 'blocklyPathDark', 'transform': 'translate(1, 1)'}, + this.svgGroup_); + this.svgPath_ = Blockly.createSvgElement('path', {'class': 'blocklyPath'}, + this.svgGroup_); + this.svgPathLight_ = Blockly.createSvgElement('path', + {'class': 'blocklyPathLight'}, this.svgGroup_); + this.svgPath_.tooltip = this.block_; + Blockly.Tooltip && Blockly.Tooltip.bindMouseEvents(this.svgPath_); + this.updateMovable(); +}; + +/** + * Constant for identifying rows that are to be rendered inline. + * Don't collide with Blockly.INPUT_VALUE and friends. + * @const + */ +Blockly.BlockSvg.INLINE = -1; + +/** + * Initialize the SVG representation with any block attributes which have + * already been defined. + */ +Blockly.BlockSvg.prototype.init = function() { + var block = this.block_; + this.updateColour(); + for (var x = 0, input; input = block.inputList[x]; x++) { + input.init(); + } + if (block.mutator) { + block.mutator.createIcon(); + } +}; + +/** + * Add or remove the UI indicating if this block is movable or not. + */ +Blockly.BlockSvg.prototype.updateMovable = function() { + if (this.block_.isMovable()) { + Blockly.addClass_(/** @type {!Element} */ (this.svgGroup_), + 'blocklyDraggable'); + } else { + Blockly.removeClass_(/** @type {!Element} */ (this.svgGroup_), + 'blocklyDraggable'); + } +}; + +/** + * Get the root SVG element. + * @return {!Element} The root SVG element. + */ +Blockly.BlockSvg.prototype.getRootElement = function() { + return this.svgGroup_; +}; + +// UI constants for rendering blocks. +/** + * Horizontal space between elements. + * @const + */ +Blockly.BlockSvg.SEP_SPACE_X = 10; +/** + * Vertical space between elements. + * @const + */ +Blockly.BlockSvg.SEP_SPACE_Y = 10; +/** + * Vertical padding around inline elements. + * @const + */ +Blockly.BlockSvg.INLINE_PADDING_Y = 5; +/** + * Minimum height of a block. + * @const + */ +Blockly.BlockSvg.MIN_BLOCK_Y = 25; +/** + * Height of horizontal puzzle tab. + * @const + */ +Blockly.BlockSvg.TAB_HEIGHT = 20; +/** + * Width of horizontal puzzle tab. + * @const + */ +Blockly.BlockSvg.TAB_WIDTH = 8; +/** + * Width of vertical tab (inc left margin). + * @const + */ +Blockly.BlockSvg.NOTCH_WIDTH = 30; +/** + * Rounded corner radius. + * @const + */ +Blockly.BlockSvg.CORNER_RADIUS = 8; +/** + * Minimum height of title rows. + * @const + */ +Blockly.BlockSvg.TITLE_HEIGHT = 18; +/** + * Distance from shape edge to intersect with a curved corner at 45 degrees. + * Applies to highlighting on around the inside of a curve. + * @const + */ +Blockly.BlockSvg.DISTANCE_45_INSIDE = (1 - Math.SQRT1_2) * + (Blockly.BlockSvg.CORNER_RADIUS - 1) + 1; +/** + * Distance from shape edge to intersect with a curved corner at 45 degrees. + * Applies to highlighting on around the outside of a curve. + * @const + */ +Blockly.BlockSvg.DISTANCE_45_OUTSIDE = (1 - Math.SQRT1_2) * + (Blockly.BlockSvg.CORNER_RADIUS + 1) - 1; +/** + * SVG path for drawing next/previous notch from left to right. + * @const + */ +Blockly.BlockSvg.NOTCH_PATH_LEFT = 'l 6,4 3,0 6,-4'; +/** + * SVG path for drawing next/previous notch from left to right with + * highlighting. + * @const + */ +Blockly.BlockSvg.NOTCH_PATH_LEFT_HIGHLIGHT = 'l 6.5,4 2,0 6.5,-4'; +/** + * SVG path for drawing next/previous notch from right to left. + * @const + */ +Blockly.BlockSvg.NOTCH_PATH_RIGHT = 'l -6,4 -3,0 -6,-4'; +/** + * SVG path for drawing jagged teeth at the end of collapsed blocks. + * @const + */ +Blockly.BlockSvg.JAGGED_TEETH = 'l 8,0 0,4 8,4 -16,8 8,4'; +/** + * SVG path for drawing jagged teeth at the end of collapsed blocks. + * @const + */ +Blockly.BlockSvg.JAGGED_TEETH_HEIGHT = 20; +/** + * SVG path for drawing a horizontal puzzle tab from top to bottom. + * @const + */ +Blockly.BlockSvg.TAB_PATH_DOWN = 'v 5 c 0,10 -' + Blockly.BlockSvg.TAB_WIDTH + + ',-8 -' + Blockly.BlockSvg.TAB_WIDTH + ',7.5 s ' + + Blockly.BlockSvg.TAB_WIDTH + ',-2.5 ' + Blockly.BlockSvg.TAB_WIDTH + ',7.5'; +/** + * SVG path for drawing a horizontal puzzle tab from top to bottom with + * highlighting from the upper-right. + * @const + */ +Blockly.BlockSvg.TAB_PATH_DOWN_HIGHLIGHT_RTL = 'v 6.5 m -' + + (Blockly.BlockSvg.TAB_WIDTH * 0.98) + ',2.5 q -' + + (Blockly.BlockSvg.TAB_WIDTH * .05) + ',10 ' + + (Blockly.BlockSvg.TAB_WIDTH * .27) + ',10 m ' + + (Blockly.BlockSvg.TAB_WIDTH * .71) + ',-2.5 v 1.5'; + +/** + * SVG start point for drawing the top-left corner. + * @const + */ +Blockly.BlockSvg.TOP_LEFT_CORNER_START = + 'm 0,' + Blockly.BlockSvg.CORNER_RADIUS; +/** + * SVG start point for drawing the top-left corner's highlight in RTL. + * @const + */ +Blockly.BlockSvg.TOP_LEFT_CORNER_START_HIGHLIGHT_RTL = + 'm ' + Blockly.BlockSvg.DISTANCE_45_INSIDE + ',' + + Blockly.BlockSvg.DISTANCE_45_INSIDE; +/** + * SVG start point for drawing the top-left corner's highlight in LTR. + * @const + */ +Blockly.BlockSvg.TOP_LEFT_CORNER_START_HIGHLIGHT_LTR = + 'm 1,' + (Blockly.BlockSvg.CORNER_RADIUS - 1); +/** + * SVG path for drawing the rounded top-left corner. + * @const + */ +Blockly.BlockSvg.TOP_LEFT_CORNER = + 'A ' + Blockly.BlockSvg.CORNER_RADIUS + ',' + + Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,1 ' + + Blockly.BlockSvg.CORNER_RADIUS + ',0'; +/** + * SVG path for drawing the highlight on the rounded top-left corner. + * @const + */ +Blockly.BlockSvg.TOP_LEFT_CORNER_HIGHLIGHT = + 'A ' + (Blockly.BlockSvg.CORNER_RADIUS - 1) + ',' + + (Blockly.BlockSvg.CORNER_RADIUS - 1) + ' 0 0,1 ' + + Blockly.BlockSvg.CORNER_RADIUS + ',1'; +/** + * SVG path for drawing the top-left corner of a statement input. + * Includes the top notch, a horizontal space, and the rounded inside corner. + * @const + */ +Blockly.BlockSvg.INNER_TOP_LEFT_CORNER = + Blockly.BlockSvg.NOTCH_PATH_RIGHT + ' h -' + + (Blockly.BlockSvg.NOTCH_WIDTH - 15 - Blockly.BlockSvg.CORNER_RADIUS) + + ' a ' + Blockly.BlockSvg.CORNER_RADIUS + ',' + + Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 -' + + Blockly.BlockSvg.CORNER_RADIUS + ',' + + Blockly.BlockSvg.CORNER_RADIUS; +/** + * SVG path for drawing the bottom-left corner of a statement input. + * Includes the rounded inside corner. + * @const + */ +Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER = + 'a ' + Blockly.BlockSvg.CORNER_RADIUS + ',' + + Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 ' + + Blockly.BlockSvg.CORNER_RADIUS + ',' + + Blockly.BlockSvg.CORNER_RADIUS; +/** + * SVG path for drawing highlight on the top-left corner of a statement + * input in RTL. + * @const + */ +Blockly.BlockSvg.INNER_TOP_LEFT_CORNER_HIGHLIGHT_RTL = + 'a ' + (Blockly.BlockSvg.CORNER_RADIUS + 1) + ',' + + (Blockly.BlockSvg.CORNER_RADIUS + 1) + ' 0 0,0 ' + + (-Blockly.BlockSvg.DISTANCE_45_OUTSIDE - 1) + ',' + + (Blockly.BlockSvg.CORNER_RADIUS - + Blockly.BlockSvg.DISTANCE_45_OUTSIDE); +/** + * SVG path for drawing highlight on the bottom-left corner of a statement + * input in RTL. + * @const + */ +Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER_HIGHLIGHT_RTL = + 'a ' + (Blockly.BlockSvg.CORNER_RADIUS + 1) + ',' + + (Blockly.BlockSvg.CORNER_RADIUS + 1) + ' 0 0,0 ' + + (Blockly.BlockSvg.CORNER_RADIUS + 1) + ',' + + (Blockly.BlockSvg.CORNER_RADIUS + 1); +/** + * SVG path for drawing highlight on the bottom-left corner of a statement + * input in LTR. + * @const + */ +Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER_HIGHLIGHT_LTR = + 'a ' + (Blockly.BlockSvg.CORNER_RADIUS + 1) + ',' + + (Blockly.BlockSvg.CORNER_RADIUS + 1) + ' 0 0,0 ' + + (Blockly.BlockSvg.CORNER_RADIUS - + Blockly.BlockSvg.DISTANCE_45_OUTSIDE) + ',' + + (Blockly.BlockSvg.DISTANCE_45_OUTSIDE + 1); + +/** + * Dispose of this SVG block. + */ +Blockly.BlockSvg.prototype.dispose = function() { + goog.dom.removeNode(this.svgGroup_); + // Sever JavaScript to DOM connections. + this.svgGroup_ = null; + this.svgPath_ = null; + this.svgPathLight_ = null; + this.svgPathDark_ = null; + // Break circular references. + this.block_ = null; +}; + +/** + * Play some UI effects (sound, animation) when disposing of a block. + */ +Blockly.BlockSvg.prototype.disposeUiEffect = function() { + Blockly.playAudio('delete'); + + var xy = Blockly.getSvgXY_(/** @type {!Element} */ (this.svgGroup_)); + // Deeply clone the current block. + var clone = this.svgGroup_.cloneNode(true); + clone.translateX_ = xy.x; + clone.translateY_ = xy.y; + clone.setAttribute('transform', + 'translate(' + clone.translateX_ + ',' + clone.translateY_ + ')'); + Blockly.svg.appendChild(clone); + clone.bBox_ = clone.getBBox(); + // Start the animation. + clone.startDate_ = new Date(); + Blockly.BlockSvg.disposeUiStep_(clone); +}; + +/** + * Animate a cloned block and eventually dispose of it. + * @param {!Element} clone SVG element to animate and dispose of. + * @private + */ +Blockly.BlockSvg.disposeUiStep_ = function(clone) { + var ms = (new Date()) - clone.startDate_; + var percent = ms / 150; + if (percent > 1) { + goog.dom.removeNode(clone); + } else { + var x = clone.translateX_ + + (Blockly.RTL ? -1 : 1) * clone.bBox_.width / 2 * percent; + var y = clone.translateY_ + clone.bBox_.height * percent; + var translate = x + ', ' + y; + var scale = 1 - percent; + clone.setAttribute('transform', 'translate(' + translate + ')' + + ' scale(' + scale + ')'); + var closure = function() { + Blockly.BlockSvg.disposeUiStep_(clone); + }; + window.setTimeout(closure, 10); + } +}; + +/** + * Play some UI effects (sound, ripple) after a connection has been established. + */ +Blockly.BlockSvg.prototype.connectionUiEffect = function() { + Blockly.playAudio('click'); + + // Determine the absolute coordinates of the inferior block. + var xy = Blockly.getSvgXY_(/** @type {!Element} */ (this.svgGroup_)); + // Offset the coordinates based on the two connection types. + if (this.block_.outputConnection) { + xy.x += Blockly.RTL ? 3 : -3; + xy.y += 13; + } else if (this.block_.previousConnection) { + xy.x += Blockly.RTL ? -23 : 23; + xy.y += 3; + } + var ripple = Blockly.createSvgElement('circle', + {'cx': xy.x, 'cy': xy.y, 'r': 0, 'fill': 'none', + 'stroke': '#888', 'stroke-width': 10}, + Blockly.svg); + // Start the animation. + ripple.startDate_ = new Date(); + Blockly.BlockSvg.connectionUiStep_(ripple); +}; + +/** + * Expand a ripple around a connection. + * @param {!Element} ripple Element to animate. + * @private + */ +Blockly.BlockSvg.connectionUiStep_ = function(ripple) { + var ms = (new Date()) - ripple.startDate_; + var percent = ms / 150; + if (percent > 1) { + goog.dom.removeNode(ripple); + } else { + ripple.setAttribute('r', percent * 25); + ripple.style.opacity = 1 - percent; + var closure = function() { + Blockly.BlockSvg.connectionUiStep_(ripple); + }; + window.setTimeout(closure, 10); + } +}; + +/** + * Change the colour of a block. + */ +Blockly.BlockSvg.prototype.updateColour = function() { + if (this.block_.disabled) { + // Disabled blocks don't have colour. + return; + } + var hexColour = Blockly.makeColour(this.block_.getColour()); + var rgb = goog.color.hexToRgb(hexColour); + var rgbLight = goog.color.lighten(rgb, 0.3); + var rgbDark = goog.color.darken(rgb, 0.4); + this.svgPathLight_.setAttribute('stroke', goog.color.rgbArrayToHex(rgbLight)); + this.svgPathDark_.setAttribute('fill', goog.color.rgbArrayToHex(rgbDark)); + this.svgPath_.setAttribute('fill', hexColour); +}; + +/** + * Enable or disable a block. + */ +Blockly.BlockSvg.prototype.updateDisabled = function() { + if (this.block_.disabled || this.block_.getInheritedDisabled()) { + Blockly.addClass_(/** @type {!Element} */ (this.svgGroup_), + 'blocklyDisabled'); + this.svgPath_.setAttribute('fill', 'url(#blocklyDisabledPattern)'); + } else { + Blockly.removeClass_(/** @type {!Element} */ (this.svgGroup_), + 'blocklyDisabled'); + this.updateColour(); + } + var children = this.block_.getChildren(); + for (var x = 0, child; child = children[x]; x++) { + child.svg_.updateDisabled(); + } +}; + +/** + * Select this block. Highlight it visually. + */ +Blockly.BlockSvg.prototype.addSelect = function() { + Blockly.addClass_(/** @type {!Element} */ (this.svgGroup_), + 'blocklySelected'); + // Move the selected block to the top of the stack. + this.svgGroup_.parentNode.appendChild(this.svgGroup_); +}; + +/** + * Unselect this block. Remove its highlighting. + */ +Blockly.BlockSvg.prototype.removeSelect = function() { + Blockly.removeClass_(/** @type {!Element} */ (this.svgGroup_), + 'blocklySelected'); +}; + +/** + * Adds the dragging class to this block. + * Also disables the highlights/shadows to improve performance. + */ +Blockly.BlockSvg.prototype.addDragging = function() { + Blockly.addClass_(/** @type {!Element} */ (this.svgGroup_), + 'blocklyDragging'); +}; + +/** + * Removes the dragging class from this block. + */ +Blockly.BlockSvg.prototype.removeDragging = function() { + Blockly.removeClass_(/** @type {!Element} */ (this.svgGroup_), + 'blocklyDragging'); +}; + +/** + * Render the block. + * Lays out and reflows a block based on its contents and settings. + */ +Blockly.BlockSvg.prototype.render = function() { + this.block_.rendered = true; + + var cursorX = Blockly.BlockSvg.SEP_SPACE_X; + if (Blockly.RTL) { + cursorX = -cursorX; + } + // Move the icons into position. + var icons = this.block_.getIcons(); + for (var x = 0; x < icons.length; x++) { + cursorX = icons[x].renderIcon(cursorX); + } + cursorX += Blockly.RTL ? + Blockly.BlockSvg.SEP_SPACE_X : -Blockly.BlockSvg.SEP_SPACE_X; + // If there are no icons, cursorX will be 0, otherwise it will be the + // width that the first label needs to move over by. + + var inputRows = this.renderCompute_(cursorX); + this.renderDraw_(cursorX, inputRows); + + // Render all blocks above this one (propagate a reflow). + var parentBlock = this.block_.getParent(); + if (parentBlock) { + parentBlock.render(); + } else { + // Top-most block. Fire an event to allow scrollbars to resize. + Blockly.fireUiEvent(window, 'resize'); + } +}; + +/** + * Render a list of titles starting at the specified location. + * @param {!Array.} titleList List of titles. + * @param {number} cursorX X-coordinate to start the titles. + * @param {number} cursorY Y-coordinate to start the titles. + * @return {number} X-coordinate of the end of the title row (plus a gap). + * @private + */ +Blockly.BlockSvg.prototype.renderTitles_ = function(titleList, + cursorX, cursorY) { + if (Blockly.RTL) { + cursorX = -cursorX; + } + for (var t = 0, title; title = titleList[t]; t++) { + // Get the dimensions of the title. + var titleSize = title.getSize(); + var titleWidth = titleSize.width; + + if (Blockly.RTL) { + cursorX -= titleWidth; + title.getRootElement().setAttribute('transform', + 'translate(' + cursorX + ', ' + cursorY + ')'); + if (titleWidth) { + cursorX -= Blockly.BlockSvg.SEP_SPACE_X; + } + } else { + title.getRootElement().setAttribute('transform', + 'translate(' + cursorX + ', ' + cursorY + ')'); + if (titleWidth) { + cursorX += titleWidth + Blockly.BlockSvg.SEP_SPACE_X; + } + } + } + return Blockly.RTL ? -cursorX : cursorX; +}; + +/** + * Computes the height and widths for each row and title. + * @param {number} iconWidth Offset of first row due to icons. + * @return {!Array.>} 2D array of objects, each containing + * position information. + * @private + */ +Blockly.BlockSvg.prototype.renderCompute_ = function(iconWidth) { + var inputList = this.block_.inputList; + var inputRows = []; + inputRows.rightEdge = iconWidth + Blockly.BlockSvg.SEP_SPACE_X * 2; + if (this.block_.previousConnection || this.block_.nextConnection) { + inputRows.rightEdge = Math.max(inputRows.rightEdge, + Blockly.BlockSvg.NOTCH_WIDTH + Blockly.BlockSvg.SEP_SPACE_X); + } + var titleValueWidth = 0; // Width of longest external value title. + var titleStatementWidth = 0; // Width of longest statement title. + var hasValue = false; + var hasStatement = false; + var hasDummy = false; + var lastType = undefined; + var isInline = this.block_.inputsInline && !this.block_.isCollapsed(); + for (var i = 0, input; input = inputList[i]; i++) { + if (!input.isVisible()) { + continue; + } + var row; + if (!isInline || !lastType || + lastType == Blockly.NEXT_STATEMENT || + input.type == Blockly.NEXT_STATEMENT) { + // Create new row. + lastType = input.type; + row = []; + if (isInline && input.type != Blockly.NEXT_STATEMENT) { + row.type = Blockly.BlockSvg.INLINE; + } else { + row.type = input.type; + } + row.height = 0; + inputRows.push(row); + } else { + row = inputRows[inputRows.length - 1]; + } + row.push(input); + + // Compute minimum input size. + input.renderHeight = Blockly.BlockSvg.MIN_BLOCK_Y; + // The width is currently only needed for inline value inputs. + if (isInline && input.type == Blockly.INPUT_VALUE) { + input.renderWidth = Blockly.BlockSvg.TAB_WIDTH + + Blockly.BlockSvg.SEP_SPACE_X; + } else { + input.renderWidth = 0; + } + // Expand input size if there is a connection. + if (input.connection && input.connection.targetConnection) { + var linkedBlock = input.connection.targetBlock(); + var bBox = linkedBlock.getHeightWidth(); + input.renderHeight = Math.max(input.renderHeight, bBox.height); + input.renderWidth = Math.max(input.renderWidth, bBox.width); + } + + row.height = Math.max(row.height, input.renderHeight); + input.titleWidth = 0; + if (inputRows.length == 1) { + // The first row gets shifted to accommodate any icons. + input.titleWidth += Blockly.RTL ? -iconWidth : iconWidth; + } + for (var j = 0, title; title = input.titleRow[j]; j++) { + if (j != 0) { + input.titleWidth += Blockly.BlockSvg.SEP_SPACE_X; + } + // Get the dimensions of the title. + var titleSize = title.getSize(); + input.titleWidth += titleSize.width; + row.height = Math.max(row.height, titleSize.height); + } + + if (row.type != Blockly.BlockSvg.INLINE) { + if (row.type == Blockly.NEXT_STATEMENT) { + hasStatement = true; + titleStatementWidth = Math.max(titleStatementWidth, input.titleWidth); + } else { + if (row.type == Blockly.INPUT_VALUE) { + hasValue = true; + } else if (row.type == Blockly.DUMMY_INPUT) { + hasDummy = true; + } + titleValueWidth = Math.max(titleValueWidth, input.titleWidth); + } + } + } + + // Make inline rows a bit thicker in order to enclose the values. + for (var y = 0, row; row = inputRows[y]; y++) { + row.thicker = false; + if (row.type == Blockly.BlockSvg.INLINE) { + for (var z = 0, input; input = row[z]; z++) { + if (input.type == Blockly.INPUT_VALUE) { + row.height += 2 * Blockly.BlockSvg.INLINE_PADDING_Y; + row.thicker = true; + break; + } + } + } + } + + // Compute the statement edge. + // This is the width of a block where statements are nested. + inputRows.statementEdge = 2 * Blockly.BlockSvg.SEP_SPACE_X + + titleStatementWidth; + // Compute the preferred right edge. Inline blocks may extend beyond. + // This is the width of the block where external inputs connect. + if (hasStatement) { + inputRows.rightEdge = Math.max(inputRows.rightEdge, + inputRows.statementEdge + Blockly.BlockSvg.NOTCH_WIDTH); + } + if (hasValue) { + inputRows.rightEdge = Math.max(inputRows.rightEdge, titleValueWidth + + Blockly.BlockSvg.SEP_SPACE_X * 2 + Blockly.BlockSvg.TAB_WIDTH); + } else if (hasDummy) { + inputRows.rightEdge = Math.max(inputRows.rightEdge, titleValueWidth + + Blockly.BlockSvg.SEP_SPACE_X * 2); + } + + inputRows.hasValue = hasValue; + inputRows.hasStatement = hasStatement; + inputRows.hasDummy = hasDummy; + return inputRows; +}; + + +/** + * Draw the path of the block. + * Move the titles to the correct locations. + * @param {number} iconWidth Offset of first row due to icons. + * @param {!Array.>} inputRows 2D array of objects, each + * containing position information. + * @private + */ +Blockly.BlockSvg.prototype.renderDraw_ = function(iconWidth, inputRows) { + // Should the top and bottom left corners be rounded or square? + if (this.block_.outputConnection) { + this.squareTopLeftCorner_ = true; + this.squareBottomLeftCorner_ = true; + } else { + this.squareTopLeftCorner_ = false; + this.squareBottomLeftCorner_ = false; + // If this block is in the middle of a stack, square the corners. + if (this.block_.previousConnection) { + var prevBlock = this.block_.previousConnection.targetBlock(); + if (prevBlock && prevBlock.nextConnection && + prevBlock.nextConnection.targetConnection == + this.block_.previousConnection) { + this.squareTopLeftCorner_ = true; + } + } + if (this.block_.nextConnection) { + var nextBlock = this.block_.nextConnection.targetBlock(); + if (nextBlock && nextBlock.previousConnection && + nextBlock.previousConnection.targetConnection == + this.block_.nextConnection) { + this.squareBottomLeftCorner_ = true; + } + } + } + + // Fetch the block's coordinates on the surface for use in anchoring + // the connections. + var connectionsXY = this.block_.getRelativeToSurfaceXY(); + + // Assemble the block's path. + var steps = []; + var inlineSteps = []; + // The highlighting applies to edges facing the upper-left corner. + // Since highlighting is a two-pixel wide border, it would normally overhang + // the edge of the block by a pixel. So undersize all measurements by a pixel. + var highlightSteps = []; + var highlightInlineSteps = []; + + this.renderDrawTop_(steps, highlightSteps, connectionsXY, + inputRows.rightEdge); + var cursorY = this.renderDrawRight_(steps, highlightSteps, inlineSteps, + highlightInlineSteps, connectionsXY, inputRows, iconWidth); + this.renderDrawBottom_(steps, highlightSteps, connectionsXY, cursorY); + this.renderDrawLeft_(steps, highlightSteps, connectionsXY, cursorY); + + var pathString = steps.join(' ') + '\n' + inlineSteps.join(' '); + this.svgPath_.setAttribute('d', pathString); + this.svgPathDark_.setAttribute('d', pathString); + pathString = highlightSteps.join(' ') + '\n' + highlightInlineSteps.join(' '); + this.svgPathLight_.setAttribute('d', pathString); + if (Blockly.RTL) { + // Mirror the block's path. + this.svgPath_.setAttribute('transform', 'scale(-1 1)'); + this.svgPathLight_.setAttribute('transform', 'scale(-1 1)'); + this.svgPathDark_.setAttribute('transform', 'translate(1,1) scale(-1 1)'); + } +}; + +/** + * Render the top edge of the block. + * @param {!Array.} steps Path of block outline. + * @param {!Array.} highlightSteps Path of block highlights. + * @param {!Object} connectionsXY Location of block. + * @param {number} rightEdge Minimum width of block. + * @private + */ +Blockly.BlockSvg.prototype.renderDrawTop_ = + function(steps, highlightSteps, connectionsXY, rightEdge) { + // Position the cursor at the top-left starting point. + if (this.squareTopLeftCorner_) { + steps.push('m 0,0'); + highlightSteps.push('m 1,1'); + } else { + steps.push(Blockly.BlockSvg.TOP_LEFT_CORNER_START); + highlightSteps.push(Blockly.RTL ? + Blockly.BlockSvg.TOP_LEFT_CORNER_START_HIGHLIGHT_RTL : + Blockly.BlockSvg.TOP_LEFT_CORNER_START_HIGHLIGHT_LTR); + // Top-left rounded corner. + steps.push(Blockly.BlockSvg.TOP_LEFT_CORNER); + highlightSteps.push(Blockly.BlockSvg.TOP_LEFT_CORNER_HIGHLIGHT); + } + if (Blockly.BROKEN_CONTROL_POINTS) { + /* HACK: + WebKit bug 67298 causes control points to be included in the reported + bounding box. Add 5px control point to the top of the path. + */ + steps.push('c 0,5 0,-5 0,0'); + } + + // Top edge. + if (this.block_.previousConnection) { + steps.push('H', Blockly.BlockSvg.NOTCH_WIDTH - 15); + highlightSteps.push('H', Blockly.BlockSvg.NOTCH_WIDTH - 15); + steps.push(Blockly.BlockSvg.NOTCH_PATH_LEFT); + highlightSteps.push(Blockly.BlockSvg.NOTCH_PATH_LEFT_HIGHLIGHT); + // Create previous block connection. + var connectionX = connectionsXY.x + (Blockly.RTL ? + -Blockly.BlockSvg.NOTCH_WIDTH : Blockly.BlockSvg.NOTCH_WIDTH); + var connectionY = connectionsXY.y; + this.block_.previousConnection.moveTo(connectionX, connectionY); + // This connection will be tightened when the parent renders. + } + steps.push('H', rightEdge); + highlightSteps.push('H', rightEdge + (Blockly.RTL ? -1 : 0)); +}; + +/** + * Render the right edge of the block. + * @param {!Array.} steps Path of block outline. + * @param {!Array.} highlightSteps Path of block highlights. + * @param {!Array.} inlineSteps Inline block outlines. + * @param {!Array.} highlightInlineSteps Inline block highlights. + * @param {!Object} connectionsXY Location of block. + * @param {!Array.>} inputRows 2D array of objects, each + * containing position information. + * @param {number} iconWidth Offset of first row due to icons. + * @return {number} Height of block. + * @private + */ +Blockly.BlockSvg.prototype.renderDrawRight_ = function(steps, highlightSteps, + inlineSteps, highlightInlineSteps, connectionsXY, inputRows, iconWidth) { + var cursorX; + var cursorY = 0; + var connectionX, connectionY; + for (var y = 0, row; row = inputRows[y]; y++) { + cursorX = Blockly.BlockSvg.SEP_SPACE_X; + if (y == 0) { + cursorX += Blockly.RTL ? -iconWidth : iconWidth; + } + highlightSteps.push('M', (inputRows.rightEdge - 1) + ',' + (cursorY + 1)); + if (this.block_.isCollapsed()) { + // Jagged right edge. + var input = row[0]; + var titleX = cursorX; + var titleY = cursorY + Blockly.BlockSvg.TITLE_HEIGHT; + this.renderTitles_(input.titleRow, titleX, titleY); + steps.push(Blockly.BlockSvg.JAGGED_TEETH); + if (Blockly.RTL) { + highlightSteps.push('l 8,0 0,3.8 7,3.2 m -14.5,9 l 8,4'); + } else { + highlightSteps.push('h 8'); + } + var remainder = row.height - Blockly.BlockSvg.JAGGED_TEETH_HEIGHT; + steps.push('v', remainder); + if (Blockly.RTL) { + highlightSteps.push('v', remainder - 2); + } + } else if (row.type == Blockly.BlockSvg.INLINE) { + // Inline inputs. + for (var x = 0, input; input = row[x]; x++) { + var titleX = cursorX; + var titleY = cursorY + Blockly.BlockSvg.TITLE_HEIGHT; + if (row.thicker) { + // Lower the title slightly. + titleY += Blockly.BlockSvg.INLINE_PADDING_Y; + } + // TODO: Align inline title rows (left/right/centre). + cursorX = this.renderTitles_(input.titleRow, titleX, titleY); + if (input.type != Blockly.DUMMY_INPUT) { + cursorX += input.renderWidth + Blockly.BlockSvg.SEP_SPACE_X; + } + if (input.type == Blockly.INPUT_VALUE) { + inlineSteps.push('M', (cursorX - Blockly.BlockSvg.SEP_SPACE_X) + + ',' + (cursorY + Blockly.BlockSvg.INLINE_PADDING_Y)); + inlineSteps.push('h', Blockly.BlockSvg.TAB_WIDTH - input.renderWidth); + inlineSteps.push(Blockly.BlockSvg.TAB_PATH_DOWN); + inlineSteps.push('v', input.renderHeight - + Blockly.BlockSvg.TAB_HEIGHT); + inlineSteps.push('h', input.renderWidth - Blockly.BlockSvg.TAB_WIDTH); + inlineSteps.push('z'); + if (Blockly.RTL) { + // Highlight right edge, around back of tab, and bottom. + highlightInlineSteps.push('M', + (cursorX - Blockly.BlockSvg.SEP_SPACE_X + + Blockly.BlockSvg.TAB_WIDTH - input.renderWidth - 1) + ',' + + (cursorY + Blockly.BlockSvg.INLINE_PADDING_Y + 1)); + highlightInlineSteps.push( + Blockly.BlockSvg.TAB_PATH_DOWN_HIGHLIGHT_RTL); + highlightInlineSteps.push('v', + input.renderHeight - Blockly.BlockSvg.TAB_HEIGHT + 2); + highlightInlineSteps.push('h', + input.renderWidth - Blockly.BlockSvg.TAB_WIDTH); + } else { + // Highlight right edge, bottom, and glint at bottom of tab. + highlightInlineSteps.push('M', + (cursorX - Blockly.BlockSvg.SEP_SPACE_X + 1) + ',' + + (cursorY + Blockly.BlockSvg.INLINE_PADDING_Y + 1)); + highlightInlineSteps.push('v', input.renderHeight); + highlightInlineSteps.push('h', Blockly.BlockSvg.TAB_WIDTH - + input.renderWidth); + highlightInlineSteps.push('M', + (cursorX - input.renderWidth - Blockly.BlockSvg.SEP_SPACE_X + + 3.8) + ',' + (cursorY + Blockly.BlockSvg.INLINE_PADDING_Y + + Blockly.BlockSvg.TAB_HEIGHT - 0.4)); + highlightInlineSteps.push('l', + (Blockly.BlockSvg.TAB_WIDTH * 0.42) + ',-1.8'); + } + // Create inline input connection. + if (Blockly.RTL) { + connectionX = connectionsXY.x - cursorX - + Blockly.BlockSvg.TAB_WIDTH + Blockly.BlockSvg.SEP_SPACE_X + + input.renderWidth - 1; + } else { + connectionX = connectionsXY.x + cursorX + + Blockly.BlockSvg.TAB_WIDTH - Blockly.BlockSvg.SEP_SPACE_X - + input.renderWidth + 1; + } + connectionY = connectionsXY.y + cursorY + + Blockly.BlockSvg.INLINE_PADDING_Y; + input.connection.moveTo(connectionX, connectionY); + if (input.connection.targetConnection) { + input.connection.tighten_(); + } + } + } + + cursorX = Math.max(cursorX, inputRows.rightEdge); + steps.push('H', cursorX); + highlightSteps.push('H', cursorX + (Blockly.RTL ? -1 : 0)); + steps.push('v', row.height); + if (Blockly.RTL) { + highlightSteps.push('v', row.height - 2); + } + } else if (row.type == Blockly.INPUT_VALUE) { + // External input. + var input = row[0]; + var titleX = cursorX; + var titleY = cursorY + Blockly.BlockSvg.TITLE_HEIGHT; + if (input.align != Blockly.ALIGN_LEFT) { + var titleRightX = inputRows.rightEdge - input.titleWidth - + Blockly.BlockSvg.TAB_WIDTH - 2 * Blockly.BlockSvg.SEP_SPACE_X; + if (input.align == Blockly.ALIGN_RIGHT) { + titleX += titleRightX; + } else if (input.align == Blockly.ALIGN_CENTRE) { + titleX += (titleRightX + titleX) / 2; + } + } + this.renderTitles_(input.titleRow, titleX, titleY); + steps.push(Blockly.BlockSvg.TAB_PATH_DOWN); + steps.push('v', row.height - Blockly.BlockSvg.TAB_HEIGHT); + if (Blockly.RTL) { + // Highlight around back of tab. + highlightSteps.push(Blockly.BlockSvg.TAB_PATH_DOWN_HIGHLIGHT_RTL); + highlightSteps.push('v', row.height - Blockly.BlockSvg.TAB_HEIGHT); + } else { + // Short highlight glint at bottom of tab. + highlightSteps.push('M', (inputRows.rightEdge - 4.2) + ',' + + (cursorY + Blockly.BlockSvg.TAB_HEIGHT - 0.4)); + highlightSteps.push('l', (Blockly.BlockSvg.TAB_WIDTH * 0.42) + + ',-1.8'); + } + // Create external input connection. + connectionX = connectionsXY.x + + (Blockly.RTL ? -inputRows.rightEdge - 1 : inputRows.rightEdge + 1); + connectionY = connectionsXY.y + cursorY; + input.connection.moveTo(connectionX, connectionY); + if (input.connection.targetConnection) { + input.connection.tighten_(); + } + } else if (row.type == Blockly.DUMMY_INPUT) { + // External naked title. + var input = row[0]; + var titleX = cursorX; + var titleY = cursorY + Blockly.BlockSvg.TITLE_HEIGHT; + if (input.align != Blockly.ALIGN_LEFT) { + var titleRightX = inputRows.rightEdge - input.titleWidth - + 2 * Blockly.BlockSvg.SEP_SPACE_X; + if (inputRows.hasValue) { + titleRightX -= Blockly.BlockSvg.TAB_WIDTH; + } + if (input.align == Blockly.ALIGN_RIGHT) { + titleX += titleRightX; + } else if (input.align == Blockly.ALIGN_CENTRE) { + titleX += (titleRightX + titleX) / 2; + } + } + this.renderTitles_(input.titleRow, titleX, titleY); + steps.push('v', row.height); + if (Blockly.RTL) { + highlightSteps.push('v', row.height - 2); + } + } else if (row.type == Blockly.NEXT_STATEMENT) { + // Nested statement. + var input = row[0]; + if (y == 0) { + // If the first input is a statement stack, add a small row on top. + steps.push('v', Blockly.BlockSvg.SEP_SPACE_Y); + if (Blockly.RTL) { + highlightSteps.push('v', Blockly.BlockSvg.SEP_SPACE_Y - 1); + } + cursorY += Blockly.BlockSvg.SEP_SPACE_Y; + } + var titleX = cursorX; + var titleY = cursorY + Blockly.BlockSvg.TITLE_HEIGHT; + if (input.align != Blockly.ALIGN_LEFT) { + var titleRightX = inputRows.statementEdge - input.titleWidth - + 2 * Blockly.BlockSvg.SEP_SPACE_X; + if (input.align == Blockly.ALIGN_RIGHT) { + titleX += titleRightX; + } else if (input.align == Blockly.ALIGN_CENTRE) { + titleX += (titleRightX + titleX) / 2; + } + } + this.renderTitles_(input.titleRow, titleX, titleY); + cursorX = inputRows.statementEdge + Blockly.BlockSvg.NOTCH_WIDTH; + steps.push('H', cursorX); + steps.push(Blockly.BlockSvg.INNER_TOP_LEFT_CORNER); + steps.push('v', row.height - 2 * Blockly.BlockSvg.CORNER_RADIUS); + steps.push(Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER); + steps.push('H', inputRows.rightEdge); + if (Blockly.RTL) { + highlightSteps.push('M', + (cursorX - Blockly.BlockSvg.NOTCH_WIDTH + + Blockly.BlockSvg.DISTANCE_45_OUTSIDE) + + ',' + (cursorY + Blockly.BlockSvg.DISTANCE_45_OUTSIDE)); + highlightSteps.push( + Blockly.BlockSvg.INNER_TOP_LEFT_CORNER_HIGHLIGHT_RTL); + highlightSteps.push('v', + row.height - 2 * Blockly.BlockSvg.CORNER_RADIUS); + highlightSteps.push( + Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER_HIGHLIGHT_RTL); + highlightSteps.push('H', inputRows.rightEdge - 1); + } else { + highlightSteps.push('M', + (cursorX - Blockly.BlockSvg.NOTCH_WIDTH + + Blockly.BlockSvg.DISTANCE_45_OUTSIDE) + ',' + + (cursorY + row.height - Blockly.BlockSvg.DISTANCE_45_OUTSIDE)); + highlightSteps.push( + Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER_HIGHLIGHT_LTR); + highlightSteps.push('H', inputRows.rightEdge); + } + // Create statement connection. + connectionX = connectionsXY.x + (Blockly.RTL ? -cursorX : cursorX); + connectionY = connectionsXY.y + cursorY + 1; + input.connection.moveTo(connectionX, connectionY); + if (input.connection.targetConnection) { + input.connection.tighten_(); + } + if (y == inputRows.length - 1 || + inputRows[y + 1].type == Blockly.NEXT_STATEMENT) { + // If the final input is a statement stack, add a small row underneath. + // Consecutive statement stacks are also separated by a small divider. + steps.push('v', Blockly.BlockSvg.SEP_SPACE_Y); + if (Blockly.RTL) { + highlightSteps.push('v', Blockly.BlockSvg.SEP_SPACE_Y - 1); + } + cursorY += Blockly.BlockSvg.SEP_SPACE_Y; + } + } + cursorY += row.height; + } + if (!inputRows.length) { + cursorY = Blockly.BlockSvg.MIN_BLOCK_Y; + steps.push('V', cursorY); + if (Blockly.RTL) { + highlightSteps.push('V', cursorY - 1); + } + } + return cursorY; +}; + +/** + * Render the bottom edge of the block. + * @param {!Array.} steps Path of block outline. + * @param {!Array.} highlightSteps Path of block highlights. + * @param {!Object} connectionsXY Location of block. + * @param {number} cursorY Height of block. + * @private + */ +Blockly.BlockSvg.prototype.renderDrawBottom_ = function(steps, highlightSteps, + connectionsXY, cursorY) { + if (this.block_.nextConnection) { + steps.push('H', Blockly.BlockSvg.NOTCH_WIDTH + ' ' + + Blockly.BlockSvg.NOTCH_PATH_RIGHT); + // Create next block connection. + var connectionX; + if (Blockly.RTL) { + connectionX = connectionsXY.x - Blockly.BlockSvg.NOTCH_WIDTH; + } else { + connectionX = connectionsXY.x + Blockly.BlockSvg.NOTCH_WIDTH; + } + var connectionY = connectionsXY.y + cursorY + 1; + this.block_.nextConnection.moveTo(connectionX, connectionY); + if (this.block_.nextConnection.targetConnection) { + this.block_.nextConnection.tighten_(); + } + } + + if (Blockly.BROKEN_CONTROL_POINTS) { + /* HACK: + WebKit bug 67298 causes control points to be included in the reported + bounding box. Add 5px control point to the bottom of the path. + */ + steps.push('c 0,5 0,-5 0,0'); + } + // Should the bottom-left corner be rounded or square? + if (this.squareBottomLeftCorner_) { + steps.push('H 0'); + if (!Blockly.RTL) { + highlightSteps.push('M', '1,' + cursorY); + } + } else { + steps.push('H', Blockly.BlockSvg.CORNER_RADIUS); + steps.push('a', Blockly.BlockSvg.CORNER_RADIUS + ',' + + Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,1 -' + + Blockly.BlockSvg.CORNER_RADIUS + ',-' + + Blockly.BlockSvg.CORNER_RADIUS); + if (!Blockly.RTL) { + highlightSteps.push('M', Blockly.BlockSvg.DISTANCE_45_INSIDE + ',' + + (cursorY - Blockly.BlockSvg.DISTANCE_45_INSIDE)); + highlightSteps.push('A', (Blockly.BlockSvg.CORNER_RADIUS - 1) + ',' + + (Blockly.BlockSvg.CORNER_RADIUS - 1) + ' 0 0,1 ' + + '1,' + (cursorY - Blockly.BlockSvg.CORNER_RADIUS)); + } + } +}; + +/** + * Render the left edge of the block. + * @param {!Array.} steps Path of block outline. + * @param {!Array.} highlightSteps Path of block highlights. + * @param {!Object} connectionsXY Location of block. + * @param {number} cursorY Height of block. + * @private + */ +Blockly.BlockSvg.prototype.renderDrawLeft_ = function(steps, highlightSteps, + connectionsXY, cursorY) { + if (this.block_.outputConnection) { + // Create output connection. + this.block_.outputConnection.moveTo(connectionsXY.x, connectionsXY.y); + // This connection will be tightened when the parent renders. + steps.push('V', Blockly.BlockSvg.TAB_HEIGHT); + steps.push('c 0,-10 -' + Blockly.BlockSvg.TAB_WIDTH + ',8 -' + + Blockly.BlockSvg.TAB_WIDTH + ',-7.5 s ' + Blockly.BlockSvg.TAB_WIDTH + + ',2.5 ' + Blockly.BlockSvg.TAB_WIDTH + ',-7.5'); + if (Blockly.RTL) { + highlightSteps.push('M', (Blockly.BlockSvg.TAB_WIDTH * -0.3) + ',8.9'); + highlightSteps.push('l', (Blockly.BlockSvg.TAB_WIDTH * -0.45) + ',-2.1'); + } else { + highlightSteps.push('V', Blockly.BlockSvg.TAB_HEIGHT - 1); + highlightSteps.push('m', (Blockly.BlockSvg.TAB_WIDTH * -0.92) + + ',-1 q ' + (Blockly.BlockSvg.TAB_WIDTH * -0.19) + + ',-5.5 0,-11'); + highlightSteps.push('m', (Blockly.BlockSvg.TAB_WIDTH * 0.92) + + ',1 V 1 H 2'); + } + } else if (!Blockly.RTL) { + if (this.squareTopLeftCorner_) { + highlightSteps.push('V', 1); + } else { + highlightSteps.push('V', Blockly.BlockSvg.CORNER_RADIUS); + } + } + steps.push('z'); +}; diff --git a/core/blockly.js b/core/blockly.js new file mode 100644 index 000000000..18bf56117 --- /dev/null +++ b/core/blockly.js @@ -0,0 +1,698 @@ +/** + * Visual Blocks Editor + * + * Copyright 2011 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Core JavaScript library for Blockly. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +// Top level object for Blockly. +goog.provide('Blockly'); + +// Blockly core dependencies. +goog.require('Blockly.Block'); +goog.require('Blockly.Connection'); +goog.require('Blockly.FieldAngle'); +goog.require('Blockly.FieldCheckbox'); +goog.require('Blockly.FieldColour'); +goog.require('Blockly.FieldDropdown'); +goog.require('Blockly.FieldImage'); +goog.require('Blockly.FieldTextInput'); +goog.require('Blockly.FieldVariable'); +goog.require('Blockly.Generator'); +goog.require('Blockly.Msg'); +goog.require('Blockly.Procedures'); +goog.require('Blockly.Toolbox'); +goog.require('Blockly.WidgetDiv'); +goog.require('Blockly.Workspace'); +goog.require('Blockly.inject'); +goog.require('Blockly.utils'); + +// Closure dependencies. +goog.require('goog.dom'); +goog.require('goog.color'); +goog.require('goog.events'); +goog.require('goog.string'); +goog.require('goog.ui.ColorPicker'); +goog.require('goog.ui.tree.TreeControl'); +goog.require('goog.userAgent'); + + +/** + * Path to Blockly's directory. Can be relative, absolute, or remote. + * Used for loading additional resources. + */ +Blockly.pathToBlockly = './'; + +/** + * Required name space for SVG elements. + * @const + */ +Blockly.SVG_NS = 'http://www.w3.org/2000/svg'; +/** + * Required name space for HTML elements. + * @const + */ +Blockly.HTML_NS = 'http://www.w3.org/1999/xhtml'; + +/** + * The richness of block colours, regardless of the hue. + * Must be in the range of 0 (inclusive) to 1 (exclusive). + */ +Blockly.HSV_SATURATION = 0.45; +/** + * The intensity of block colours, regardless of the hue. + * Must be in the range of 0 (inclusive) to 1 (exclusive). + */ +Blockly.HSV_VALUE = 0.65; + +/** + * Convert a hue (HSV model) into an RGB hex triplet. + * @param {number} hue Hue on a colour wheel (0-360). + * @return {string} RGB code, e.g. '#5ba65b'. + */ +Blockly.makeColour = function(hue) { + return goog.color.hsvToHex(hue, Blockly.HSV_SATURATION, + Blockly.HSV_VALUE * 256); +}; + +/** + * ENUM for a right-facing value input. E.g. 'test' or 'return'. + * @const + */ +Blockly.INPUT_VALUE = 1; +/** + * ENUM for a left-facing value output. E.g. 'call random'. + * @const + */ +Blockly.OUTPUT_VALUE = 2; +/** + * ENUM for a down-facing block stack. E.g. 'then-do' or 'else-do'. + * @const + */ +Blockly.NEXT_STATEMENT = 3; +/** + * ENUM for an up-facing block stack. E.g. 'close screen'. + * @const + */ +Blockly.PREVIOUS_STATEMENT = 4; +/** + * ENUM for an dummy input. Used to add title(s) with no input. + * @const + */ +Blockly.DUMMY_INPUT = 5; + +/** + * ENUM for left alignment. + * @const + */ +Blockly.ALIGN_LEFT = -1; +/** + * ENUM for centre alignment. + * @const + */ +Blockly.ALIGN_CENTRE = 0; +/** + * ENUM for right alignment. + * @const + */ +Blockly.ALIGN_RIGHT = 1; + +/** + * Lookup table for determining the opposite type of a connection. + * @const + */ +Blockly.OPPOSITE_TYPE = []; +Blockly.OPPOSITE_TYPE[Blockly.INPUT_VALUE] = Blockly.OUTPUT_VALUE; +Blockly.OPPOSITE_TYPE[Blockly.OUTPUT_VALUE] = Blockly.INPUT_VALUE; +Blockly.OPPOSITE_TYPE[Blockly.NEXT_STATEMENT] = Blockly.PREVIOUS_STATEMENT; +Blockly.OPPOSITE_TYPE[Blockly.PREVIOUS_STATEMENT] = Blockly.NEXT_STATEMENT; + +/** + * Database of pre-loaded sounds. + * @private + * @const + */ +Blockly.SOUNDS_ = Object.create(null); + +/** + * Currently selected block. + * @type {Blockly.Block} + */ +Blockly.selected = null; + +/** + * Is Blockly in a read-only, non-editable mode? + * Note that this property may only be set before init is called. + * It can't be used to dynamically toggle editability on and off. + */ +Blockly.readOnly = false; + +/** + * Currently highlighted connection (during a drag). + * @type {Blockly.Connection} + * @private + */ +Blockly.highlightedConnection_ = null; + +/** + * Connection on dragged block that matches the highlighted connection. + * @type {Blockly.Connection} + * @private + */ +Blockly.localConnection_ = null; + +/** + * Number of pixels the mouse must move before a drag starts. + * @const + */ +Blockly.DRAG_RADIUS = 5; + +/** + * Maximum misalignment between connections for them to snap together. + * @const + */ +Blockly.SNAP_RADIUS = 15; + +/** + * Delay in ms between trigger and bumping unconnected block out of alignment. + * @const + */ +Blockly.BUMP_DELAY = 250; + +/** + * Number of characters to truncate a collapsed block to. + * @const + */ +Blockly.COLLAPSE_CHARS = 30; + +/** + * The main workspace (defined by inject.js). + * @type {Blockly.Workspace} + */ +Blockly.mainWorkspace = null; + +/** + * Contents of the local clipboard. + * @type {Element} + * @private + */ +Blockly.clipboard_ = null; + +/** + * Returns the dimensions of the current SVG image. + * @return {!Object} Contains width, height, top and left properties. + */ +Blockly.svgSize = function() { + return {width: Blockly.svg.cachedWidth_, + height: Blockly.svg.cachedHeight_}; +}; + +/** + * Size the SVG image to completely fill its container. Record both + * the height/width and the absolute position of the SVG image. + */ +Blockly.svgResize = function() { + var svg = Blockly.svg; + var div = svg.parentNode; + var width = div.offsetWidth; + var height = div.offsetHeight; + if (svg.cachedWidth_ != width) { + svg.setAttribute('width', width + 'px'); + svg.cachedWidth_ = width; + } + if (svg.cachedHeight_ != height) { + svg.setAttribute('height', height + 'px'); + svg.cachedHeight_ = height; + } + // Update the scrollbars (if they exist). + if (Blockly.mainWorkspace.scrollbar) { + Blockly.mainWorkspace.scrollbar.resize(); + } +}; + +/** + * Handle a mouse-down on SVG drawing surface. + * @param {!Event} e Mouse down event. + * @private + */ +Blockly.onMouseDown_ = function(e) { + Blockly.terminateDrag_(); // In case mouse-up event was lost. + Blockly.hideChaff(); + var isTargetSvg = e.target && e.target.nodeName && + e.target.nodeName.toLowerCase() == 'svg'; + if (!Blockly.readOnly && Blockly.selected && isTargetSvg) { + // Clicking on the document clears the selection. + Blockly.selected.unselect(); + } + if (Blockly.isRightButton(e)) { + // Right-click. + if (Blockly.ContextMenu) { + Blockly.showContextMenu_(Blockly.mouseToSvg(e)); + } + } else if ((Blockly.readOnly || isTargetSvg) && + Blockly.mainWorkspace.scrollbar) { + // If the workspace is editable, only allow dragging when gripping empty + // space. Otherwise, allow dragging when gripping anywhere. + Blockly.mainWorkspace.dragMode = true; + // Record the current mouse position. + Blockly.mainWorkspace.startDragMouseX = e.clientX; + Blockly.mainWorkspace.startDragMouseY = e.clientY; + Blockly.mainWorkspace.startDragMetrics = + Blockly.mainWorkspace.getMetrics(); + Blockly.mainWorkspace.startScrollX = Blockly.mainWorkspace.scrollX; + Blockly.mainWorkspace.startScrollY = Blockly.mainWorkspace.scrollY; + } +}; + +/** + * Handle a mouse-up on SVG drawing surface. + * @param {!Event} e Mouse up event. + * @private + */ +Blockly.onMouseUp_ = function(e) { + Blockly.setCursorHand_(false); + Blockly.mainWorkspace.dragMode = false; +}; + +/** + * Handle a mouse-move on SVG drawing surface. + * @param {!Event} e Mouse move event. + * @private + */ +Blockly.onMouseMove_ = function(e) { + if (Blockly.mainWorkspace.dragMode) { + Blockly.removeAllRanges(); + var dx = e.clientX - Blockly.mainWorkspace.startDragMouseX; + var dy = e.clientY - Blockly.mainWorkspace.startDragMouseY; + var metrics = Blockly.mainWorkspace.startDragMetrics; + var x = Blockly.mainWorkspace.startScrollX + dx; + var y = Blockly.mainWorkspace.startScrollY + dy; + x = Math.min(x, -metrics.contentLeft); + y = Math.min(y, -metrics.contentTop); + x = Math.max(x, metrics.viewWidth - metrics.contentLeft - + metrics.contentWidth); + y = Math.max(y, metrics.viewHeight - metrics.contentTop - + metrics.contentHeight); + + // Move the scrollbars and the page will scroll automatically. + Blockly.mainWorkspace.scrollbar.set(-x - metrics.contentLeft, + -y - metrics.contentTop); + } +}; + +/** + * Handle a key-down on SVG drawing surface. + * @param {!Event} e Key down event. + * @private + */ +Blockly.onKeyDown_ = function(e) { + if (Blockly.isTargetInput_(e)) { + // When focused on an HTML text input widget, don't trap any keys. + return; + } + // TODO: Add keyboard support for cursoring around the context menu. + if (e.keyCode == 27) { + // Pressing esc closes the context menu. + Blockly.hideChaff(); + } else if (e.keyCode == 8 || e.keyCode == 46) { + // Delete or backspace. + try { + if (Blockly.selected && Blockly.selected.isDeletable()) { + Blockly.hideChaff(); + Blockly.selected.dispose(true, true); + } + } finally { + // Stop the browser from going back to the previous page. + // Use a finally so that any error in delete code above doesn't disappear + // from the console when the page rolls back. + e.preventDefault(); + } + } else if (e.altKey || e.ctrlKey || e.metaKey) { + if (Blockly.selected && Blockly.selected.isDeletable() && + Blockly.selected.workspace == Blockly.mainWorkspace) { + Blockly.hideChaff(); + if (e.keyCode == 67) { + // 'c' for copy. + Blockly.copy_(Blockly.selected); + } else if (e.keyCode == 88) { + // 'x' for cut. + Blockly.copy_(Blockly.selected); + Blockly.selected.dispose(true, true); + } + } + if (e.keyCode == 86) { + // 'v' for paste. + if (Blockly.clipboard_) { + Blockly.mainWorkspace.paste(Blockly.clipboard_); + } + } + } +}; + +/** + * Stop binding to the global mouseup and mousemove events. + * @private + */ +Blockly.terminateDrag_ = function() { + Blockly.Block.terminateDrag_(); + Blockly.Flyout.terminateDrag_(); +}; + +/** + * Copy a block onto the local clipboard. + * @param {!Blockly.Block} block Block to be copied. + * @private + */ +Blockly.copy_ = function(block) { + var xmlBlock = Blockly.Xml.blockToDom_(block); + Blockly.Xml.deleteNext(xmlBlock); + // Encode start position in XML. + var xy = block.getRelativeToSurfaceXY(); + xmlBlock.setAttribute('x', Blockly.RTL ? -xy.x : xy.x); + xmlBlock.setAttribute('y', xy.y); + Blockly.clipboard_ = xmlBlock; +}; + +/** + * Show the context menu for the workspace. + * @param {!Object} xy Coordinates of mouse click, contains x and y properties. + * @private + */ +Blockly.showContextMenu_ = function(xy) { + if (Blockly.readOnly) { + return; + } + var options = []; + + if (Blockly.collapse) { + var hasCollapsedBlocks = false; + var hasExpandedBlocks = false; + var topBlocks = Blockly.mainWorkspace.getTopBlocks(false); + for (var i = 0; i < topBlocks.length; i++) { + if (topBlocks[i].isCollapsed()) { + hasCollapsedBlocks = true; + } else { + hasExpandedBlocks = true; + } + } + + // Option to collapse top blocks. + var collapseOption = {enabled: hasExpandedBlocks}; + collapseOption.text = Blockly.Msg.COLLAPSE_ALL; + collapseOption.callback = function() { + for (var i = 0; i < topBlocks.length; i++) { + topBlocks[i].setCollapsed(true); + } + }; + options.push(collapseOption); + + // Option to expand top blocks. + var expandOption = {enabled: hasCollapsedBlocks}; + expandOption.text = Blockly.Msg.EXPAND_ALL; + expandOption.callback = function() { + for (var i = 0; i < topBlocks.length; i++) { + topBlocks[i].setCollapsed(false); + } + }; + options.push(expandOption); + } + + // Option to get help. + var helpOption = {enabled: false}; + helpOption.text = Blockly.Msg.HELP; + helpOption.callback = function() {}; + options.push(helpOption); + + Blockly.ContextMenu.show(xy, options); +}; + +/** + * Cancel the native context menu, unless the focus is on an HTML input widget. + * @param {!Event} e Mouse down event. + * @private + */ +Blockly.onContextMenu_ = function(e) { + if (!Blockly.isTargetInput_(e) && Blockly.ContextMenu) { + // When focused on an HTML text input widget, don't cancel the context menu. + e.preventDefault(); + } +}; + +/** + * Close tooltips, context menus, dropdown selections, etc. + * @param {boolean=} opt_allowToolbox If true, don't close the toolbox. + */ +Blockly.hideChaff = function(opt_allowToolbox) { + Blockly.Tooltip && Blockly.Tooltip.hide(); + Blockly.ContextMenu && Blockly.ContextMenu.hide(); + Blockly.FieldDropdown && Blockly.FieldDropdown.hide(); + Blockly.WidgetDiv.hide(); + if (!opt_allowToolbox && + Blockly.Toolbox.flyout_ && Blockly.Toolbox.flyout_.autoClose) { + Blockly.Toolbox.clearSelection(); + } +}; + +/** + * Deselect any selections on the webpage. + * Chrome will select text outside the SVG when double-clicking. + * Deselect this text, so that it doesn't mess up any subsequent drag. + */ +Blockly.removeAllRanges = function() { + if (window.getSelection) { // W3 + var sel = window.getSelection(); + if (sel && sel.removeAllRanges) { + sel.removeAllRanges(); + window.setTimeout(function() { + window.getSelection().removeAllRanges(); + }, 0); + } + } +}; + +/** + * Is this event targeting a text input widget? + * @param {!Event} e An event. + * @return {boolean} True if text input. + * @private + */ +Blockly.isTargetInput_ = function(e) { + return e.target.type == 'textarea' || e.target.type == 'text'; +}; + +/** + * Load an audio file. Cache it, ready for instantaneous playing. + * @param {!Array.} filenames List of file types in decreasing order of + * preference (i.e. increasing size). E.g. ['media/go.mp3', 'media/go.wav'] + * Filenames include path from Blockly's root. File extensions matter. + * @param {string} name Name of sound. + * @private + */ +Blockly.loadAudio_ = function(filenames, name) { + if (!window['Audio'] || !filenames.length) { + // No browser support for Audio. + return; + } + var sound; + var audioTest = new window['Audio'](); + for (var i = 0; i < filenames.length; i++) { + var filename = filenames[i]; + var ext = filename.match(/\.(\w+)$/); + if (ext && audioTest.canPlayType('audio/' + ext[1])) { + // Found an audio format we can play. + sound = new window['Audio'](Blockly.pathToBlockly + filename); + break; + } + } + // To force the browser to load the sound, play it, but at nearly zero volume. + if (sound && sound.play) { + sound.volume = 0.01; + sound.play(); + Blockly.SOUNDS_[name] = sound; + } +}; + +/** + * Play an audio file at specified value. If volume is not specified, + * use full volume (1). + * @param {string} name Name of sound. + * @param {?number} opt_volume Volume of sound (0-1). + */ +Blockly.playAudio = function(name, opt_volume) { + var sound = Blockly.SOUNDS_[name]; + if (sound) { + var mySound; + var ie9 = goog.userAgent.DOCUMENT_MODE && + goog.userAgent.DOCUMENT_MODE === 9; + if (ie9 || goog.userAgent.IPAD || goog.userAgent.ANDROID) { + // Creating a new audio node causes lag in IE9, Android and iPad. Android + // and IE9 refetch the file from the server, iPad uses a singleton audio + // node which must be deleted and recreated for each new audio tag. + mySound = sound; + } else { + mySound = sound.cloneNode(); + } + mySound.volume = (opt_volume === undefined ? 1 : opt_volume); + mySound.play(); + } +}; + +/** + * Set the mouse cursor to be either a closed hand or the default. + * @param {boolean} closed True for closed hand. + * @private + */ +Blockly.setCursorHand_ = function(closed) { + if (Blockly.readOnly) { + return; + } + /* Hotspot coordinates are baked into the CUR file, but they are still + required due to a Chrome bug. + http://code.google.com/p/chromium/issues/detail?id=1446 */ + var cursor = ''; + if (closed) { + cursor = 'url(' + Blockly.pathToBlockly + 'media/handclosed.cur) 7 3, auto'; + } + if (Blockly.selected) { + Blockly.selected.getSvgRoot().style.cursor = cursor; + } + // Set cursor on the SVG surface as well as block so that rapid movements + // don't result in cursor changing to an arrow momentarily. + Blockly.svg.style.cursor = cursor; +}; + +/** + * Return an object with all the metrics required to size scrollbars for the + * main workspace. The following properties are computed: + * .viewHeight: Height of the visible rectangle, + * .viewWidth: Width of the visible rectangle, + * .contentHeight: Height of the contents, + * .contentWidth: Width of the content, + * .viewTop: Offset of top edge of visible rectangle from parent, + * .viewLeft: Offset of left edge of visible rectangle from parent, + * .contentTop: Offset of the top-most content from the y=0 coordinate, + * .contentLeft: Offset of the left-most content from the x=0 coordinate. + * .absoluteTop: Top-edge of view. + * .absoluteLeft: Left-edge of view. + * @return {Object} Contains size and position metrics of main workspace. + * @private + */ +Blockly.getMainWorkspaceMetrics_ = function() { + var svgSize = Blockly.svgSize(); + svgSize.width -= Blockly.Toolbox.width; // Zero if no Toolbox. + var viewWidth = svgSize.width - Blockly.Scrollbar.scrollbarThickness; + var viewHeight = svgSize.height - Blockly.Scrollbar.scrollbarThickness; + try { + var blockBox = Blockly.mainWorkspace.getCanvas().getBBox(); + } catch (e) { + // Firefox has trouble with hidden elements (Bug 528969). + return null; + } + if (Blockly.mainWorkspace.scrollbar) { + // Add a border around the content that is at least half a screenful wide. + var leftEdge = Math.min(blockBox.x - viewWidth / 2, + blockBox.x + blockBox.width - viewWidth); + var rightEdge = Math.max(blockBox.x + blockBox.width + viewWidth / 2, + blockBox.x + viewWidth); + var topEdge = Math.min(blockBox.y - viewHeight / 2, + blockBox.y + blockBox.height - viewHeight); + var bottomEdge = Math.max(blockBox.y + blockBox.height + viewHeight / 2, + blockBox.y + viewHeight); + } else { + var leftEdge = blockBox.x; + var rightEdge = leftEdge + blockBox.width; + var topEdge = blockBox.y; + var bottomEdge = topEdge + blockBox.height; + } + var absoluteLeft = Blockly.RTL ? 0 : Blockly.Toolbox.width; + return { + viewHeight: svgSize.height, + viewWidth: svgSize.width, + contentHeight: bottomEdge - topEdge, + contentWidth: rightEdge - leftEdge, + viewTop: -Blockly.mainWorkspace.scrollY, + viewLeft: -Blockly.mainWorkspace.scrollX, + contentTop: topEdge, + contentLeft: leftEdge, + absoluteTop: 0, + absoluteLeft: absoluteLeft + }; +}; + +/** + * Sets the X/Y translations of the main workspace to match the scrollbars. + * @param {!Object} xyRatio Contains an x and/or y property which is a float + * between 0 and 1 specifying the degree of scrolling. + * @private + */ +Blockly.setMainWorkspaceMetrics_ = function(xyRatio) { + if (!Blockly.mainWorkspace.scrollbar) { + throw 'Attempt to set main workspace scroll without scrollbars.'; + } + var metrics = Blockly.getMainWorkspaceMetrics_(); + if (goog.isNumber(xyRatio.x)) { + Blockly.mainWorkspace.scrollX = -metrics.contentWidth * xyRatio.x - + metrics.contentLeft; + } + if (goog.isNumber(xyRatio.y)) { + Blockly.mainWorkspace.scrollY = -metrics.contentHeight * xyRatio.y - + metrics.contentTop; + } + var translation = 'translate(' + + (Blockly.mainWorkspace.scrollX + metrics.absoluteLeft) + ',' + + (Blockly.mainWorkspace.scrollY + metrics.absoluteTop) + ')'; + Blockly.mainWorkspace.getCanvas().setAttribute('transform', translation); + Blockly.mainWorkspace.getBubbleCanvas().setAttribute('transform', + translation); +}; + +/** + * When something in Blockly's workspace changes, call a function. + * @param {!Function} func Function to call. + * @return {!Array.} Opaque data that can be passed to + * removeChangeListener. + */ +Blockly.addChangeListener = function(func) { + return Blockly.bindEvent_(Blockly.mainWorkspace.getCanvas(), + 'blocklyWorkspaceChange', null, func); +}; + +/** + * Stop listening for Blockly's workspace changes. + * @param {!Array.} bindData Opaque data from addChangeListener. + */ +Blockly.removeChangeListener = function(bindData) { + Blockly.unbindEvent_(bindData); +}; + +/** + * Returns the main workspace. + * @return {!Blockly.Workspace} The main workspace. + */ +Blockly.getMainWorkspace = function() { + return Blockly.mainWorkspace; +}; + +// Export symbols that would otherwise be renamed by Closure compiler. +window['Blockly'] = Blockly; +Blockly['getMainWorkspace'] = Blockly.getMainWorkspace; +Blockly['addChangeListener'] = Blockly.addChangeListener; +Blockly['removeChangeListener'] = Blockly.removeChangeListener; diff --git a/core/blocks.js b/core/blocks.js new file mode 100644 index 000000000..2c27199f1 --- /dev/null +++ b/core/blocks.js @@ -0,0 +1,30 @@ +/** + * Visual Blocks Editor + * + * Copyright 2013 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Core JavaScript library for Blockly. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +/** + * Name space for the Blocks singleton. + * Blocks gets populated in the blocks files. + */ +goog.provide('Blockly.Blocks'); diff --git a/core/bubble.js b/core/bubble.js new file mode 100644 index 000000000..74059b3ba --- /dev/null +++ b/core/bubble.js @@ -0,0 +1,569 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Object representing a UI bubble. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Bubble'); + +goog.require('Blockly.Workspace'); + + +/** + * Class for UI bubble. + * @param {!Blockly.Workspace} workspace The workspace on which to draw the + * bubble. + * @param {!Element} content SVG content for the bubble. + * @param {Element} shape SVG element to avoid eclipsing. + * @param {number} anchorX Absolute horizontal position of bubbles anchor point. + * @param {number} anchorY Absolute vertical position of bubbles anchor point. + * @param {?number} bubbleWidth Width of bubble, or null if not resizable. + * @param {?number} bubbleHeight Height of bubble, or null if not resizable. + * @constructor + */ +Blockly.Bubble = function(workspace, content, shape, + anchorX, anchorY, + bubbleWidth, bubbleHeight) { + var angle = Blockly.Bubble.ARROW_ANGLE; + if (Blockly.RTL) { + angle = -angle; + } + this.arrow_radians_ = angle / 360 * Math.PI * 2; + + this.workspace_ = workspace; + this.content_ = content; + this.shape_ = shape; + var canvas = workspace.getBubbleCanvas(); + canvas.appendChild(this.createDom_(content, !!(bubbleWidth && bubbleHeight))); + + this.setAnchorLocation(anchorX, anchorY); + if (!bubbleWidth || !bubbleHeight) { + var bBox = /** @type {SVGLocatable} */ (this.content_).getBBox(); + bubbleWidth = bBox.width + 2 * Blockly.Bubble.BORDER_WIDTH; + bubbleHeight = bBox.height + 2 * Blockly.Bubble.BORDER_WIDTH; + } + this.setBubbleSize(bubbleWidth, bubbleHeight); + + // Render the bubble. + this.positionBubble_(); + this.renderArrow_(); + this.rendered_ = true; + + if (!Blockly.readOnly) { + Blockly.bindEvent_(this.bubbleBack_, 'mousedown', this, + this.bubbleMouseDown_); + if (this.resizeGroup_) { + Blockly.bindEvent_(this.resizeGroup_, 'mousedown', this, + this.resizeMouseDown_); + } + } +}; + +/** + * Width of the border around the bubble. + */ +Blockly.Bubble.BORDER_WIDTH = 6; + +/** + * Determines the thickness of the base of the arrow in relation to the size + * of the bubble. Higher numbers result in thinner arrows. + */ +Blockly.Bubble.ARROW_THICKNESS = 10; + +/** + * The number of degrees that the arrow bends counter-clockwise. + */ +Blockly.Bubble.ARROW_ANGLE = 20; + +/** + * The sharpness of the arrow's bend. Higher numbers result in smoother arrows. + */ +Blockly.Bubble.ARROW_BEND = 4; + +/** + * Distance between arrow point and anchor point. + */ +Blockly.Bubble.ANCHOR_RADIUS = 8; + +/** + * Wrapper function called when a mouseUp occurs during a drag operation. + * @type {Array.} + * @private + */ +Blockly.Bubble.onMouseUpWrapper_ = null; + +/** + * Wrapper function called when a mouseMove occurs during a drag operation. + * @type {Array.} + * @private + */ +Blockly.Bubble.onMouseMoveWrapper_ = null; + +/** + * Stop binding to the global mouseup and mousemove events. + * @private + */ +Blockly.Bubble.unbindDragEvents_ = function() { + if (Blockly.Bubble.onMouseUpWrapper_) { + Blockly.unbindEvent_(Blockly.Bubble.onMouseUpWrapper_); + Blockly.Bubble.onMouseUpWrapper_ = null; + } + if (Blockly.Bubble.onMouseMoveWrapper_) { + Blockly.unbindEvent_(Blockly.Bubble.onMouseMoveWrapper_); + Blockly.Bubble.onMouseMoveWrapper_ = null; + } +}; + +/** + * Flag to stop incremental rendering during construction. + * @private + */ +Blockly.Bubble.prototype.rendered_ = false; + +/** + * Absolute X coordinate of anchor point. + * @private + */ +Blockly.Bubble.prototype.anchorX_ = 0; + +/** + * Absolute Y coordinate of anchor point. + * @private + */ +Blockly.Bubble.prototype.anchorY_ = 0; + +/** + * Relative X coordinate of bubble with respect to the anchor's centre. + * In RTL mode the initial value is negated. + * @private + */ +Blockly.Bubble.prototype.relativeLeft_ = 0; + +/** + * Relative Y coordinate of bubble with respect to the anchor's centre. + * @private + */ +Blockly.Bubble.prototype.relativeTop_ = 0; + +/** + * Width of bubble. + * @private + */ +Blockly.Bubble.prototype.width_ = 0; + +/** + * Height of bubble. + * @private + */ +Blockly.Bubble.prototype.height_ = 0; + +/** + * Automatically position and reposition the bubble. + * @private + */ +Blockly.Bubble.prototype.autoLayout_ = true; + +/** + * Create the bubble's DOM. + * @param {!Element} content SVG content for the bubble. + * @param {boolean} hasResize Add diagonal resize gripper if true. + * @return {!Element} The bubble's SVG group. + * @private + */ +Blockly.Bubble.prototype.createDom_ = function(content, hasResize) { + /* Create the bubble. Here's the markup that will be generated: + + + + + + + + + + + [...content goes here...] + + */ + this.bubbleGroup_ = Blockly.createSvgElement('g', {}, null); + var bubbleEmboss = Blockly.createSvgElement('g', + {'filter': 'url(#blocklyEmboss)'}, this.bubbleGroup_); + this.bubbleArrow_ = Blockly.createSvgElement('path', {}, bubbleEmboss); + this.bubbleBack_ = Blockly.createSvgElement('rect', + {'class': 'blocklyDraggable', 'x': 0, 'y': 0, + 'rx': Blockly.Bubble.BORDER_WIDTH, 'ry': Blockly.Bubble.BORDER_WIDTH}, + bubbleEmboss); + if (hasResize) { + this.resizeGroup_ = Blockly.createSvgElement('g', + {'class': Blockly.RTL ? 'blocklyResizeSW' : 'blocklyResizeSE'}, + this.bubbleGroup_); + var resizeSize = 2 * Blockly.Bubble.BORDER_WIDTH; + Blockly.createSvgElement('polygon', + {'points': '0,x x,x x,0'.replace(/x/g, resizeSize.toString())}, + this.resizeGroup_); + Blockly.createSvgElement('line', + {'class': 'blocklyResizeLine', + 'x1': resizeSize / 3, 'y1': resizeSize - 1, + 'x2': resizeSize - 1, 'y2': resizeSize / 3}, this.resizeGroup_); + Blockly.createSvgElement('line', + {'class': 'blocklyResizeLine', + 'x1': resizeSize * 2 / 3, 'y1': resizeSize - 1, + 'x2': resizeSize - 1, 'y2': resizeSize * 2 / 3}, this.resizeGroup_); + } else { + this.resizeGroup_ = null; + } + this.bubbleGroup_.appendChild(content); + return this.bubbleGroup_; +}; + +/** + * Handle a mouse-down on bubble's border. + * @param {!Event} e Mouse down event. + * @private + */ +Blockly.Bubble.prototype.bubbleMouseDown_ = function(e) { + this.promote_(); + Blockly.Bubble.unbindDragEvents_(); + if (Blockly.isRightButton(e)) { + // Right-click. + return; + } else if (Blockly.isTargetInput_(e)) { + // When focused on an HTML text input widget, don't trap any events. + return; + } + // Left-click (or middle click) + Blockly.setCursorHand_(true); + // Record the starting offset between the current location and the mouse. + if (Blockly.RTL) { + this.dragDeltaX = this.relativeLeft_ + e.clientX; + } else { + this.dragDeltaX = this.relativeLeft_ - e.clientX; + } + this.dragDeltaY = this.relativeTop_ - e.clientY; + + Blockly.Bubble.onMouseUpWrapper_ = Blockly.bindEvent_(document, + 'mouseup', this, Blockly.Bubble.unbindDragEvents_); + Blockly.Bubble.onMouseMoveWrapper_ = Blockly.bindEvent_(document, + 'mousemove', this, this.bubbleMouseMove_); + Blockly.hideChaff(); + // This event has been handled. No need to bubble up to the document. + e.stopPropagation(); +}; + +/** + * Drag this bubble to follow the mouse. + * @param {!Event} e Mouse move event. + * @private + */ +Blockly.Bubble.prototype.bubbleMouseMove_ = function(e) { + this.autoLayout_ = false; + if (Blockly.RTL) { + this.relativeLeft_ = this.dragDeltaX - e.clientX; + } else { + this.relativeLeft_ = this.dragDeltaX + e.clientX; + } + this.relativeTop_ = this.dragDeltaY + e.clientY; + this.positionBubble_(); + this.renderArrow_(); +}; + +/** + * Handle a mouse-down on bubble's resize corner. + * @param {!Event} e Mouse down event. + * @private + */ +Blockly.Bubble.prototype.resizeMouseDown_ = function(e) { + this.promote_(); + Blockly.Bubble.unbindDragEvents_(); + if (Blockly.isRightButton(e)) { + // Right-click. + return; + } + // Left-click (or middle click) + Blockly.setCursorHand_(true); + // Record the starting offset between the current location and the mouse. + if (Blockly.RTL) { + this.resizeDeltaWidth = this.width_ + e.clientX; + } else { + this.resizeDeltaWidth = this.width_ - e.clientX; + } + this.resizeDeltaHeight = this.height_ - e.clientY; + + Blockly.Bubble.onMouseUpWrapper_ = Blockly.bindEvent_(document, + 'mouseup', this, Blockly.Bubble.unbindDragEvents_); + Blockly.Bubble.onMouseMoveWrapper_ = Blockly.bindEvent_(document, + 'mousemove', this, this.resizeMouseMove_); + Blockly.hideChaff(); + // This event has been handled. No need to bubble up to the document. + e.stopPropagation(); +}; + +/** + * Resize this bubble to follow the mouse. + * @param {!Event} e Mouse move event. + * @private + */ +Blockly.Bubble.prototype.resizeMouseMove_ = function(e) { + this.autoLayout_ = false; + var w = this.resizeDeltaWidth; + var h = this.resizeDeltaHeight + e.clientY; + if (Blockly.RTL) { + // RTL drags the bottom-left corner. + w -= e.clientX; + } else { + // LTR drags the bottom-right corner. + w += e.clientX; + } + this.setBubbleSize(w, h); + if (Blockly.RTL) { + // RTL requires the bubble to move its left edge. + this.positionBubble_(); + } +}; + +/** + * Register a function as a callback event for when the bubble is resized. + * @param {Object} thisObject The value of 'this' in the callback. + * @param {!Function} callback The function to call on resize. + */ +Blockly.Bubble.prototype.registerResizeEvent = function(thisObject, callback) { + Blockly.bindEvent_(this.bubbleGroup_, 'resize', thisObject, callback); +}; + +/** + * Move this bubble to the top of the stack. + * @private + */ +Blockly.Bubble.prototype.promote_ = function() { + var svgGroup = this.bubbleGroup_.parentNode; + svgGroup.appendChild(this.bubbleGroup_); +}; + +/** + * Notification that the anchor has moved. + * Update the arrow and bubble accordingly. + * @param {number} x Absolute horizontal location. + * @param {number} y Absolute vertical location. + */ +Blockly.Bubble.prototype.setAnchorLocation = function(x, y) { + this.anchorX_ = x; + this.anchorY_ = y; + if (this.rendered_) { + this.positionBubble_(); + } +}; + +/** + * Position the bubble so that it does not fall offscreen. + * @private + */ +Blockly.Bubble.prototype.layoutBubble_ = function() { + // Compute the preferred bubble location. + var relativeLeft = -this.width_ / 4; + var relativeTop = -this.height_ - Blockly.BlockSvg.MIN_BLOCK_Y; + // Prevent the bubble from being offscreen. + if (this.workspace_.scrollbar) { + // Fetch the workspace's metrics, if they exist. + var metrics = this.workspace_.getMetrics(); + if (this.anchorX_ + relativeLeft < + Blockly.BlockSvg.SEP_SPACE_X + metrics.viewLeft) { + // Slide the bubble right until it is onscreen. + relativeLeft = Blockly.BlockSvg.SEP_SPACE_X + metrics.viewLeft - + this.anchorX_; + } else if (metrics.viewLeft + metrics.viewWidth < + this.anchorX_ + relativeLeft + this.width_ + + Blockly.BlockSvg.SEP_SPACE_X + + Blockly.Scrollbar.scrollbarThickness) { + // Slide the bubble left until it is onscreen. + relativeLeft = metrics.viewLeft + metrics.viewWidth - this.anchorX_ - + this.width_ - Blockly.BlockSvg.SEP_SPACE_X - + Blockly.Scrollbar.scrollbarThickness; + } + if (this.anchorY_ + relativeTop < + Blockly.BlockSvg.SEP_SPACE_Y + metrics.viewTop) { + // Slide the bubble below the block. + var bBox = /** @type {SVGLocatable} */ (this.shape_).getBBox(); + relativeTop = bBox.height; + } + } + this.relativeLeft_ = relativeLeft; + this.relativeTop_ = relativeTop; +}; + +/** + * Move the bubble to a location relative to the anchor's centre. + * @private + */ +Blockly.Bubble.prototype.positionBubble_ = function() { + var left; + if (Blockly.RTL) { + left = this.anchorX_ - this.relativeLeft_ - this.width_; + } else { + left = this.anchorX_ + this.relativeLeft_; + } + var top = this.relativeTop_ + this.anchorY_; + this.bubbleGroup_.setAttribute('transform', + 'translate(' + left + ', ' + top + ')'); +}; + +/** + * Get the dimensions of this bubble. + * @return {!Object} Object with width and height properties. + */ +Blockly.Bubble.prototype.getBubbleSize = function() { + return {width: this.width_, height: this.height_}; +}; + +/** + * Size this bubble. + * @param {number} width Width of the bubble. + * @param {number} height Height of the bubble. + */ +Blockly.Bubble.prototype.setBubbleSize = function(width, height) { + var doubleBorderWidth = 2 * Blockly.Bubble.BORDER_WIDTH; + // Minimum size of a bubble. + width = Math.max(width, doubleBorderWidth + 45); + height = Math.max(height, doubleBorderWidth + Blockly.BlockSvg.TITLE_HEIGHT); + this.width_ = width; + this.height_ = height; + this.bubbleBack_.setAttribute('width', width); + this.bubbleBack_.setAttribute('height', height); + if (this.resizeGroup_) { + if (Blockly.RTL) { + // Mirror the resize group. + var resizeSize = 2 * Blockly.Bubble.BORDER_WIDTH; + this.resizeGroup_.setAttribute('transform', 'translate(' + + resizeSize + ', ' + + (height - doubleBorderWidth) + ') scale(-1 1)'); + } else { + this.resizeGroup_.setAttribute('transform', 'translate(' + + (width - doubleBorderWidth) + ', ' + + (height - doubleBorderWidth) + ')'); + } + } + if (this.rendered_) { + if (this.autoLayout_) { + this.layoutBubble_(); + } + this.positionBubble_(); + this.renderArrow_(); + } + // Fire an event to allow the contents to resize. + Blockly.fireUiEvent(this.bubbleGroup_, 'resize'); +}; + +/** + * Draw the arrow between the bubble and the origin. + * @private + */ +Blockly.Bubble.prototype.renderArrow_ = function() { + var steps = []; + // Find the relative coordinates of the center of the bubble. + var relBubbleX = this.width_ / 2; + var relBubbleY = this.height_ / 2; + // Find the relative coordinates of the center of the anchor. + var relAnchorX = -this.relativeLeft_; + var relAnchorY = -this.relativeTop_; + if (relBubbleX == relAnchorX && relBubbleY == relAnchorY) { + // Null case. Bubble is directly on top of the anchor. + // Short circuit this rather than wade through divide by zeros. + steps.push('M ' + relBubbleX + ',' + relBubbleY); + } else { + // Compute the angle of the arrow's line. + var rise = relAnchorY - relBubbleY; + var run = relAnchorX - relBubbleX; + if (Blockly.RTL) { + run *= -1; + } + var hypotenuse = Math.sqrt(rise * rise + run * run); + var angle = Math.acos(run / hypotenuse); + if (rise < 0) { + angle = 2 * Math.PI - angle; + } + // Compute a line perpendicular to the arrow. + var rightAngle = angle + Math.PI / 2; + if (rightAngle > Math.PI * 2) { + rightAngle -= Math.PI * 2; + } + var rightRise = Math.sin(rightAngle); + var rightRun = Math.cos(rightAngle); + + // Calculate the thickness of the base of the arrow. + var bubbleSize = this.getBubbleSize(); + var thickness = (bubbleSize.width + bubbleSize.height) / + Blockly.Bubble.ARROW_THICKNESS; + thickness = Math.min(thickness, bubbleSize.width, bubbleSize.height) / 2; + + // Back the tip of the arrow off of the anchor. + var backoffRatio = 1 - Blockly.Bubble.ANCHOR_RADIUS / hypotenuse; + relAnchorX = relBubbleX + backoffRatio * run; + relAnchorY = relBubbleY + backoffRatio * rise; + + // Coordinates for the base of the arrow. + var baseX1 = relBubbleX + thickness * rightRun; + var baseY1 = relBubbleY + thickness * rightRise; + var baseX2 = relBubbleX - thickness * rightRun; + var baseY2 = relBubbleY - thickness * rightRise; + + // Distortion to curve the arrow. + var swirlAngle = angle + this.arrow_radians_; + if (swirlAngle > Math.PI * 2) { + swirlAngle -= Math.PI * 2; + } + var swirlRise = Math.sin(swirlAngle) * + hypotenuse / Blockly.Bubble.ARROW_BEND; + var swirlRun = Math.cos(swirlAngle) * + hypotenuse / Blockly.Bubble.ARROW_BEND; + + steps.push('M' + baseX1 + ',' + baseY1); + steps.push('C' + (baseX1 + swirlRun) + ',' + (baseY1 + swirlRise) + + ' ' + relAnchorX + ',' + relAnchorY + + ' ' + relAnchorX + ',' + relAnchorY); + steps.push('C' + relAnchorX + ',' + relAnchorY + + ' ' + (baseX2 + swirlRun) + ',' + (baseY2 + swirlRise) + + ' ' + baseX2 + ',' + baseY2); + } + steps.push('z'); + this.bubbleArrow_.setAttribute('d', steps.join(' ')); +}; + +/** + * Change the colour of a bubble. + * @param {string} hexColour Hex code of colour. + */ +Blockly.Bubble.prototype.setColour = function(hexColour) { + this.bubbleBack_.setAttribute('fill', hexColour); + this.bubbleArrow_.setAttribute('fill', hexColour); +}; + +/** + * Dispose of this bubble. + */ +Blockly.Bubble.prototype.dispose = function() { + Blockly.Bubble.unbindDragEvents_(); + // Dispose of and unlink the bubble. + goog.dom.removeNode(this.bubbleGroup_); + this.bubbleGroup_ = null; + this.workspace_ = null; + this.content_ = null; + this.shape_ = null; +}; diff --git a/core/comment.js b/core/comment.js new file mode 100644 index 000000000..c65c2bf1e --- /dev/null +++ b/core/comment.js @@ -0,0 +1,230 @@ +/** + * Visual Blocks Editor + * + * Copyright 2011 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Object representing a code comment. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Comment'); + +goog.require('Blockly.Bubble'); +goog.require('Blockly.Icon'); + + +/** + * Class for a comment. + * @param {!Blockly.Block} block The block associated with this comment. + * @extends {Blockly.Icon} + * @constructor + */ +Blockly.Comment = function(block) { + Blockly.Comment.superClass_.constructor.call(this, block); + this.createIcon_(); +}; +goog.inherits(Blockly.Comment, Blockly.Icon); + +/** + * Comment text (if bubble is not visible). + * @private + */ +Blockly.Comment.prototype.text_ = ''; + +/** + * Width of bubble. + * @private + */ +Blockly.Comment.prototype.width_ = 160; + +/** + * Height of bubble. + * @private + */ +Blockly.Comment.prototype.height_ = 80; + +/** + * Create the icon on the block. + * @private + */ +Blockly.Comment.prototype.createIcon_ = function() { + Blockly.Icon.prototype.createIcon_.call(this); + /* Here's the markup that will be generated: + + ? + */ + var iconShield = Blockly.createSvgElement('circle', + {'class': 'blocklyIconShield', + 'r': Blockly.Icon.RADIUS, + 'cx': Blockly.Icon.RADIUS, + 'cy': Blockly.Icon.RADIUS}, this.iconGroup_); + this.iconMark_ = Blockly.createSvgElement('text', + {'class': 'blocklyIconMark', + 'x': Blockly.Icon.RADIUS, + 'y': 2 * Blockly.Icon.RADIUS - 3}, this.iconGroup_); + this.iconMark_.appendChild(document.createTextNode('?')); +}; + +/** + * Create the editor for the comment's bubble. + * @return {!Element} The top-level node of the editor. + * @private + */ +Blockly.Comment.prototype.createEditor_ = function() { + /* Create the editor. Here's the markup that will be generated: + + + + + + */ + this.foreignObject_ = Blockly.createSvgElement('foreignObject', + {'x': Blockly.Bubble.BORDER_WIDTH, 'y': Blockly.Bubble.BORDER_WIDTH}, + null); + var body = document.createElementNS(Blockly.HTML_NS, 'body'); + body.setAttribute('xmlns', Blockly.HTML_NS); + body.className = 'blocklyMinimalBody'; + this.textarea_ = document.createElementNS(Blockly.HTML_NS, 'textarea'); + this.textarea_.className = 'blocklyCommentTextarea'; + this.textarea_.setAttribute('dir', Blockly.RTL ? 'RTL' : 'LTR'); + body.appendChild(this.textarea_); + this.foreignObject_.appendChild(body); + Blockly.bindEvent_(this.textarea_, 'mouseup', this, this.textareaFocus_); + return this.foreignObject_; +}; + +/** + * Callback function triggered when the bubble has resized. + * Resize the text area accordingly. + * @private + */ +Blockly.Comment.prototype.resizeBubble_ = function() { + var size = this.bubble_.getBubbleSize(); + var doubleBorderWidth = 2 * Blockly.Bubble.BORDER_WIDTH; + this.foreignObject_.setAttribute('width', size.width - doubleBorderWidth); + this.foreignObject_.setAttribute('height', size.height - doubleBorderWidth); + this.textarea_.style.width = (size.width - doubleBorderWidth - 4) + 'px'; + this.textarea_.style.height = (size.height - doubleBorderWidth - 4) + 'px'; +}; + +/** + * Show or hide the comment bubble. + * @param {boolean} visible True if the bubble should be visible. + */ +Blockly.Comment.prototype.setVisible = function(visible) { + if (visible == this.isVisible()) { + // No change. + return; + } + // Save the bubble stats before the visibility switch. + var text = this.getText(); + var size = this.getBubbleSize(); + if (visible) { + // Create the bubble. + this.bubble_ = new Blockly.Bubble( + /** @type {!Blockly.Workspace} */ (this.block_.workspace), + this.createEditor_(), this.block_.svg_.svgGroup_, + this.iconX_, this.iconY_, + this.width_, this.height_); + this.bubble_.registerResizeEvent(this, this.resizeBubble_); + this.updateColour(); + this.text_ = null; + } else { + // Dispose of the bubble. + this.bubble_.dispose(); + this.bubble_ = null; + this.textarea_ = null; + this.foreignObject_ = null; + } + // Restore the bubble stats after the visibility switch. + this.setText(text); + this.setBubbleSize(size.width, size.height); +}; + +/** + * Bring the comment to the top of the stack when clicked on. + * @param {!Event} e Mouse up event. + * @private + */ +Blockly.Comment.prototype.textareaFocus_ = function(e) { + // Ideally this would be hooked to the focus event for the comment. + // However doing so in Firefox swallows the cursor for unknown reasons. + // So this is hooked to mouseup instead. No big deal. + this.bubble_.promote_(); + // Since the act of moving this node within the DOM causes a loss of focus, + // we need to reapply the focus. + this.textarea_.focus(); +}; + +/** + * Get the dimensions of this comment's bubble. + * @return {!Object} Object with width and height properties. + */ +Blockly.Comment.prototype.getBubbleSize = function() { + if (this.isVisible()) { + return this.bubble_.getBubbleSize(); + } else { + return {width: this.width_, height: this.height_}; + } +}; + +/** + * Size this comment's bubble. + * @param {number} width Width of the bubble. + * @param {number} height Height of the bubble. + */ +Blockly.Comment.prototype.setBubbleSize = function(width, height) { + if (this.isVisible()) { + this.bubble_.setBubbleSize(width, height); + } else { + this.width_ = width; + this.height_ = height; + } +}; + +/** + * Returns this comment's text. + * @return {string} Comment text. + */ +Blockly.Comment.prototype.getText = function() { + return this.isVisible() ? this.textarea_.value : this.text_; +}; + +/** + * Set this comment's text. + * @param {string} text Comment text. + */ +Blockly.Comment.prototype.setText = function(text) { + if (this.isVisible()) { + this.textarea_.value = text; + } else { + this.text_ = text; + } +}; + +/** + * Dispose of this comment. + */ +Blockly.Comment.prototype.dispose = function() { + this.block_.comment = null; + Blockly.Icon.prototype.dispose.call(this); +}; + diff --git a/core/connection.js b/core/connection.js new file mode 100644 index 000000000..b645346dc --- /dev/null +++ b/core/connection.js @@ -0,0 +1,781 @@ +/** + * Visual Blocks Editor + * + * Copyright 2011 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Components for creating connections between blocks. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Connection'); +goog.provide('Blockly.ConnectionDB'); + +goog.require('Blockly.Workspace'); + + +/** + * Class for a connection between blocks. + * @param {!Blockly.Block} source The block establishing this connection. + * @param {number} type The type of the connection. + * @constructor + */ +Blockly.Connection = function(source, type) { + this.sourceBlock_ = source; + this.targetConnection = null; + this.type = type; + this.x_ = 0; + this.y_ = 0; + this.inDB_ = false; + // Shortcut for the databases for this connection's workspace. + this.dbList_ = this.sourceBlock_.workspace.connectionDBList; +}; + +/** + * Sever all links to this connection (not including from the source object). + */ +Blockly.Connection.prototype.dispose = function() { + if (this.targetConnection) { + throw 'Disconnect connection before disposing of it.'; + } + if (this.inDB_) { + this.dbList_[this.type].removeConnection_(this); + } + this.inDB_ = false; + if (Blockly.highlightedConnection_ == this) { + Blockly.highlightedConnection_ = null; + } + if (Blockly.localConnection_ == this) { + Blockly.localConnection_ = null; + } +}; + +/** + * Does the connection belong to a superior block (higher in the source stack)? + * @return {boolean} True if connection faces down or right. + */ +Blockly.Connection.prototype.isSuperior = function() { + return this.type == Blockly.INPUT_VALUE || + this.type == Blockly.NEXT_STATEMENT; +}; + +/** + * Connect this connection to another connection. + * @param {!Blockly.Connection} otherConnection Connection to connect to. + */ +Blockly.Connection.prototype.connect = function(otherConnection) { + if (this.sourceBlock_ == otherConnection.sourceBlock_) { + throw 'Attempted to connect a block to itself.'; + } + if (this.sourceBlock_.workspace !== otherConnection.sourceBlock_.workspace) { + throw 'Blocks are on different workspaces.'; + } + if (Blockly.OPPOSITE_TYPE[this.type] != otherConnection.type) { + throw 'Attempt to connect incompatible types.'; + } + if (this.type == Blockly.INPUT_VALUE || this.type == Blockly.OUTPUT_VALUE) { + if (this.targetConnection) { + // Can't make a value connection if male block is already connected. + throw 'Source connection already connected (value).'; + } else if (otherConnection.targetConnection) { + // If female block is already connected, disconnect and bump the male. + var orphanBlock = otherConnection.targetBlock(); + orphanBlock.setParent(null); + if (!orphanBlock.outputConnection) { + throw 'Orphan block does not have an output connection.'; + } + // Attempt to reattach the orphan at the end of the newly inserted + // block. Since this block may be a row, walk down to the end. + var newBlock = this.sourceBlock_; + var connection; + while (connection = + Blockly.Connection.singleConnection_( + /** @type {!Blockly.Block} */ (newBlock), orphanBlock)) { + // '=' is intentional in line above. + if (connection.targetBlock()) { + newBlock = connection.targetBlock(); + } else { + connection.connect(orphanBlock.outputConnection); + orphanBlock = null; + break; + } + } + if (orphanBlock) { + // Unable to reattach orphan. Bump it off to the side. + window.setTimeout(function() { + orphanBlock.outputConnection.bumpAwayFrom_(otherConnection); + }, Blockly.BUMP_DELAY); + } + } + } else { + if (this.targetConnection) { + throw 'Source connection already connected (block).'; + } else if (otherConnection.targetConnection) { + // Statement blocks may be inserted into the middle of a stack. + if (this.type != Blockly.PREVIOUS_STATEMENT) { + throw 'Can only do a mid-stack connection with the top of a block.'; + } + // Split the stack. + var orphanBlock = otherConnection.targetBlock(); + orphanBlock.setParent(null); + if (!orphanBlock.previousConnection) { + throw 'Orphan block does not have a previous connection.'; + } + // Attempt to reattach the orphan at the bottom of the newly inserted + // block. Since this block may be a stack, walk down to the end. + var newBlock = this.sourceBlock_; + while (newBlock.nextConnection) { + if (newBlock.nextConnection.targetConnection) { + newBlock = newBlock.nextConnection.targetBlock(); + } else { + newBlock.nextConnection.connect(orphanBlock.previousConnection); + orphanBlock = null; + break; + } + } + if (orphanBlock) { + // Unable to reattach orphan. Bump it off to the side. + window.setTimeout(function() { + orphanBlock.previousConnection.bumpAwayFrom_(otherConnection); + }, Blockly.BUMP_DELAY); + } + } + } + + // Determine which block is superior (higher in the source stack). + var parentBlock, childBlock; + if (this.isSuperior()) { + // Superior block. + parentBlock = this.sourceBlock_; + childBlock = otherConnection.sourceBlock_; + } else { + // Inferior block. + parentBlock = otherConnection.sourceBlock_; + childBlock = this.sourceBlock_; + } + + // Establish the connections. + this.targetConnection = otherConnection; + otherConnection.targetConnection = this; + + // Demote the inferior block so that one is a child of the superior one. + childBlock.setParent(parentBlock); + + if (parentBlock.rendered) { + parentBlock.svg_.updateDisabled(); + } + if (childBlock.rendered) { + childBlock.svg_.updateDisabled(); + } + if (parentBlock.rendered && childBlock.rendered) { + if (this.type == Blockly.NEXT_STATEMENT || + this.type == Blockly.PREVIOUS_STATEMENT) { + // Child block may need to square off its corners if it is in a stack. + // Rendering a child will render its parent. + childBlock.render(); + } else { + // Child block does not change shape. Rendering the parent node will + // move its connected children into position. + parentBlock.render(); + } + } +}; + +/** + * Does the given block have one and only one connection point that will accept + * the orphaned block? + * @param {!Blockly.Block} block The superior block. + * @param {!Blockly.Block} orphanBlock The inferior block. + * @return {Blockly.Connection} The suitable connection point on 'block', + * or null. + * @private + */ +Blockly.Connection.singleConnection_ = function(block, orphanBlock) { + var connection = false; + for (var x = 0; x < block.inputList.length; x++) { + var thisConnection = block.inputList[x].connection; + if (thisConnection && thisConnection.type == Blockly.INPUT_VALUE && + orphanBlock.outputConnection.checkType_(thisConnection)) { + if (connection) { + return null; // More than one connection. + } + connection = thisConnection; + } + } + return connection; +}; + +/** + * Disconnect this connection. + */ +Blockly.Connection.prototype.disconnect = function() { + var otherConnection = this.targetConnection; + if (!otherConnection) { + throw 'Source connection not connected.'; + } else if (otherConnection.targetConnection != this) { + throw 'Target connection not connected to source connection.'; + } + otherConnection.targetConnection = null; + this.targetConnection = null; + + // Rerender the parent so that it may reflow. + var parentBlock, childBlock; + if (this.isSuperior()) { + // Superior block. + parentBlock = this.sourceBlock_; + childBlock = otherConnection.sourceBlock_; + } else { + // Inferior block. + parentBlock = otherConnection.sourceBlock_; + childBlock = this.sourceBlock_; + } + if (parentBlock.rendered) { + parentBlock.render(); + } + if (childBlock.rendered) { + childBlock.svg_.updateDisabled(); + childBlock.render(); + } +}; + +/** + * Returns the block that this connection connects to. + * @return {Blockly.Block} The connected block or null if none is connected. + */ +Blockly.Connection.prototype.targetBlock = function() { + if (this.targetConnection) { + return this.targetConnection.sourceBlock_; + } + return null; +}; + +/** + * Move the block(s) belonging to the connection to a point where they don't + * visually interfere with the specified connection. + * @param {!Blockly.Connection} staticConnection The connection to move away + * from. + * @private + */ +Blockly.Connection.prototype.bumpAwayFrom_ = function(staticConnection) { + if (Blockly.Block.dragMode_ != 0) { + // Don't move blocks around while the user is doing the same. + return; + } + // Move the root block. + var rootBlock = this.sourceBlock_.getRootBlock(); + if (rootBlock.isInFlyout) { + // Don't move blocks around in a flyout. + return; + } + var reverse = false; + if (!rootBlock.isMovable()) { + // Can't bump an uneditable block away. + // Check to see if the other block is movable. + rootBlock = staticConnection.sourceBlock_.getRootBlock(); + if (!rootBlock.isMovable()) { + return; + } + // Swap the connections and move the 'static' connection instead. + staticConnection = this; + reverse = true; + } + // Raise it to the top for extra visibility. + rootBlock.getSvgRoot().parentNode.appendChild(rootBlock.getSvgRoot()); + var dx = (staticConnection.x_ + Blockly.SNAP_RADIUS) - this.x_; + var dy = (staticConnection.y_ + Blockly.SNAP_RADIUS * 2) - this.y_; + if (reverse) { + // When reversing a bump due to an uneditable block, bump up. + dy = -dy; + } + if (Blockly.RTL) { + dx = -dx; + } + rootBlock.moveBy(dx, dy); +}; + +/** + * Change the connection's coordinates. + * @param {number} x New absolute x coordinate. + * @param {number} y New absolute y coordinate. + */ +Blockly.Connection.prototype.moveTo = function(x, y) { + // Remove it from its old location in the database (if already present) + if (this.inDB_) { + this.dbList_[this.type].removeConnection_(this); + } + this.x_ = x; + this.y_ = y; + // Insert it into its new location in the database. + this.dbList_[this.type].addConnection_(this); +}; + +/** + * Change the connection's coordinates. + * @param {number} dx Change to x coordinate. + * @param {number} dy Change to y coordinate. + */ +Blockly.Connection.prototype.moveBy = function(dx, dy) { + this.moveTo(this.x_ + dx, this.y_ + dy); +}; + +/** + * Add highlighting around this connection. + */ +Blockly.Connection.prototype.highlight = function() { + var steps; + if (this.type == Blockly.INPUT_VALUE || this.type == Blockly.OUTPUT_VALUE) { + var tabWidth = Blockly.RTL ? -Blockly.BlockSvg.TAB_WIDTH : + Blockly.BlockSvg.TAB_WIDTH; + steps = 'm 0,0 v 5 c 0,10 ' + -tabWidth + ',-8 ' + -tabWidth + ',7.5 s ' + + tabWidth + ',-2.5 ' + tabWidth + ',7.5 v 5'; + } else { + if (Blockly.RTL) { + steps = 'm 20,0 h -5 l -6,4 -3,0 -6,-4 h -5'; + } else { + steps = 'm -20,0 h 5 l 6,4 3,0 6,-4 h 5'; + } + } + var xy = this.sourceBlock_.getRelativeToSurfaceXY(); + var x = this.x_ - xy.x; + var y = this.y_ - xy.y; + Blockly.Connection.highlightedPath_ = Blockly.createSvgElement('path', + {'class': 'blocklyHighlightedConnectionPath', + 'd': steps, + transform: 'translate(' + x + ', ' + y + ')'}, + this.sourceBlock_.getSvgRoot()); +}; + +/** + * Remove the highlighting around this connection. + */ +Blockly.Connection.prototype.unhighlight = function() { + goog.dom.removeNode(Blockly.Connection.highlightedPath_); + delete Blockly.Connection.highlightedPath_; +}; + +/** + * Move the blocks on either side of this connection right next to each other. + * @private + */ +Blockly.Connection.prototype.tighten_ = function() { + var dx = Math.round(this.targetConnection.x_ - this.x_); + var dy = Math.round(this.targetConnection.y_ - this.y_); + if (dx != 0 || dy != 0) { + var block = this.targetBlock(); + var svgRoot = block.getSvgRoot(); + if (!svgRoot) { + throw 'block is not rendered.'; + } + var xy = Blockly.getRelativeXY_(svgRoot); + block.getSvgRoot().setAttribute('transform', + 'translate(' + (xy.x - dx) + ', ' + (xy.y - dy) + ')'); + block.moveConnections_(-dx, -dy); + } +}; + +/** + * Find the closest compatible connection to this connection. + * @param {number} maxLimit The maximum radius to another connection. + * @param {number} dx Horizontal offset between this connection's location + * in the database and the current location (as a result of dragging). + * @param {number} dy Vertical offset between this connection's location + * in the database and the current location (as a result of dragging). + * @return {!Object} Contains two properties: 'connection' which is either + * another connection or null, and 'radius' which is the distance. + */ +Blockly.Connection.prototype.closest = function(maxLimit, dx, dy) { + if (this.targetConnection) { + // Don't offer to connect to a connection that's already connected. + return {connection: null, radius: maxLimit}; + } + // Determine the opposite type of connection. + var oppositeType = Blockly.OPPOSITE_TYPE[this.type]; + var db = this.dbList_[oppositeType]; + + // Since this connection is probably being dragged, add the delta. + var currentX = this.x_ + dx; + var currentY = this.y_ + dy; + + // Binary search to find the closest y location. + var pointerMin = 0; + var pointerMax = db.length - 2; + var pointerMid = pointerMax; + while (pointerMin < pointerMid) { + if (db[pointerMid].y_ < currentY) { + pointerMin = pointerMid; + } else { + pointerMax = pointerMid; + } + pointerMid = Math.floor((pointerMin + pointerMax) / 2); + } + + // Walk forward and back on the y axis looking for the closest x,y point. + pointerMin = pointerMid; + pointerMax = pointerMid; + var closestConnection = null; + var sourceBlock = this.sourceBlock_; + var thisConnection = this; + if (db.length) { + while (pointerMin >= 0 && checkConnection_(pointerMin)) { + pointerMin--; + } + do { + pointerMax++; + } while (pointerMax < db.length && checkConnection_(pointerMax)); + } + + /** + * Computes if the current connection is within the allowed radius of another + * connection. + * This function is a closure and has access to outside variables. + * @param {number} yIndex The other connection's index in the database. + * @return {boolean} True if the search needs to continue: either the current + * connection's vertical distance from the other connection is less than + * the allowed radius, or if the connection is not compatible. + */ + function checkConnection_(yIndex) { + var connection = db[yIndex]; + if (connection.type == Blockly.OUTPUT_VALUE || + connection.type == Blockly.PREVIOUS_STATEMENT) { + // Don't offer to connect an already connected left (male) value plug to + // an available right (female) value plug. Don't offer to connect the + // bottom of a statement block to one that's already connected. + if (connection.targetConnection) { + return true; + } + } + // Offering to connect the top of a statement block to an already connected + // connection is ok, we'll just insert it into the stack. + // Offering to connect the left (male) of a value block to an already + // connected value pair is ok, we'll splice it in. + + // Do type checking. + if (!thisConnection.checkType_(connection)) { + return true; + } + + // Don't let blocks try to connect to themselves or ones they nest. + var targetSourceBlock = connection.sourceBlock_; + do { + if (sourceBlock == targetSourceBlock) { + return true; + } + targetSourceBlock = targetSourceBlock.getParent(); + } while (targetSourceBlock); + + var dx = currentX - db[yIndex].x_; + var dy = currentY - db[yIndex].y_; + var r = Math.sqrt(dx * dx + dy * dy); + if (r <= maxLimit) { + closestConnection = db[yIndex]; + maxLimit = r; + } + return dy < maxLimit; + } + return {connection: closestConnection, radius: maxLimit}; +}; + +/** + * Is this connection compatible with another connection with respect to the + * value type system. E.g. square_root("Hello") is not compatible. + * @param {!Blockly.Connection} otherConnection Connection to compare against. + * @return {boolean} True if the connections share a type. + * @private + */ +Blockly.Connection.prototype.checkType_ = function(otherConnection) { + if (!this.check_ || !otherConnection.check_) { + // One or both sides are promiscuous enough that anything will fit. + return true; + } + // Find any intersection in the check lists. + for (var x = 0; x < this.check_.length; x++) { + if (otherConnection.check_.indexOf(this.check_[x]) != -1) { + return true; + } + } + // No intersection. + return false; +}; + +/** + * Change a connection's compatibility. + * @param {*} check Compatible value type or list of value types. + * Null if all types are compatible. + * @return {!Blockly.Connection} The connection being modified + * (to allow chaining). + */ +Blockly.Connection.prototype.setCheck = function(check) { + if (check) { + // Ensure that check is in an array. + if (!(check instanceof Array)) { + check = [check]; + } + this.check_ = check; + // The new value type may not be compatible with the existing connection. + if (this.targetConnection && !this.checkType_(this.targetConnection)) { + if (this.isSuperior()) { + this.targetBlock().setParent(null); + } else { + this.sourceBlock_.setParent(null); + } + // Bump away. + this.sourceBlock_.bumpNeighbours_(); + } + } else { + this.check_ = null; + } + return this; +}; + +/** + * Find all nearby compatible connections to this connection. + * Type checking does not apply, since this function is used for bumping. + * @param {number} maxLimit The maximum radius to another connection. + * @return {!Array.} List of connections. + * @private + */ +Blockly.Connection.prototype.neighbours_ = function(maxLimit) { + // Determine the opposite type of connection. + var oppositeType = Blockly.OPPOSITE_TYPE[this.type]; + var db = this.dbList_[oppositeType]; + + var currentX = this.x_; + var currentY = this.y_; + + // Binary search to find the closest y location. + var pointerMin = 0; + var pointerMax = db.length - 2; + var pointerMid = pointerMax; + while (pointerMin < pointerMid) { + if (db[pointerMid].y_ < currentY) { + pointerMin = pointerMid; + } else { + pointerMax = pointerMid; + } + pointerMid = Math.floor((pointerMin + pointerMax) / 2); + } + + // Walk forward and back on the y axis looking for the closest x,y point. + pointerMin = pointerMid; + pointerMax = pointerMid; + var neighbours = []; + var sourceBlock = this.sourceBlock_; + if (db.length) { + while (pointerMin >= 0 && checkConnection_(pointerMin)) { + pointerMin--; + } + do { + pointerMax++; + } while (pointerMax < db.length && checkConnection_(pointerMax)); + } + + /** + * Computes if the current connection is within the allowed radius of another + * connection. + * This function is a closure and has access to outside variables. + * @param {number} yIndex The other connection's index in the database. + * @return {boolean} True if the current connection's vertical distance from + * the other connection is less than the allowed radius. + */ + function checkConnection_(yIndex) { + var dx = currentX - db[yIndex].x_; + var dy = currentY - db[yIndex].y_; + var r = Math.sqrt(dx * dx + dy * dy); + if (r <= maxLimit) { + neighbours.push(db[yIndex]); + } + return dy < maxLimit; + } + return neighbours; +}; + +/** + * Hide this connection, as well as all down-stream connections on any block + * attached to this connection. This happens when a block is collapsed. + * Also hides down-stream comments. + */ +Blockly.Connection.prototype.hideAll = function() { + if (this.inDB_) { + this.dbList_[this.type].removeConnection_(this); + } + if (this.targetConnection) { + var blocks = this.targetBlock().getDescendants(); + for (var b = 0; b < blocks.length; b++) { + var block = blocks[b]; + // Hide all connections of all children. + var connections = block.getConnections_(true); + for (var c = 0; c < connections.length; c++) { + var connection = connections[c]; + if (connection.inDB_) { + this.dbList_[connection.type].removeConnection_(connection); + } + } + // Close all bubbles of all children. + var icons = block.getIcons(); + for (var x = 0; x < icons.length; x++) { + icons[x].setVisible(false); + } + } + } +}; + +/** + * Unhide this connection, as well as all down-stream connections on any block + * attached to this connection. This happens when a block is expanded. + * Also unhides down-stream comments. + * @return {!Array.} List of blocks to render. + */ +Blockly.Connection.prototype.unhideAll = function() { + if (!this.inDB_) { + this.dbList_[this.type].addConnection_(this); + } + // All blocks that need unhiding must be unhidden before any rendering takes + // place, since rendering requires knowing the dimensions of lower blocks. + // Also, since rendering a block renders all its parents, we only need to + // render the leaf nodes. + var renderList = []; + if (this.type != Blockly.INPUT_VALUE && this.type != Blockly.NEXT_STATEMENT) { + // Only spider down. + return renderList; + } + var block = this.targetBlock(); + if (block) { + var connections; + if (block.isCollapsed()) { + // This block should only be partially revealed since it is collapsed. + connections = []; + block.outputConnection && connections.push(block.outputConnection); + block.nextConnection && connections.push(block.nextConnection); + block.previousConnection && connections.push(block.previousConnection); + } else { + // Show all connections of this block. + connections = block.getConnections_(true); + } + for (var c = 0; c < connections.length; c++) { + renderList = renderList.concat(connections[c].unhideAll()); + } + if (renderList.length == 0) { + // Leaf block. + renderList[0] = block; + } + } + return renderList; +}; + + +/** + * Database of connections. + * Connections are stored in order of their vertical component. This way + * connections in an area may be looked up quickly using a binary search. + * @constructor + */ +Blockly.ConnectionDB = function() { +}; + +Blockly.ConnectionDB.prototype = new Array(); +/** + * Don't inherit the constructor from Array. + * @type {!Function} + */ +Blockly.ConnectionDB.constructor = Blockly.ConnectionDB; + +/** + * Add a connection to the database. Must not already exist in DB. + * @param {!Blockly.Connection} connection The connection to be added. + * @private + */ +Blockly.ConnectionDB.prototype.addConnection_ = function(connection) { + if (connection.inDB_) { + throw 'Connection already in database.'; + } + // Insert connection using binary search. + var pointerMin = 0; + var pointerMax = this.length; + while (pointerMin < pointerMax) { + var pointerMid = Math.floor((pointerMin + pointerMax) / 2); + if (this[pointerMid].y_ < connection.y_) { + pointerMin = pointerMid + 1; + } else if (this[pointerMid].y_ > connection.y_) { + pointerMax = pointerMid; + } else { + pointerMin = pointerMid; + break; + } + } + this.splice(pointerMin, 0, connection); + connection.inDB_ = true; +}; + +/** + * Remove a connection from the database. Must already exist in DB. + * @param {!Blockly.Connection} connection The connection to be removed. + * @private + */ +Blockly.ConnectionDB.prototype.removeConnection_ = function(connection) { + if (!connection.inDB_) { + throw 'Connection not in database.'; + } + connection.inDB_ = false; + // Find the connection using a binary search. + var pointerMin = 0; + var pointerMax = this.length - 2; + var pointerMid = pointerMax; + while (pointerMin < pointerMid) { + if (this[pointerMid].y_ < connection.y_) { + pointerMin = pointerMid; + } else { + pointerMax = pointerMid; + } + pointerMid = Math.floor((pointerMin + pointerMax) / 2); + } + + // Walk forward and back on the y axis looking for the connection. + // When found, splice it out of the array. + pointerMin = pointerMid; + pointerMax = pointerMid; + while (pointerMin >= 0 && this[pointerMin].y_ == connection.y_) { + if (this[pointerMin] == connection) { + this.splice(pointerMin, 1); + return; + } + pointerMin--; + } + do { + if (this[pointerMax] == connection) { + this.splice(pointerMax, 1); + return; + } + pointerMax++; + } while (pointerMax < this.length && + this[pointerMax].y_ == connection.y_); + throw 'Unable to find connection in connectionDB.'; +}; + +/** + * Initialize a set of connection DBs for a specified workspace. + * @param {!Blockly.Workspace} workspace The workspace this DB is for. + */ +Blockly.ConnectionDB.init = function(workspace) { + // Create four databases, one for each connection type. + var dbList = []; + dbList[Blockly.INPUT_VALUE] = new Blockly.ConnectionDB(); + dbList[Blockly.OUTPUT_VALUE] = new Blockly.ConnectionDB(); + dbList[Blockly.NEXT_STATEMENT] = new Blockly.ConnectionDB(); + dbList[Blockly.PREVIOUS_STATEMENT] = new Blockly.ConnectionDB(); + workspace.connectionDBList = dbList; +}; diff --git a/core/contextmenu.js b/core/contextmenu.js new file mode 100644 index 000000000..d6485cfd4 --- /dev/null +++ b/core/contextmenu.js @@ -0,0 +1,225 @@ +/** + * Visual Blocks Editor + * + * Copyright 2011 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Functionality for the right-click context menus. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.ContextMenu'); + + +/** + * Horizontal padding on either side of each option. + */ +Blockly.ContextMenu.X_PADDING = 20; + +/** + * Vertical height of each option. + */ +Blockly.ContextMenu.Y_HEIGHT = 20; + +/** + * Is a context menu currently showing? + */ +Blockly.ContextMenu.visible = false; + +/** + * Creates the context menu's DOM. Only needs to be called once. + * @return {!SVGGElement} The context menu's SVG group. + */ +Blockly.ContextMenu.createDom = function() { + /* + + + + + + + */ + var svgGroup = /** @type {!SVGGElement} */ ( + Blockly.createSvgElement('g', {'class': 'blocklyHidden'}, null)); + Blockly.ContextMenu.svgGroup = svgGroup; + Blockly.ContextMenu.svgShadow = Blockly.createSvgElement('rect', + {'class': 'blocklyContextMenuShadow', + 'x': 2, 'y': -2, 'rx': 4, 'ry': 4}, svgGroup); + Blockly.ContextMenu.svgBackground = Blockly.createSvgElement('rect', + {'class': 'blocklyContextMenuBackground', + 'y': -4, 'rx': 4, 'ry': 4}, svgGroup); + Blockly.ContextMenu.svgOptions = Blockly.createSvgElement('g', + {'class': 'blocklyContextMenuOptions'}, svgGroup); + return svgGroup; +}; + +/** + * Construct the menu based on the list of options and show the menu. + * @param {!Object} xy Coordinates of anchor point, contains x and y properties. + * @param {!Array.} options Array of menu options. + */ +Blockly.ContextMenu.show = function(xy, options) { + if (!options.length) { + Blockly.ContextMenu.hide(); + return; + } + /* Here's what one option object looks like: + {text: 'Make It So', + enabled: true, + callback: Blockly.MakeItSo} + */ + // Erase all existing options. + goog.dom.removeChildren(Blockly.ContextMenu.svgOptions); + /* Here's the SVG we want for each option: + + + Make It So + + */ + // The menu must be made visible early since otherwise BBox and + // getComputedTextLength will return 0. + Blockly.ContextMenu.svgGroup.style.display = 'block'; + var maxWidth = 0; + var resizeList = [Blockly.ContextMenu.svgBackground, + Blockly.ContextMenu.svgShadow]; + for (var x = 0, option; option = options[x]; x++) { + var gElement = Blockly.ContextMenu.optionToDom(option.text); + var rectElement = /** @type {SVGRectElement} */ (gElement.firstChild); + var textElement = /** @type {SVGTextElement} */ (gElement.lastChild); + Blockly.ContextMenu.svgOptions.appendChild(gElement); + + gElement.setAttribute('transform', + 'translate(0, ' + (x * Blockly.ContextMenu.Y_HEIGHT) + ')'); + resizeList.push(rectElement); + Blockly.bindEvent_(gElement, 'mousedown', null, Blockly.noEvent); + if (option.enabled) { + Blockly.bindEvent_(gElement, 'mouseup', null, option.callback); + Blockly.bindEvent_(gElement, 'mouseup', null, Blockly.ContextMenu.hide); + } else { + gElement.setAttribute('class', 'blocklyMenuDivDisabled'); + } + // Compute the length of the longest text length. + maxWidth = Math.max(maxWidth, textElement.getComputedTextLength()); + } + // Run a second pass to resize all options to the required width. + maxWidth += Blockly.ContextMenu.X_PADDING * 2; + for (var x = 0; x < resizeList.length; x++) { + resizeList[x].setAttribute('width', maxWidth); + } + if (Blockly.RTL) { + // Right-align the text. + for (var x = 0, gElement; + gElement = Blockly.ContextMenu.svgOptions.childNodes[x]; x++) { + var textElement = gElement.lastChild; + textElement.setAttribute('text-anchor', 'end'); + textElement.setAttribute('x', maxWidth - Blockly.ContextMenu.X_PADDING); + } + } + Blockly.ContextMenu.svgBackground.setAttribute('height', + options.length * Blockly.ContextMenu.Y_HEIGHT + 8); + Blockly.ContextMenu.svgShadow.setAttribute('height', + options.length * Blockly.ContextMenu.Y_HEIGHT + 10); + + // Convert the mouse coordinates into SVG coordinates. + var anchorX = xy.x; + var anchorY = xy.y; + + // Measure the menu's size and position it so that it does not go off-screen. + var bBox = Blockly.ContextMenu.svgGroup.getBBox(); + var svgSize = Blockly.svgSize(); + if (anchorY + bBox.height > svgSize.height) { + // Falling off the bottom of the screen; flip the menu up. + anchorY -= bBox.height - 10; + } + if (Blockly.RTL) { + if (anchorX - bBox.width <= 0) { + anchorX++; + } else { + // Falling off the left edge in RTL mode; flip menu to right. + anchorX -= bBox.width; + } + } else { + if (anchorX + bBox.width > svgSize.width) { + // Falling off the right edge in LTR mode; flip the menu to left. + anchorX -= bBox.width; + } else { + anchorX++; + } + } + Blockly.ContextMenu.svgGroup.setAttribute('transform', + 'translate(' + anchorX + ', ' + anchorY + ')'); + Blockly.ContextMenu.visible = true; +}; + +/** + * Create the DOM nodes for a menu option. + * @param {string} text The option's text. + * @return {!Element} node containing the menu option. + */ +Blockly.ContextMenu.optionToDom = function(text) { + /* Here's the SVG we create: + + + Make It So + + */ + var gElement = Blockly.createSvgElement('g', {'class': 'blocklyMenuDiv'}, + null); + var rectElement = Blockly.createSvgElement('rect', + {'height': Blockly.ContextMenu.Y_HEIGHT}, gElement); + var textElement = Blockly.createSvgElement('text', + {'class': 'blocklyMenuText', + 'x': Blockly.ContextMenu.X_PADDING, + 'y': 15}, gElement); + var textNode = document.createTextNode(text); + textElement.appendChild(textNode); + return gElement; +}; + +/** + * Hide the context menu. + */ +Blockly.ContextMenu.hide = function() { + if (Blockly.ContextMenu.visible) { + Blockly.ContextMenu.svgGroup.style.display = 'none'; + Blockly.ContextMenu.visible = false; + } +}; + +/** + * Create a callback function that creates and configures a block, + * then places the new block next to the original. + * @param {!Blockly.Block} block Original block. + * @param {!Element} xml XML representation of new block. + * @return {!Function} Function that creates a block. + */ +Blockly.ContextMenu.callbackFactory = function(block, xml) { + return function() { + var newBlock = Blockly.Xml.domToBlock_(block.workspace, xml); + // Move the new block next to the old block. + var xy = block.getRelativeToSurfaceXY(); + if (Blockly.RTL) { + xy.x -= Blockly.SNAP_RADIUS; + } else { + xy.x += Blockly.SNAP_RADIUS; + } + xy.y += Blockly.SNAP_RADIUS * 2; + newBlock.moveBy(xy.x, xy.y); + newBlock.select(); + }; +}; diff --git a/core/css.js b/core/css.js new file mode 100644 index 000000000..465b984dc --- /dev/null +++ b/core/css.js @@ -0,0 +1,399 @@ +/** + * Visual Blocks Editor + * + * Copyright 2013 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Inject Blockly's CSS synchronously. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Css'); + +goog.require('goog.cssom'); + + +/** + * Inject the CSS into the DOM. This is preferable over using a regular CSS + * file since: + * a) It loads synchronously and doesn't force a redraw later. + * b) It speeds up loading by not blocking on a separate HTTP transfer. + * c) The CSS content may be made dynamic depending on init options. + */ +Blockly.Css.inject = function() { + var text = Blockly.Css.CONTENT.join('\n'); + // Strip off any trailing slash (either Unix or Windows). + var path = Blockly.pathToBlockly.replace(/[\\\/]$/, ''); + text = text.replace(/<<>>/g, path); + goog.cssom.addCssText(text); +}; + +/** + * Array making up the CSS content for Blockly. + */ +Blockly.Css.CONTENT = [ + '.blocklySvg {', + ' background-color: #fff;', + ' border: 1px solid #ddd;', + '}', + '.blocklyWidgetDiv {', + ' position: absolute;', + ' display: none;', + ' z-index: 999;', + '}', + '.blocklyDraggable {', + ' /* Hotspot coordinates are baked into the CUR file, but they are still', + ' required in the CSS due to a Chrome bug.', + ' http://code.google.com/p/chromium/issues/detail?id=1446 */', + ' cursor: url(<<>>/media/handopen.cur) 8 5, auto;', + '}', + '.blocklyResizeSE {', + ' fill: #aaa;', + ' cursor: se-resize;', + '}', + '.blocklyResizeSW {', + ' fill: #aaa;', + ' cursor: sw-resize;', + '}', + '.blocklyResizeLine {', + ' stroke-width: 1;', + ' stroke: #888;', + '}', + '.blocklyHighlightedConnectionPath {', + ' stroke-width: 4px;', + ' stroke: #fc3;', + ' fill: none;', + '}', + '.blocklyPathLight {', + ' fill: none;', + ' stroke-width: 2;', + ' stroke-linecap: round;', + '}', + '.blocklySelected>.blocklyPath {', + ' stroke-width: 3px;', + ' stroke: #fc3;', + '}', + '.blocklySelected>.blocklyPathLight {', + ' display: none;', + '}', + '.blocklyDragging>.blocklyPath,', + '.blocklyDragging>.blocklyPathLight {', + ' fill-opacity: 0.8;', + ' stroke-opacity: 0.8;', + '}', + '.blocklyDragging>.blocklyPathDark {', + ' display: none;', + '}', + '.blocklyDisabled>.blocklyPath {', + ' fill-opacity: 0.50;', + ' stroke-opacity: 0.50;', + '}', + '.blocklyDisabled>.blocklyPathLight,', + '.blocklyDisabled>.blocklyPathDark {', + ' display: none;', + '}', + '.blocklyText {', + ' cursor: default;', + ' font-family: sans-serif;', + ' font-size: 11pt;', + ' fill: #fff;', + '}', + '.blocklyNonEditableText>text {', + ' pointer-events: none;', + '}', + '.blocklyNonEditableText>rect,', + '.blocklyEditableText>rect {', + ' fill: #fff;', + ' fill-opacity: 0.6;', + '}', + '.blocklyNonEditableText>text,', + '.blocklyEditableText>text {', + ' fill: #000;', + '}', + '.blocklyEditableText:hover>rect {', + ' stroke-width: 2;', + ' stroke: #fff;', + '}', + '/*', + ' * Don\'t allow users to select text. It gets annoying when trying to', + ' * drag a block and selected text moves instead.', + ' */', + '.blocklySvg text {', + ' -moz-user-select: none;', + ' -webkit-user-select: none;', + ' user-select: none;', + ' cursor: inherit;', + '}', + '', + '.blocklyHidden {', + ' display: none;', + '}', + '.blocklyFieldDropdown:not(.blocklyHidden) {', + ' display: block;', + '}', + '.blocklyTooltipBackground {', + ' fill: #ffffc7;', + ' stroke-width: 1px;', + ' stroke: #d8d8d8;', + '}', + '.blocklyTooltipShadow,', + '.blocklyContextMenuShadow,', + '.blocklyDropdownMenuShadow {', + ' fill: #bbb;', + ' filter: url(#blocklyShadowFilter);', + '}', + '.blocklyTooltipText {', + ' font-family: sans-serif;', + ' font-size: 9pt;', + ' fill: #000;', + '}', + '', + '.blocklyIconShield {', + ' cursor: default;', + ' fill: #00c;', + ' stroke-width: 1px;', + ' stroke: #ccc;', + '}', + '.blocklyIconGroup:hover>.blocklyIconShield {', + ' fill: #00f;', + ' stroke: #fff;', + '}', + '.blocklyIconGroup:hover>.blocklyIconMark {', + ' fill: #fff;', + '}', + '.blocklyIconMark {', + ' cursor: default !important;', + ' font-family: sans-serif;', + ' font-size: 9pt;', + ' font-weight: bold;', + ' fill: #ccc;', + ' text-anchor: middle;', + '}', + '.blocklyWarningBody {', + '}', + '.blocklyMinimalBody {', + ' margin: 0;', + ' padding: 0;', + '}', + '.blocklyCommentTextarea {', + ' margin: 0;', + ' padding: 2px;', + ' border: 0;', + ' resize: none;', + ' background-color: #ffc;', + '}', + '.blocklyHtmlInput {', + ' font-family: sans-serif;', + ' font-size: 11pt;', + ' border: none;', + ' outline: none;', + ' width: 100%', + '}', + '.blocklyContextMenuBackground,', + '.blocklyMutatorBackground {', + ' fill: #fff;', + ' stroke-width: 1;', + ' stroke: #ddd;', + '}', + '.blocklyContextMenuOptions>.blocklyMenuDiv,', + '.blocklyContextMenuOptions>.blocklyMenuDivDisabled,', + '.blocklyDropdownMenuOptions>.blocklyMenuDiv {', + ' fill: #fff;', + '}', + '.blocklyContextMenuOptions>.blocklyMenuDiv:hover>rect,', + '.blocklyDropdownMenuOptions>.blocklyMenuDiv:hover>rect {', + ' fill: #57e;', + '}', + '.blocklyMenuSelected>rect {', + ' fill: #57e;', + '}', + '.blocklyMenuText {', + ' cursor: default !important;', + ' font-family: sans-serif;', + ' font-size: 15px; /* All context menu sizes are based on pixels. */', + ' fill: #000;', + '}', + '.blocklyContextMenuOptions>.blocklyMenuDiv:hover>.blocklyMenuText,', + '.blocklyDropdownMenuOptions>.blocklyMenuDiv:hover>.blocklyMenuText {', + ' fill: #fff;', + '}', + '.blocklyMenuSelected>.blocklyMenuText {', + ' fill: #fff;', + '}', + '.blocklyMenuDivDisabled>.blocklyMenuText {', + ' fill: #ccc;', + '}', + '.blocklyFlyoutBackground {', + ' fill: #ddd;', + ' fill-opacity: 0.8;', + '}', + '.blocklyColourBackground {', + ' fill: #666;', + '}', + '.blocklyScrollbarBackground {', + ' fill: #fff;', + ' stroke-width: 1;', + ' stroke: #e4e4e4;', + '}', + '.blocklyScrollbarKnob {', + ' fill: #ccc;', + '}', + '.blocklyScrollbarBackground:hover+.blocklyScrollbarKnob,', + '.blocklyScrollbarKnob:hover {', + ' fill: #bbb;', + '}', + '.blocklyInvalidInput {', + ' background: #faa;', + '}', + '.blocklyAngleCircle {', + ' stroke: #444;', + ' stroke-width: 1;', + ' fill: #ddd;', + ' fill-opacity: 0.8;', + '}', + '.blocklyAngleMarks {', + ' stroke: #444;', + ' stroke-width: 1;', + '}', + '.blocklyAngleGuage {', + ' fill: #d00;', + ' fill-opacity: 0.8; ', + '}', + '', + '/* Category tree in Toolbox. */', + '.blocklyToolboxDiv {', + ' background-color: #ddd;', + ' display: none;', + ' overflow-x: visible;', + ' overflow-y: auto;', + ' position: absolute;', + '}', + '.blocklyTreeRoot {', + ' padding: 4px 0;', + '}', + '.blocklyTreeRoot:focus {', + ' outline: none;', + '}', + '.blocklyTreeRow {', + ' line-height: 22px;', + ' height: 22px;', + ' padding-right: 1em;', + ' white-space: nowrap;', + '}', + '.blocklyToolboxDiv[dir="RTL"] .blocklyTreeRow {', + ' padding-right: 0;', + ' padding-left: 1em !important;', + '}', + '.blocklyTreeRow:hover {', + ' background-color: #e4e4e4;', + '}', + '.blocklyTreeIcon {', + ' height: 16px;', + ' width: 16px;', + ' vertical-align: middle;', + ' background-image: url(<<>>/media/tree.png);', + '}', + '.blocklyTreeIconClosedLtr {', + ' background-position: -32px -1px;', + '}', + '.blocklyTreeIconClosedRtl {', + ' background-position: 0px -1px;', + '}', + '.blocklyTreeIconOpen {', + ' background-position: -16px -1px;', + '}', + '.blocklyTreeIconNone {', + ' background-position: -48px -1px;', + '}', + '.blocklyTreeSelected>.blocklyTreeIconClosedLtr {', + ' background-position: -32px -17px;', + '}', + '.blocklyTreeSelected>.blocklyTreeIconClosedRtl {', + ' background-position: 0px -17px;', + '}', + '.blocklyTreeSelected>.blocklyTreeIconOpen {', + ' background-position: -16px -17px;', + '}', + '.blocklyTreeSelected>.blocklyTreeIconNone {', + ' background-position: -48px -17px;', + '}', + '.blocklyTreeLabel {', + ' cursor: default;', + ' font-family: sans-serif;', + ' font-size: 16px;', + ' padding: 0 3px;', + ' vertical-align: middle;', + '}', + '.blocklyTreeSelected {', + ' background-color: #57e !important;', + '}', + '.blocklyTreeSelected .blocklyTreeLabel {', + ' color: #fff;', + '}', + '', + '/*', + ' * Copyright 2007 The Closure Library Authors. All Rights Reserved.', + ' *', + ' * Use of this source code is governed by the Apache License, Version 2.0.', + ' * See the COPYING file for details.', + ' */', + '', + '/* Author: pupius@google.com (Daniel Pupius) */', + '', + '/*', + ' Styles to make the colorpicker look like the old gmail color picker', + ' NOTE: without CSS scoping this will override styles defined in palette.css', + '*/', + '.goog-palette {', + ' outline: none;', + ' cursor: default;', + '}', + '', + '.goog-palette-table {', + ' border: 1px solid #666;', + ' border-collapse: collapse;', + '}', + '', + '.goog-palette-cell {', + ' height: 13px;', + ' width: 15px;', + ' margin: 0;', + ' border: 0;', + ' text-align: center;', + ' vertical-align: middle;', + ' border-right: 1px solid #666;', + ' font-size: 1px;', + '}', + '', + '.goog-palette-colorswatch {', + ' position: relative;', + ' height: 13px;', + ' width: 15px;', + ' border: 1px solid #666;', + '}', + '', + '.goog-palette-cell-hover .goog-palette-colorswatch {', + ' border: 1px solid #FFF;', + '}', + '', + '.goog-palette-cell-selected .goog-palette-colorswatch {', + ' border: 1px solid #000;', + ' color: #fff;', + '}', + '' +]; diff --git a/core/field.js b/core/field.js new file mode 100644 index 000000000..dfd2ebfa1 --- /dev/null +++ b/core/field.js @@ -0,0 +1,254 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Input field. Used for editable titles, variables, etc. + * This is an abstract class that defines the UI on the block. Actual + * instances would be Blockly.FieldTextInput, Blockly.FieldDropdown, etc. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Field'); + +// TODO(scr): Fix circular dependencies +// goog.require('Blockly.Block'); +goog.require('Blockly.BlockSvg'); + + +/** + * Class for an editable field. + * @param {string} text The initial content of the field. + * @constructor + */ +Blockly.Field = function(text) { + this.sourceBlock_ = null; + // Build the DOM. + this.fieldGroup_ = Blockly.createSvgElement('g', {}, null); + this.borderRect_ = Blockly.createSvgElement('rect', + {'rx': 4, + 'ry': 4, + 'x': -Blockly.BlockSvg.SEP_SPACE_X / 2, + 'y': -12, + 'height': 16}, this.fieldGroup_); + this.textElement_ = Blockly.createSvgElement('text', + {'class': 'blocklyText'}, this.fieldGroup_); + this.size_ = {height: 25, width: 0}; + this.setText(text); + this.visible_ = true; +}; + +/** + * Non-breaking space. + */ +Blockly.Field.NBSP = '\u00A0'; + +/** + * Editable fields are saved by the XML renderer, non-editable fields are not. + */ +Blockly.Field.prototype.EDITABLE = true; + +/** + * Install this field on a block. + * @param {!Blockly.Block} block The block containing this field. + */ +Blockly.Field.prototype.init = function(block) { + if (this.sourceBlock_) { + throw 'Field has already been initialized once.'; + } + this.sourceBlock_ = block; + this.updateEditable(); + block.getSvgRoot().appendChild(this.fieldGroup_); + this.mouseUpWrapper_ = + Blockly.bindEvent_(this.fieldGroup_, 'mouseup', this, this.onMouseUp_); + // Bump to set the colours for dropdown arrows. + this.setText(null); +}; + +/** + * Dispose of all DOM objects belonging to this editable field. + */ +Blockly.Field.prototype.dispose = function() { + if (this.mouseUpWrapper_) { + Blockly.unbindEvent_(this.mouseUpWrapper_); + this.mouseUpWrapper_ = null; + } + this.sourceBlock_ = null; + goog.dom.removeNode(this.fieldGroup_); + this.fieldGroup_ = null; + this.textElement_ = null; + this.borderRect_ = null; +}; + +/** + * Add or remove the UI indicating if this field is editable or not. + */ +Blockly.Field.prototype.updateEditable = function() { + if (!this.EDITABLE) { + return; + } + if (this.sourceBlock_.isEditable()) { + Blockly.addClass_(/** @type {!Element} */ (this.fieldGroup_), + 'blocklyEditableText'); + Blockly.removeClass_(/** @type {!Element} */ (this.fieldGroup_), + 'blocklyNoNEditableText'); + this.fieldGroup_.style.cursor = this.CURSOR; + } else { + Blockly.addClass_(/** @type {!Element} */ (this.fieldGroup_), + 'blocklyNonEditableText'); + Blockly.removeClass_(/** @type {!Element} */ (this.fieldGroup_), + 'blocklyEditableText'); + this.fieldGroup_.style.cursor = ''; + } +}; + +/** + * Gets whether this editable field is visible or not. + * @return {boolean} True if visible. + */ +Blockly.Field.prototype.isVisible = function() { + return this.visible_; +}; + +/** + * Sets whether this editable field is visible or not. + * @param {boolean} visible True if visible. + */ +Blockly.Field.prototype.setVisible = function(visible) { + this.visible_ = visible; + this.getRootElement().style.display = visible ? 'block' : 'none'; +}; + +/** + * Gets the group element for this editable field. + * Used for measuring the size and for positioning. + * @return {!Element} The group element. + */ +Blockly.Field.prototype.getRootElement = function() { + return /** @type {!Element} */ (this.fieldGroup_); +}; + +/** + * Draws the border with the correct width. + * Saves the computed width in a property. + * @private + */ +Blockly.Field.prototype.render_ = function() { + var width = this.textElement_.getComputedTextLength(); + if (this.borderRect_) { + this.borderRect_.setAttribute('width', + width + Blockly.BlockSvg.SEP_SPACE_X); + } + this.size_.width = width; +}; + +/** + * Returns the height and width of the title. + * @return {!Object} Height and width. + */ +Blockly.Field.prototype.getSize = function() { + if (!this.size_.width) { + this.render_(); + } + return this.size_; +}; + +/** + * Get the text from this field. + * @return {string} Current text. + */ +Blockly.Field.prototype.getText = function() { + return this.text_; +}; + +/** + * Set the text in this field. Trigger a rerender of the source block. + * @param {?string} text New text. + */ +Blockly.Field.prototype.setText = function(text) { + if (text === null || text === this.text_) { + // No change if null. + return; + } + this.text_ = text; + // Empty the text element. + goog.dom.removeChildren(/** @type {!Element} */ (this.textElement_)); + // Replace whitespace with non-breaking spaces so the text doesn't collapse. + text = text.replace(/\s/g, Blockly.Field.NBSP); + if (!text) { + // Prevent the field from disappearing if empty. + text = Blockly.Field.NBSP; + } + var textNode = document.createTextNode(text); + this.textElement_.appendChild(textNode); + + // Cached width is obsolete. Clear it. + this.size_.width = 0; + + if (this.sourceBlock_ && this.sourceBlock_.rendered) { + this.sourceBlock_.render(); + this.sourceBlock_.bumpNeighbours_(); + this.sourceBlock_.workspace.fireChangeEvent(); + } +}; + +/** + * By default there is no difference between the human-readable text and + * the language-neutral values. Subclasses (such as dropdown) may define this. + * @return {string} Current text. + */ +Blockly.Field.prototype.getValue = function() { + return this.getText(); +}; + +/** + * By default there is no difference between the human-readable text and + * the language-neutral values. Subclasses (such as dropdown) may define this. + * @param {string} text New text. + */ +Blockly.Field.prototype.setValue = function(text) { + this.setText(text); +}; + +/** + * Handle a mouse up event on an editable field. + * @param {!Event} e Mouse up event. + * @private + */ +Blockly.Field.prototype.onMouseUp_ = function(e) { + if (Blockly.isRightButton(e)) { + // Right-click. + return; + } else if (Blockly.Block.dragMode_ == 2) { + // Drag operation is concluding. Don't open the editor. + return; + } else if (this.sourceBlock_.isEditable()) { + // Non-abstract sub-classes must define a showEditor_ method. + this.showEditor_(); + } +}; + +/** + * Change the tooltip text for this field. + * @param {string|!Element} newTip Text for tooltip or a parent element to + * link to for its tooltip. + */ +Blockly.Field.prototype.setTooltip = function(newTip) { + // Non-abstract sub-classes may wish to implement this. See FieldLabel. +}; diff --git a/core/field_angle.js b/core/field_angle.js new file mode 100644 index 000000000..f35fab6fe --- /dev/null +++ b/core/field_angle.js @@ -0,0 +1,232 @@ +/** + * Visual Blocks Editor + * + * Copyright 2013 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Angle input field. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.FieldAngle'); + +goog.require('Blockly.FieldTextInput'); + + +/** + * Class for an editable angle field. + * @param {string} text The initial content of the field. + * @param {Function} opt_changeHandler An optional function that is called + * to validate any constraints on what the user entered. Takes the new + * text as an argument and returns the accepted text or null to abort + * the change. + * @extends {Blockly.Field} + * @constructor + */ +Blockly.FieldAngle = function(text, opt_changeHandler) { + var changeHandler; + if (opt_changeHandler) { + // Wrap the user's change handler together with the angle validator. + var thisObj = this; + changeHandler = function(value) { + value = Blockly.FieldAngle.angleValidator.call(thisObj, value); + if (value !== null) { + opt_changeHandler.call(thisObj, value); + } + return value; + }; + } else { + changeHandler = Blockly.FieldAngle.angleValidator; + } + + // Add degree symbol: "360°" (LTR) or "°360" (RTL) + this.symbol_ = Blockly.createSvgElement('tspan', {}, null); + this.symbol_.appendChild(document.createTextNode('\u00B0')); + + Blockly.FieldAngle.superClass_.constructor.call(this, + text, changeHandler); +}; +goog.inherits(Blockly.FieldAngle, Blockly.FieldTextInput); + +/** + * Half the width of protractor image. + */ +Blockly.FieldAngle.HALF = 100 / 2; + +/** + * Radius of protractor circle. Slightly smaller than protractor size since + * otherwise SVG crops off half the border at the edges. + */ +Blockly.FieldAngle.RADIUS = Blockly.FieldAngle.HALF - 1; + +/** + * Clean up this FieldAngle, as well as the inherited FieldTextInput. + * @return {!Function} Closure to call on destruction of the WidgetDiv. + * @private + */ +Blockly.FieldAngle.prototype.dispose_ = function() { + var thisField = this; + return function() { + Blockly.FieldAngle.superClass_.dispose_.call(thisField)(); + thisField.gauge_ = null; + if (thisField.clickWrapper_) { + Blockly.unbindEvent_(thisField.clickWrapper_); + } + if (thisField.moveWrapper1_) { + Blockly.unbindEvent_(thisField.moveWrapper1_); + } + if (thisField.moveWrapper2_) { + Blockly.unbindEvent_(thisField.moveWrapper2_); + } + }; +}; + +/** + * Show the inline free-text editor on top of the text. + * @private + */ +Blockly.FieldAngle.prototype.showEditor_ = function() { + Blockly.FieldAngle.superClass_.showEditor_.call(this); + var div = Blockly.WidgetDiv.DIV; + if (!div.firstChild) { + // Mobile interface uses window.prompt. + return; + } + // Build the SVG DOM. + var svg = Blockly.createSvgElement('svg', { + 'xmlns': 'http://www.w3.org/2000/svg', + 'xmlns:html': 'http://www.w3.org/1999/xhtml', + 'xmlns:xlink': 'http://www.w3.org/1999/xlink', + 'version': '1.1', + 'height': (Blockly.FieldAngle.HALF * 2) + 'px', + 'width': (Blockly.FieldAngle.HALF * 2) + 'px' + }, div); + var circle = Blockly.createSvgElement('circle', { + 'cx': Blockly.FieldAngle.HALF, 'cy': Blockly.FieldAngle.HALF, + 'r': Blockly.FieldAngle.RADIUS, + 'class': 'blocklyAngleCircle' + }, svg); + this.gauge_ = + Blockly.createSvgElement('path', {'class': 'blocklyAngleGuage'}, svg); + // Draw markers around the edge. + for (var a = 0; a < 360; a += 15) { + Blockly.createSvgElement('line', { + 'x1': Blockly.FieldAngle.HALF + Blockly.FieldAngle.RADIUS, + 'y1': Blockly.FieldAngle.HALF, + 'x2': Blockly.FieldAngle.HALF + Blockly.FieldAngle.RADIUS - + (a % 45 == 0 ? 10 : 5), + 'y2': Blockly.FieldAngle.HALF, + 'class': 'blocklyAngleMarks', + 'transform': 'rotate(' + a + ', ' + + Blockly.FieldAngle.HALF + ', ' + Blockly.FieldAngle.HALF + ')' + }, svg); + } + svg.style.marginLeft = '-35px'; + this.clickWrapper_ = + Blockly.bindEvent_(svg, 'click', this, Blockly.WidgetDiv.hide); + this.moveWrapper1_ = + Blockly.bindEvent_(circle, 'mousemove', this, this.onMouseMove); + this.moveWrapper2_ = + Blockly.bindEvent_(this.gauge_, 'mousemove', this, this.onMouseMove); + this.updateGraph(); +}; + +/** + * Set the angle to match the mouse's position. + * @param {!Event} e Mouse move event. + */ +Blockly.FieldAngle.prototype.onMouseMove = function(e) { + var bBox = this.gauge_.ownerSVGElement.getBoundingClientRect(); + var dx = e.clientX - bBox.left - Blockly.FieldAngle.HALF; + var dy = e.clientY - bBox.top - Blockly.FieldAngle.HALF; + var angle = Math.atan(-dy / dx); + if (isNaN(angle)) { + // This shouldn't happen, but let's not let this error propogate further. + return; + } + angle = angle / Math.PI * 180; + // 0: East, 90: North, 180: West, 270: South. + if (dx < 0) { + angle += 180; + } else if (dy > 0) { + angle += 360; + } + angle = String(Math.round(angle)); + Blockly.FieldTextInput.htmlInput_.value = angle; + this.setText(angle); +}; + +/** + * Insert a degree symbol. + * @param {?string} text New text. + */ +Blockly.FieldAngle.prototype.setText = function(text) { + Blockly.FieldAngle.superClass_.setText.call(this, text); + this.updateGraph(); + // Insert degree symbol. + if (Blockly.RTL) { + this.textElement_.insertBefore(this.symbol_, this.textElement_.firstChild); + } else { + this.textElement_.appendChild(this.symbol_); + } + // Cached width is obsolete. Clear it. + this.size_.width = 0; +}; + +/** + * Ensure that only an angle may be entered. + * @param {string} text The user's text. + * @return {?string} A string representing a valid angle, or null if invalid. + */ +Blockly.FieldAngle.prototype.updateGraph = function() { + if (this.gauge_) { + var angleRadians = Number(this.getText()) / 180 * Math.PI; + if (isNaN(angleRadians)) { + this.gauge_.setAttribute('d', + 'M ' + Blockly.FieldAngle.HALF + ', ' + Blockly.FieldAngle.HALF); + } else { + var x = Blockly.FieldAngle.HALF + Math.cos(angleRadians) * + Blockly.FieldAngle.RADIUS; + var y = Blockly.FieldAngle.HALF + Math.sin(angleRadians) * + -Blockly.FieldAngle.RADIUS; + var largeFlag = (angleRadians > Math.PI) ? 1 : 0; + this.gauge_.setAttribute('d', + 'M ' + Blockly.FieldAngle.HALF + ', ' + Blockly.FieldAngle.HALF + + ' h ' + Blockly.FieldAngle.RADIUS + + ' A ' + Blockly.FieldAngle.RADIUS + ',' + Blockly.FieldAngle.RADIUS + + ' 0 ' + largeFlag + ' 0 ' + x + ',' + y + ' z'); + } + } +}; + +/** + * Ensure that only an angle may be entered. + * @param {string} text The user's text. + * @return {?string} A string representing a valid angle, or null if invalid. + */ +Blockly.FieldAngle.angleValidator = function(text) { + var n = Blockly.FieldTextInput.numberValidator(text); + if (n !== null) { + n = n % 360; + if (n < 0) { + n += 360; + } + n = String(n); + } + return n; +}; diff --git a/core/field_checkbox.js b/core/field_checkbox.js new file mode 100644 index 000000000..e0f8ecf55 --- /dev/null +++ b/core/field_checkbox.js @@ -0,0 +1,98 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Checkbox field. Checked or not checked. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.FieldCheckbox'); + +goog.require('Blockly.Field'); + + +/** + * Class for a checkbox field. + * @param {string} state The initial state of the field ('TRUE' or 'FALSE'). + * @param {Function} opt_changeHandler A function that is executed when a new + * option is selected. + * @extends {Blockly.Field} + * @constructor + */ +Blockly.FieldCheckbox = function(state, opt_changeHandler) { + Blockly.FieldCheckbox.superClass_.constructor.call(this, ''); + + this.changeHandler_ = opt_changeHandler; + // The checkbox doesn't use the inherited text element. + // Instead it uses a custom checkmark element that is either visible or not. + this.checkElement_ = Blockly.createSvgElement('text', + {'class': 'blocklyText', 'x': -3}, this.fieldGroup_); + var textNode = document.createTextNode('\u2713'); + this.checkElement_.appendChild(textNode); + // Set the initial state. + this.setValue(state); +}; +goog.inherits(Blockly.FieldCheckbox, Blockly.Field); + +/** + * Mouse cursor style when over the hotspot that initiates editability. + */ +Blockly.FieldCheckbox.prototype.CURSOR = 'default'; + +/** + * Return 'TRUE' if the checkbox is checked, 'FALSE' otherwise. + * @return {string} Current state. + */ +Blockly.FieldCheckbox.prototype.getValue = function() { + return String(this.state_).toUpperCase(); +}; + +/** + * Set the checkbox to be checked if strBool is 'TRUE', unchecks otherwise. + * @param {string} strBool New state. + */ +Blockly.FieldCheckbox.prototype.setValue = function(strBool) { + var newState = (strBool == 'TRUE'); + if (this.state_ !== newState) { + this.state_ = newState; + this.checkElement_.style.display = newState ? 'block' : 'none'; + if (this.sourceBlock_ && this.sourceBlock_.rendered) { + this.sourceBlock_.workspace.fireChangeEvent(); + } + } +}; + +/** + * Toggle the state of the checkbox. + * @private + */ +Blockly.FieldCheckbox.prototype.showEditor_ = function() { + var newState = !this.state_; + if (this.changeHandler_) { + // Call any change handler, and allow it to override. + var override = this.changeHandler_(newState); + if (override !== undefined) { + newState = override; + } + } + if (newState !== null) { + this.setValue(String(newState).toUpperCase()); + } +}; diff --git a/core/field_colour.js b/core/field_colour.js new file mode 100644 index 000000000..f2e31b9bb --- /dev/null +++ b/core/field_colour.js @@ -0,0 +1,151 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Colour input field. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.FieldColour'); + +goog.require('Blockly.Field'); +goog.require('goog.ui.ColorPicker'); + + +/** + * Class for a colour input field. + * @param {string} colour The initial colour in '#rrggbb' format. + * @param {Function} opt_changeHandler A function that is executed when a new + * option is selected. + * @extends {Blockly.Field} + * @constructor + */ +Blockly.FieldColour = function(colour, opt_changeHandler) { + Blockly.FieldColour.superClass_.constructor.call(this, '\u00A0\u00A0\u00A0'); + + this.changeHandler_ = opt_changeHandler; + this.borderRect_.style.fillOpacity = 1; + // Set the initial state. + this.setValue(colour); +}; +goog.inherits(Blockly.FieldColour, Blockly.Field); + +/** + * Mouse cursor style when over the hotspot that initiates the editor. + */ +Blockly.FieldColour.prototype.CURSOR = 'default'; + +/** + * Dispose of all DOM objects belonging to this editable field. + */ +Blockly.FieldColour.prototype.dispose = function() { + Blockly.WidgetDiv.hideIfField(this); + Blockly.FieldColour.superClass_.dispose.call(this); +}; + +/** + * Return the current colour. + * @return {string} Current colour in '#rrggbb' format. + */ +Blockly.FieldColour.prototype.getValue = function() { + return this.colour_; +}; + +/** + * Set the colour. + * @param {string} colour The new colour in '#rrggbb' format. + */ +Blockly.FieldColour.prototype.setValue = function(colour) { + this.colour_ = colour; + this.borderRect_.style.fill = colour; + if (this.sourceBlock_ && this.sourceBlock_.rendered) { + this.sourceBlock_.workspace.fireChangeEvent(); + } +}; + +/** + * An array of colour strings for the palette. + * See bottom of this page for the default: + * http://docs.closure-library.googlecode.com/git/closure_goog_ui_colorpicker.js.source.html + * @type {!Array.} + */ +Blockly.FieldColour.COLOURS = goog.ui.ColorPicker.SIMPLE_GRID_COLORS; + +/** + * Number of columns in the palette. + */ +Blockly.FieldColour.COLUMNS = 7; + +/** + * Create a palette under the colour field. + * @private + */ +Blockly.FieldColour.prototype.showEditor_ = function() { + Blockly.WidgetDiv.show(this, Blockly.FieldColour.dispose_); + var div = Blockly.WidgetDiv.DIV; + // Create the palette using Closure. + var picker = new goog.ui.ColorPicker(); + picker.setSize(Blockly.FieldColour.COLUMNS); + picker.setColors(Blockly.FieldColour.COLOURS); + picker.render(div); + picker.setSelectedColor(this.getValue()); + + // Position the palette to line up with the field. + var xy = Blockly.getAbsoluteXY_(/** @type {!Element} */ (this.borderRect_)); + var borderBBox = this.borderRect_.getBBox(); + if (Blockly.RTL) { + xy.x += borderBBox.width; + } + xy.y += borderBBox.height - 1; + if (Blockly.RTL) { + xy.x -= div.offsetWidth; + } + div.style.left = xy.x + 'px'; + div.style.top = xy.y + 'px'; + + // Configure event handler. + var thisObj = this; + Blockly.FieldColour.changeEventKey_ = goog.events.listen(picker, + goog.ui.ColorPicker.EventType.CHANGE, + function(event) { + var colour = event.target.getSelectedColor() || '#000000'; + Blockly.WidgetDiv.hide(); + if (thisObj.changeHandler_) { + // Call any change handler, and allow it to override. + var override = thisObj.changeHandler_(colour); + if (override !== undefined) { + colour = override; + } + } + if (colour !== null) { + thisObj.setValue(colour); + } + }); +}; + +/** + * Hide the colour palette. + * @private + */ +Blockly.FieldColour.dispose_ = function() { + if (Blockly.FieldColour.changeEventKey_) { + goog.events.unlistenByKey(Blockly.FieldColour.changeEventKey_); + } +}; diff --git a/core/field_dropdown.js b/core/field_dropdown.js new file mode 100644 index 000000000..351c77a5c --- /dev/null +++ b/core/field_dropdown.js @@ -0,0 +1,357 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Dropdown input field. Used for editable titles and variables. + * In the interests of a consistent UI, the toolbox shares some functions and + * properties with the context menu. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.FieldDropdown'); + +goog.require('Blockly.Field'); + + +/** + * Class for an editable dropdown field. + * @param {(!Array.|!Function)} menuGenerator An array of options + * for a dropdown list, or a function which generates these options. + * @param {Function} opt_changeHandler A function that is executed when a new + * option is selected. + * @extends {Blockly.Field} + * @constructor + */ +Blockly.FieldDropdown = function(menuGenerator, opt_changeHandler) { + this.menuGenerator_ = menuGenerator; + this.changeHandler_ = opt_changeHandler; + this.trimOptions_(); + var firstTuple = this.getOptions_()[0]; + this.value_ = firstTuple[1]; + + // Add dropdown arrow: "option ▾" (LTR) or "▾ אופציה" (RTL) + this.arrow_ = Blockly.createSvgElement('tspan', {}, null); + this.arrow_.appendChild(document.createTextNode( + Blockly.RTL ? '\u25BE ' : ' \u25BE')); + + // Call parent's constructor. + Blockly.FieldDropdown.superClass_.constructor.call(this, firstTuple[0]); +}; +goog.inherits(Blockly.FieldDropdown, Blockly.Field); + +/** + * Create the dropdown field's elements. Only needs to be called once. + * @return {!Element} The field's SVG group. + */ +Blockly.FieldDropdown.createDom = function() { + /* + + + + + + + */ + var svgGroup = Blockly.createSvgElement('g', + {'class': 'blocklyHidden blocklyFieldDropdown'}, null); + Blockly.FieldDropdown.svgGroup_ = svgGroup; + Blockly.FieldDropdown.svgShadow_ = Blockly.createSvgElement('rect', + {'class': 'blocklyDropdownMenuShadow', + 'x': 0, 'y': 1, 'rx': 2, 'ry': 2}, svgGroup); + Blockly.FieldDropdown.svgBackground_ = Blockly.createSvgElement('rect', + {'x': -2, 'y': -1, 'rx': 2, 'ry': 2, + 'filter': 'url(#blocklyEmboss)'}, svgGroup); + Blockly.FieldDropdown.svgOptions_ = Blockly.createSvgElement('g', + {'class': 'blocklyDropdownMenuOptions'}, svgGroup); + return svgGroup; +}; + +/** + * Close the dropdown and dispose of all UI. + */ +Blockly.FieldDropdown.prototype.dispose = function() { + if (Blockly.FieldDropdown.openDropdown_ == this) { + Blockly.FieldDropdown.hide(); + } + // Call parent's destructor. + Blockly.Field.prototype.dispose.call(this); +}; + +/** + * Corner radius of the dropdown background. + */ +Blockly.FieldDropdown.CORNER_RADIUS = 2; + +/** + * Mouse cursor style when over the hotspot that initiates the editor. + */ +Blockly.FieldDropdown.prototype.CURSOR = 'default'; + +/** + * Which block is the dropdown attached to? + * @type {Blockly.FieldDropdown} + * @private + */ +Blockly.FieldDropdown.openDropdown_ = null; + +/** + * Create a dropdown menu under the text. + * @private + */ +Blockly.FieldDropdown.prototype.showEditor_ = function() { + var svgGroup = Blockly.FieldDropdown.svgGroup_; + var svgOptions = Blockly.FieldDropdown.svgOptions_; + var svgBackground = Blockly.FieldDropdown.svgBackground_; + var svgShadow = Blockly.FieldDropdown.svgShadow_; + // Erase all existing options. + goog.dom.removeChildren(svgOptions); + // The menu must be made visible early since otherwise BBox and + // getComputedTextLength will return 0. + Blockly.removeClass_(svgGroup, 'blocklyHidden'); + Blockly.FieldDropdown.openDropdown_ = this; + + function callbackFactory(value) { + return function(e) { + if (this.changeHandler_) { + // Call any change handler, and allow it to override. + var override = this.changeHandler_(value); + if (override !== undefined) { + value = override; + } + } + if (value !== null) { + this.setValue(value); + } + // This mouse click has been handled, don't bubble up to document. + e.stopPropagation(); + }; + } + + var maxWidth = 0; + var resizeList = []; + var checkElement = null; + var options = this.getOptions_(); + for (var x = 0; x < options.length; x++) { + var text = options[x][0]; // Human-readable text. + var value = options[x][1]; // Language-neutral value. + var gElement = Blockly.ContextMenu.optionToDom(text); + var rectElement = /** @type {SVGRectElement} */ (gElement.firstChild); + var textElement = /** @type {SVGTextElement} */ (gElement.lastChild); + svgOptions.appendChild(gElement); + // Add a checkmark next to the current item. + if (!checkElement && value == this.value_) { + checkElement = Blockly.createSvgElement('text', + {'class': 'blocklyMenuText', 'y': 15}, null); + // Insert the checkmark between the rect and text, thus preserving the + // ability to reference them as firstChild and lastChild respectively. + gElement.insertBefore(checkElement, textElement); + checkElement.appendChild(document.createTextNode('\u2713')); + } + + gElement.setAttribute('transform', + 'translate(0, ' + (x * Blockly.ContextMenu.Y_HEIGHT) + ')'); + resizeList.push(rectElement); + Blockly.bindEvent_(gElement, 'mousedown', null, Blockly.noEvent); + Blockly.bindEvent_(gElement, 'mouseup', this, callbackFactory(value)); + Blockly.bindEvent_(gElement, 'mouseup', null, + Blockly.FieldDropdown.hide); + // Compute the length of the longest text length. + maxWidth = Math.max(maxWidth, textElement.getComputedTextLength()); + } + // Run a second pass to resize all options to the required width. + maxWidth += Blockly.ContextMenu.X_PADDING * 2; + for (var x = 0; x < resizeList.length; x++) { + resizeList[x].setAttribute('width', maxWidth); + } + if (Blockly.RTL) { + // Right-align the text. + for (var x = 0, gElement; gElement = svgOptions.childNodes[x]; x++) { + var textElement = gElement.lastChild; + textElement.setAttribute('text-anchor', 'end'); + textElement.setAttribute('x', maxWidth - Blockly.ContextMenu.X_PADDING); + } + } + if (checkElement) { + if (Blockly.RTL) { + // Research indicates that RTL checkmarks are supposed to be drawn the + // same in the same direction as LTR checkmarks. It's only the alignment + // that needs to change. + checkElement.setAttribute('text-anchor', 'end'); + checkElement.setAttribute('x', maxWidth - 5); + } else { + checkElement.setAttribute('x', 5); + } + } + var width = maxWidth + Blockly.FieldDropdown.CORNER_RADIUS * 2; + var height = options.length * Blockly.ContextMenu.Y_HEIGHT + + Blockly.FieldDropdown.CORNER_RADIUS + 1; + svgShadow.setAttribute('width', width); + svgShadow.setAttribute('height', height); + svgBackground.setAttribute('width', width); + svgBackground.setAttribute('height', height); + var hexColour = Blockly.makeColour(this.sourceBlock_.getColour()); + svgBackground.setAttribute('fill', hexColour); + // Position the dropdown to line up with the field. + var xy = Blockly.getSvgXY_(/** @type {!Element} */ (this.borderRect_)); + var borderBBox = this.borderRect_.getBBox(); + var x; + if (Blockly.RTL) { + x = xy.x - maxWidth + Blockly.ContextMenu.X_PADDING + borderBBox.width - + Blockly.BlockSvg.SEP_SPACE_X / 2; + } else { + x = xy.x - Blockly.ContextMenu.X_PADDING + Blockly.BlockSvg.SEP_SPACE_X / 2; + } + svgGroup.setAttribute('transform', + 'translate(' + x + ', ' + (xy.y + borderBBox.height) + ')'); +}; + +/** + * Factor out common words in statically defined options. + * Create prefix and/or suffix labels. + * @private + */ +Blockly.FieldDropdown.prototype.trimOptions_ = function() { + this.prefixTitle = null; + this.suffixTitle = null; + var options = this.menuGenerator_; + if (!goog.isArray(options) || options.length < 2) { + return; + } + var strings = options.map(function(t) {return t[0];}); + var shortest = Blockly.shortestStringLength(strings); + var prefixLength = Blockly.commonWordPrefix(strings, shortest); + var suffixLength = Blockly.commonWordSuffix(strings, shortest); + if (!prefixLength && !suffixLength) { + return; + } + if (shortest <= prefixLength + suffixLength) { + // One or more strings will entirely vanish if we proceed. Abort. + return; + } + if (prefixLength) { + this.prefixTitle = strings[0].substring(0, prefixLength - 1); + } + if (suffixLength) { + this.suffixTitle = strings[0].substr(1 - suffixLength); + } + // Remove the prefix and suffix from the options. + var newOptions = []; + for (var x = 0; x < options.length; x++) { + var text = options[x][0]; + var value = options[x][1]; + text = text.substring(prefixLength, text.length - suffixLength); + newOptions[x] = [text, value]; + } + this.menuGenerator_ = newOptions; +}; + +/** + * Return a list of the options for this dropdown. + * @return {!Array.>} Array of option tuples: + * (human-readable text, language-neutral name). + * @private + */ +Blockly.FieldDropdown.prototype.getOptions_ = function() { + if (goog.isFunction(this.menuGenerator_)) { + return this.menuGenerator_.call(this); + } + return /** @type {!Array.>} */ (this.menuGenerator_); +}; + +/** + * Get the language-neutral value from this dropdown menu. + * @return {string} Current text. + */ +Blockly.FieldDropdown.prototype.getValue = function() { + return this.value_; +}; + +/** + * Set the language-neutral value for this dropdown menu. + * @param {string} newValue New value to set. + */ +Blockly.FieldDropdown.prototype.setValue = function(newValue) { + this.value_ = newValue; + // Look up and display the human-readable text. + var options = this.getOptions_(); + for (var x = 0; x < options.length; x++) { + // Options are tuples of human-readable text and language-neutral values. + if (options[x][1] == newValue) { + this.setText(options[x][0]); + return; + } + } + // Value not found. Add it, maybe it will become valid once set + // (like variable names). + this.setText(newValue); +}; + +/** + * Set the text in this field. Trigger a rerender of the source block. + * @param {?string} text New text. + */ +Blockly.FieldDropdown.prototype.setText = function(text) { + if (this.sourceBlock_) { + // Update arrow's colour. + this.arrow_.style.fill = Blockly.makeColour(this.sourceBlock_.getColour()); + } + if (text === null) { + // No change if null. + return; + } + this.text_ = text; + // Empty the text element. + goog.dom.removeChildren(/** @type {!Element} */ (this.textElement_)); + // Replace whitespace with non-breaking spaces so the text doesn't collapse. + text = text.replace(/\s/g, Blockly.Field.NBSP); + if (!text) { + // Prevent the field from disappearing if empty. + text = Blockly.Field.NBSP; + } + var textNode = document.createTextNode(text); + this.textElement_.appendChild(textNode); + + // Insert dropdown arrow. + if (Blockly.RTL) { + this.textElement_.insertBefore(this.arrow_, this.textElement_.firstChild); + } else { + this.textElement_.appendChild(this.arrow_); + } + + // Cached width is obsolete. Clear it. + this.size_.width = 0; + + if (this.sourceBlock_ && this.sourceBlock_.rendered) { + this.sourceBlock_.render(); + this.sourceBlock_.bumpNeighbours_(); + this.sourceBlock_.workspace.fireChangeEvent(); + } +}; + +/** + * Hide the dropdown menu. + */ +Blockly.FieldDropdown.hide = function() { + var svgGroup = Blockly.FieldDropdown.svgGroup_; + if (svgGroup) { + Blockly.addClass_(svgGroup, 'blocklyHidden'); + } + Blockly.FieldDropdown.openDropdown_ = null; +}; diff --git a/core/field_image.js b/core/field_image.js new file mode 100644 index 000000000..dd9f4e949 --- /dev/null +++ b/core/field_image.js @@ -0,0 +1,137 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Image field. Used for titles, labels, etc. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.FieldImage'); + +goog.require('Blockly.Field'); +goog.require('goog.userAgent'); + + +/** + * Class for an image. + * @param {string} src The URL of the image. + * @param {number} width Width of the image. + * @param {number} height Height of the image. + * @extends {Blockly.Field} + * @constructor + */ +Blockly.FieldImage = function(src, width, height) { + this.sourceBlock_ = null; + // Ensure height and width are numbers. Strings are bad at math. + height = Number(height); + width = Number(width); + this.size_ = {height: height + 10, width: width}; + // Build the DOM. + var offsetY = 6 - Blockly.BlockSvg.TITLE_HEIGHT; + this.fieldGroup_ = Blockly.createSvgElement('g', {}, null); + this.imageElement_ = Blockly.createSvgElement('image', + {'height': height + 'px', + 'width': width + 'px', + 'y': offsetY}, this.fieldGroup_); + this.setText(src); + if (goog.userAgent.GECKO) { + // Due to a Firefox bug which eats mouse events on image elements, + // a transparent rectangle needs to be placed on top of the image. + this.rectElement_ = Blockly.createSvgElement('rect', + {'height': height + 'px', + 'width': width + 'px', + 'y': offsetY, + 'fill-opacity': 0}, this.fieldGroup_); + } +}; +goog.inherits(Blockly.FieldImage, Blockly.Field); + +/** + * Rectangular mask used by Firefox. + * @type {Element} + * @private + */ +Blockly.FieldImage.prototype.rectElement_ = null; + +/** + * Editable fields are saved by the XML renderer, non-editable fields are not. + */ +Blockly.FieldImage.prototype.EDITABLE = false; + +/** + * Install this text on a block. + * @param {!Blockly.Block} block The block containing this text. + */ +Blockly.FieldImage.prototype.init = function(block) { + if (this.sourceBlock_) { + throw 'Image has already been initialized once.'; + } + this.sourceBlock_ = block; + block.getSvgRoot().appendChild(this.fieldGroup_); + + // Configure the field to be transparent with respect to tooltips. + var topElement = this.rectElement_ || this.imageElement_; + topElement.tooltip = this.sourceBlock_; + Blockly.Tooltip && Blockly.Tooltip.bindMouseEvents(topElement); +}; + +/** + * Dispose of all DOM objects belonging to this text. + */ +Blockly.FieldImage.prototype.dispose = function() { + goog.dom.removeNode(this.fieldGroup_); + this.fieldGroup_ = null; + this.imageElement_ = null; + this.rectElement_ = null; +}; + +/** + * Change the tooltip text for this field. + * @param {string|!Element} newTip Text for tooltip or a parent element to + * link to for its tooltip. + */ +Blockly.FieldImage.prototype.setTooltip = function(newTip) { + var topElement = this.rectElement_ || this.imageElement_; + topElement.tooltip = newTip; +}; + +/** + * Get the source URL of this image. + * @return {string} Current text. + * @override + */ +Blockly.FieldImage.prototype.getText = function() { + return this.src_; +}; + +/** + * Set the source URL of this image. + * @param {?string} src New source. + * @override + */ +Blockly.FieldImage.prototype.setText = function(src) { + if (src === null) { + // No change if null. + return; + } + this.src_ = src; + this.imageElement_.setAttributeNS('http://www.w3.org/1999/xlink', + 'xlink:href', goog.isString(src) ? src : ''); +}; diff --git a/core/field_label.js b/core/field_label.js new file mode 100644 index 000000000..80de3c1b7 --- /dev/null +++ b/core/field_label.js @@ -0,0 +1,93 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Non-editable text field. Used for titles, labels, etc. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.FieldLabel'); + +goog.require('Blockly.Field'); +goog.require('Blockly.Tooltip'); + + +/** + * Class for a non-editable field. + * @param {string} text The initial content of the field. + * @extends {Blockly.Field} + * @constructor + */ +Blockly.FieldLabel = function(text) { + this.sourceBlock_ = null; + // Build the DOM. + this.textElement_ = Blockly.createSvgElement('text', + {'class': 'blocklyText'}, null); + this.size_ = {height: 25, width: 0}; + this.setText(text); +}; +goog.inherits(Blockly.FieldLabel, Blockly.Field); + +/** + * Editable fields are saved by the XML renderer, non-editable fields are not. + */ +Blockly.FieldLabel.prototype.EDITABLE = false; + +/** + * Install this text on a block. + * @param {!Blockly.Block} block The block containing this text. + */ +Blockly.FieldLabel.prototype.init = function(block) { + if (this.sourceBlock_) { + throw 'Text has already been initialized once.'; + } + this.sourceBlock_ = block; + block.getSvgRoot().appendChild(this.textElement_); + + // Configure the field to be transparent with respect to tooltips. + this.textElement_.tooltip = this.sourceBlock_; + Blockly.Tooltip && Blockly.Tooltip.bindMouseEvents(this.textElement_); +}; + +/** + * Dispose of all DOM objects belonging to this text. + */ +Blockly.FieldLabel.prototype.dispose = function() { + goog.dom.removeNode(this.textElement_); + this.textElement_ = null; +}; + +/** + * Gets the group element for this field. + * Used for measuring the size and for positioning. + * @return {!Element} The group element. + */ +Blockly.FieldLabel.prototype.getRootElement = function() { + return /** @type {!Element} */ (this.textElement_); +}; + +/** + * Change the tooltip text for this field. + * @param {string|!Element} newTip Text for tooltip or a parent element to + * link to for its tooltip. + */ +Blockly.FieldLabel.prototype.setTooltip = function(newTip) { + this.textElement_.tooltip = newTip; +}; diff --git a/core/field_textinput.js b/core/field_textinput.js new file mode 100644 index 000000000..a5e717974 --- /dev/null +++ b/core/field_textinput.js @@ -0,0 +1,259 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Text input field. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.FieldTextInput'); + +goog.require('Blockly.Field'); +goog.require('Blockly.Msg'); +goog.require('goog.asserts'); +goog.require('goog.userAgent'); + + +/** + * Class for an editable text field. + * @param {string} text The initial content of the field. + * @param {Function} opt_changeHandler An optional function that is called + * to validate any constraints on what the user entered. Takes the new + * text as an argument and returns the accepted text or null to abort + * the change. + * @extends {Blockly.Field} + * @constructor + */ +Blockly.FieldTextInput = function(text, opt_changeHandler) { + Blockly.FieldTextInput.superClass_.constructor.call(this, text); + + this.changeHandler_ = opt_changeHandler; +}; +goog.inherits(Blockly.FieldTextInput, Blockly.Field); + +/** + * Mouse cursor style when over the hotspot that initiates the editor. + */ +Blockly.FieldTextInput.prototype.CURSOR = 'text'; + +/** + * Dispose of all DOM objects belonging to this editable field. + */ +Blockly.FieldTextInput.prototype.dispose = function() { + Blockly.WidgetDiv.hideIfField(this); + Blockly.FieldTextInput.superClass_.dispose.call(this); +}; + +/** + * Set the text in this field. + * @param {?string} text New text. + * @override + */ +Blockly.FieldTextInput.prototype.setText = function(text) { + if (text === null) { + // No change if null. + return; + } + if (this.changeHandler_) { + var validated = this.changeHandler_(text); + // If the new text is invalid, validation returns null. + // In this case we still want to display the illegal result. + if (validated !== null && validated !== undefined) { + text = validated; + } + } + Blockly.Field.prototype.setText.call(this, text); +}; + +/** + * Show the inline free-text editor on top of the text. + * @private + */ +Blockly.FieldTextInput.prototype.showEditor_ = function() { + if (goog.userAgent.MOBILE) { + // Mobile browsers have issues with in-line textareas (focus & keyboards). + var newValue = window.prompt(Blockly.Msg.CHANGE_VALUE_TITLE, this.text_); + if (this.changeHandler_) { + var override = this.changeHandler_(newValue); + if (override !== undefined) { + newValue = override; + } + } + if (newValue !== null) { + this.setText(newValue); + } + return; + } + + Blockly.WidgetDiv.show(this, this.dispose_()); + var div = Blockly.WidgetDiv.DIV; + // Create the input. + var htmlInput = goog.dom.createDom('input', 'blocklyHtmlInput'); + Blockly.FieldTextInput.htmlInput_ = htmlInput; + div.appendChild(htmlInput); + + htmlInput.value = htmlInput.defaultValue = this.text_; + htmlInput.oldValue_ = null; + this.validate_(); + this.resizeEditor_(); + htmlInput.focus(); + htmlInput.select(); + + // Bind to keyup -- trap Enter and Esc; resize after every keystroke. + htmlInput.onKeyUpWrapper_ = + Blockly.bindEvent_(htmlInput, 'keyup', this, this.onHtmlInputChange_); + // Bind to keyPress -- repeatedly resize when holding down a key. + htmlInput.onKeyPressWrapper_ = + Blockly.bindEvent_(htmlInput, 'keypress', this, this.onHtmlInputChange_); + var workspaceSvg = this.sourceBlock_.workspace.getCanvas(); + htmlInput.onWorkspaceChangeWrapper_ = + Blockly.bindEvent_(workspaceSvg, 'blocklyWorkspaceChange', this, + this.resizeEditor_); +}; + +/** + * Handle a change to the editor. + * @param {!Event} e Keyboard event. + * @private + */ +Blockly.FieldTextInput.prototype.onHtmlInputChange_ = function(e) { + var htmlInput = Blockly.FieldTextInput.htmlInput_; + if (e.keyCode == 13) { + // Enter + Blockly.WidgetDiv.hide(); + } else if (e.keyCode == 27) { + // Esc + this.setText(htmlInput.defaultValue); + Blockly.WidgetDiv.hide(); + } else { + // Update source block. + var text = htmlInput.value; + if (text !== htmlInput.oldValue_) { + htmlInput.oldValue_ = text; + this.setText(text); + this.validate_(); + } else if (goog.userAgent.WEBKIT) { + // Cursor key. Render the source block to show the caret moving. + // Chrome only (version 26, OS X). + this.sourceBlock_.render(); + } + } +}; + +/** + * Check to see if the contents of the editor validates. + * Style the editor accordingly. + * @private + */ +Blockly.FieldTextInput.prototype.validate_ = function() { + var valid = true; + goog.asserts.assertObject(Blockly.FieldTextInput.htmlInput_); + var htmlInput = /** @type {!Element} */ (Blockly.FieldTextInput.htmlInput_); + if (this.changeHandler_) { + valid = this.changeHandler_(htmlInput.value); + } + if (valid === null) { + Blockly.addClass_(htmlInput, 'blocklyInvalidInput'); + } else { + Blockly.removeClass_(htmlInput, 'blocklyInvalidInput'); + } +}; + +/** + * Resize the editor and the underlying block to fit the text. + * @private + */ +Blockly.FieldTextInput.prototype.resizeEditor_ = function() { + var div = Blockly.WidgetDiv.DIV; + var bBox = this.fieldGroup_.getBBox(); + div.style.width = bBox.width + 'px'; + var xy = Blockly.getAbsoluteXY_(/** @type {!Element} */ (this.borderRect_)); + // In RTL mode block titles and LTR input titles the left edge moves, + // whereas the right edge is fixed. Reposition the editor. + if (Blockly.RTL) { + var borderBBox = this.borderRect_.getBBox(); + xy.x += borderBBox.width; + xy.x -= div.offsetWidth; + } + // Shift by a few pixels to line up exactly. + xy.y += 1; + if (goog.userAgent.WEBKIT) { + xy.y -= 3; + } + div.style.left = xy.x + 'px'; + div.style.top = xy.y + 'px'; +}; + +/** + * Close the editor, save the results, and dispose of the editable + * text field's elements. + * @return {!Function} Closure to call on destruction of the WidgetDiv. + * @private + */ +Blockly.FieldTextInput.prototype.dispose_ = function() { + var thisField = this; + return function() { + var htmlInput = Blockly.FieldTextInput.htmlInput_; + var text; + // Save the edit (if it validates). + text = htmlInput.value; + if (thisField.changeHandler_) { + text = thisField.changeHandler_(text); + if (text === null) { + // Invalid edit. + text = htmlInput.defaultValue; + } + } + thisField.setText(text); + thisField.sourceBlock_.render(); + Blockly.unbindEvent_(htmlInput.onKeyUpWrapper_); + Blockly.unbindEvent_(htmlInput.onKeyPressWrapper_); + Blockly.unbindEvent_(htmlInput.onWorkspaceChangeWrapper_); + Blockly.FieldTextInput.htmlInput_ = null; + }; +}; + +/** + * Ensure that only a number may be entered. + * @param {string} text The user's text. + * @return {?string} A string representing a valid number, or null if invalid. + */ +Blockly.FieldTextInput.numberValidator = function(text) { + // TODO: Handle cases like 'ten', '1.203,14', etc. + // 'O' is sometimes mistaken for '0' by inexperienced users. + text = text.replace(/O/ig, '0'); + // Strip out thousands separators. + text = text.replace(/,/g, ''); + var n = parseFloat(text || 0); + return isNaN(n) ? null : String(n); +}; + +/** + * Ensure that only a nonnegative integer may be entered. + * @param {string} text The user's text. + * @return {?string} A string representing a valid int, or null if invalid. + */ +Blockly.FieldTextInput.nonnegativeIntegerValidator = function(text) { + var n = Blockly.FieldTextInput.numberValidator(text); + if (n) { + n = String(Math.max(0, Math.floor(n))); + } + return n; +}; diff --git a/core/field_variable.js b/core/field_variable.js new file mode 100644 index 000000000..e503d29b5 --- /dev/null +++ b/core/field_variable.js @@ -0,0 +1,156 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Variable input field. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.FieldVariable'); + +goog.require('Blockly.FieldDropdown'); +goog.require('Blockly.Msg'); +goog.require('Blockly.Variables'); + + +/** + * Class for a variable's dropdown field. + * @param {!string} varname The default name for the variable. If null, + * a unique variable name will be generated. + * @param {Function} opt_changeHandler A function that is executed when a new + * option is selected. + * @extends {Blockly.FieldDropdown} + * @constructor + */ +Blockly.FieldVariable = function(varname, opt_changeHandler) { + var changeHandler; + if (opt_changeHandler) { + // Wrap the user's change handler together with the variable rename handler. + var thisObj = this; + changeHandler = function(value) { + var retVal = Blockly.FieldVariable.dropdownChange.call(thisObj, value); + var newVal; + if (retVal === undefined) { + newVal = value; // Existing variable selected. + } else if (retVal === null) { + newVal = thisObj.getValue(); // Abort, no change. + } else { + newVal = retVal; // Variable name entered. + } + opt_changeHandler.call(thisObj, newVal); + return retVal; + }; + } else { + changeHandler = Blockly.FieldVariable.dropdownChange; + } + + Blockly.FieldVariable.superClass_.constructor.call(this, + Blockly.FieldVariable.dropdownCreate, changeHandler); + + if (varname) { + this.setValue(varname); + } else { + this.setValue(Blockly.Variables.generateUniqueName()); + } +}; +goog.inherits(Blockly.FieldVariable, Blockly.FieldDropdown); + + +/** + * Get the variable's name (use a variableDB to convert into a real name). + * Unline a regular dropdown, variables are literal and have no neutral value. + * @return {string} Current text. + */ +Blockly.FieldVariable.prototype.getValue = function() { + return this.getText(); +}; + +/** + * Set the variable name. + * @param {string} text New text. + */ +Blockly.FieldVariable.prototype.setValue = function(text) { + this.value_ = text; + this.setText(text); +}; + +/** + * Return a sorted list of variable names for variable dropdown menus. + * Include a special option at the end for creating a new variable name. + * @return {!Array.} Array of variable names. + * @this {!Blockly.FieldVariable} + */ +Blockly.FieldVariable.dropdownCreate = function() { + var variableList = Blockly.Variables.allVariables(); + // Ensure that the currently selected variable is an option. + var name = this.getText(); + if (name && variableList.indexOf(name) == -1) { + variableList.push(name); + } + variableList.sort(goog.string.caseInsensitiveCompare); + variableList.push(Blockly.Msg.RENAME_VARIABLE); + variableList.push(Blockly.Msg.NEW_VARIABLE); + // Variables are not language-specific, use the name as both the user-facing + // text and the internal representation. + var options = []; + for (var x = 0; x < variableList.length; x++) { + options[x] = [variableList[x], variableList[x]]; + } + return options; +}; + +/** + * Event handler for a change in variable name. + * Special case the 'New variable...' and 'Rename variable...' options. + * In both of these special cases, prompt the user for a new name. + * @param {string} text The selected dropdown menu option. + * @return {null|undefined|string} An acceptable new variable name, or null if + * change is to be either aborted (cancel button) or has been already + * handled (rename), or undefined if an existing variable was chosen. + * @this {!Blockly.FieldVariable} + */ +Blockly.FieldVariable.dropdownChange = function(text) { + function promptName(promptText, defaultText) { + Blockly.hideChaff(); + var newVar = window.prompt(promptText, defaultText); + // Merge runs of whitespace. Strip leading and trailing whitespace. + // Beyond this, all names are legal. + return newVar && newVar.replace(/[\s\xa0]+/g, ' ').replace(/^ | $/g, ''); + } + if (text == Blockly.Msg.RENAME_VARIABLE) { + var oldVar = this.getText(); + text = promptName(Blockly.Msg.RENAME_VARIABLE_TITLE.replace('%1', oldVar), + oldVar); + if (text) { + Blockly.Variables.renameVariable(oldVar, text); + } + return null; + } else if (text == Blockly.Msg.NEW_VARIABLE) { + text = promptName(Blockly.Msg.NEW_VARIABLE_TITLE, ''); + // Since variables are case-insensitive, ensure that if the new variable + // matches with an existing variable, the new case prevails throughout. + if (text) { + Blockly.Variables.renameVariable(text, text); + return text; + } + return null; + } + return undefined; +}; diff --git a/core/flyout.js b/core/flyout.js new file mode 100644 index 000000000..83871bb74 --- /dev/null +++ b/core/flyout.js @@ -0,0 +1,595 @@ +/** + * Visual Blocks Editor + * + * Copyright 2011 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Flyout tray containing blocks which may be created. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Flyout'); + +goog.require('Blockly.Block'); +goog.require('Blockly.Comment'); + + +/** + * Class for a flyout. + * @constructor + */ +Blockly.Flyout = function() { + /** + * @type {!Blockly.Workspace} + * @private + */ + var flyout = this; + this.workspace_ = new Blockly.Workspace( + function() {return flyout.getMetrics_();}, + function(ratio) {return flyout.setMetrics_(ratio);}); + this.workspace_.isFlyout = true; + + /** + * Opaque data that can be passed to removeChangeListener. + * @type {Array.} + * @private + */ + this.changeWrapper_ = null; + + /** + * @type {number} + * @private + */ + this.width_ = 0; + + /** + * @type {number} + * @private + */ + this.height_ = 0; + + /** + * List of background buttons that lurk behind each block to catch clicks + * landing in the blocks' lakes and bays. + * @type {!Array.} + * @private + */ + this.buttons_ = []; + + /** + * List of event listeners. + * @type {!Array.} + * @private + */ + this.listeners_ = []; +}; + +/** + * Does the flyout automatically close when a block is created? + * @type {boolean} + */ +Blockly.Flyout.prototype.autoClose = true; + +/** + * Corner radius of the flyout background. + * @type {number} + * @const + */ +Blockly.Flyout.prototype.CORNER_RADIUS = 8; + +/** + * Wrapper function called when a resize occurs. + * @type {Array.} + * @private + */ +Blockly.Flyout.prototype.onResizeWrapper_ = null; + +/** + * Creates the flyout's DOM. Only needs to be called once. + * @return {!Element} The flyout's SVG group. + */ +Blockly.Flyout.prototype.createDom = function() { + /* + + + + + */ + this.svgGroup_ = Blockly.createSvgElement('g', {}, null); + this.svgBackground_ = Blockly.createSvgElement('path', + {'class': 'blocklyFlyoutBackground'}, this.svgGroup_); + this.svgGroup_.appendChild(this.workspace_.createDom()); + return this.svgGroup_; +}; + +/** + * Dispose of this flyout. + * Unlink from all DOM elements to prevent memory leaks. + */ +Blockly.Flyout.prototype.dispose = function() { + this.hide(); + if (this.onResizeWrapper_) { + Blockly.unbindEvent_(this.onResizeWrapper_); + this.onResizeWrapper_ = null; + } + if (this.changeWrapper_) { + Blockly.unbindEvent_(this.changeWrapper_); + this.changeWrapper_ = null; + } + if (this.scrollbar_) { + this.scrollbar_.dispose(); + this.scrollbar_ = null; + } + this.workspace_ = null; + if (this.svgGroup_) { + goog.dom.removeNode(this.svgGroup_); + this.svgGroup_ = null; + } + this.svgBackground_ = null; + this.targetWorkspace_ = null; +}; + +/** + * Return an object with all the metrics required to size scrollbars for the + * flyout. The following properties are computed: + * .viewHeight: Height of the visible rectangle, + * .viewWidth: Width of the visible rectangle, + * .contentHeight: Height of the contents, + * .viewTop: Offset of top edge of visible rectangle from parent, + * .contentTop: Offset of the top-most content from the y=0 coordinate, + * .absoluteTop: Top-edge of view. + * .absoluteLeft: Left-edge of view. + * @return {Object} Contains size and position metrics of the flyout. + * @private + */ +Blockly.Flyout.prototype.getMetrics_ = function() { + if (!this.isVisible()) { + // Flyout is hidden. + return null; + } + var viewHeight = this.height_ - 2 * this.CORNER_RADIUS; + var viewWidth = this.width_; + try { + var optionBox = this.workspace_.getCanvas().getBBox(); + } catch (e) { + // Firefox has trouble with hidden elements (Bug 528969). + var optionBox = {height: 0, y: 0}; + } + return { + viewHeight: viewHeight, + viewWidth: viewWidth, + contentHeight: optionBox.height + optionBox.y, + viewTop: -this.workspace_.scrollY, + contentTop: 0, + absoluteTop: this.CORNER_RADIUS, + absoluteLeft: 0 + }; +}; + +/** + * Sets the Y translation of the flyout to match the scrollbars. + * @param {!Object} yRatio Contains a y property which is a float + * between 0 and 1 specifying the degree of scrolling. + * @private + */ +Blockly.Flyout.prototype.setMetrics_ = function(yRatio) { + var metrics = this.getMetrics_(); + if (goog.isNumber(yRatio.y)) { + this.workspace_.scrollY = + -metrics.contentHeight * yRatio.y - metrics.contentTop; + } + var y = this.workspace_.scrollY + metrics.absoluteTop; + this.workspace_.getCanvas().setAttribute('transform', + 'translate(0,' + y + ')'); +}; + +/** + * Initializes the flyout. + * @param {!Blockly.Workspace} workspace The workspace in which to create new + * blocks. + * @param {boolean} withScrollbar True if a scrollbar should be displayed. + */ +Blockly.Flyout.prototype.init = + function(workspace, withScrollbar) { + this.targetWorkspace_ = workspace; + // Add scrollbars. + var flyout = this; + if (withScrollbar) { + this.scrollbar_ = new Blockly.Scrollbar(flyout.workspace_, false, false); + } + + this.hide(); + + // If the document resizes, reposition the flyout. + this.onResizeWrapper_ = Blockly.bindEvent_(window, + goog.events.EventType.RESIZE, this, this.position_); + this.position_(); + this.changeWrapper_ = Blockly.bindEvent_(this.targetWorkspace_.getCanvas(), + 'blocklyWorkspaceChange', this, this.filterForCapacity_); +}; + +/** + * Move the toolbox to the edge of the workspace. + * @private + */ +Blockly.Flyout.prototype.position_ = function() { + if (!this.isVisible()) { + return; + } + var metrics = this.targetWorkspace_.getMetrics(); + if (!metrics) { + // Hidden components will return null. + return; + } + var edgeWidth = this.width_ - this.CORNER_RADIUS; + if (Blockly.RTL) { + edgeWidth *= -1; + } + var path = ['M ' + (Blockly.RTL ? this.width_ : 0) + ',0']; + path.push('h', edgeWidth); + path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, + Blockly.RTL ? 0 : 1, + Blockly.RTL ? -this.CORNER_RADIUS : this.CORNER_RADIUS, + this.CORNER_RADIUS); + path.push('v', Math.max(0, metrics.viewHeight - this.CORNER_RADIUS * 2)); + path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, + Blockly.RTL ? 0 : 1, + Blockly.RTL ? this.CORNER_RADIUS : -this.CORNER_RADIUS, + this.CORNER_RADIUS); + path.push('h', -edgeWidth); + path.push('z'); + this.svgBackground_.setAttribute('d', path.join(' ')); + + var x = metrics.absoluteLeft; + if (Blockly.RTL) { + x += metrics.viewWidth; + x -= this.width_; + } + this.svgGroup_.setAttribute('transform', + 'translate(' + x + ',' + metrics.absoluteTop + ')'); + + // Record the height for Blockly.Flyout.getMetrics_. + this.height_ = metrics.viewHeight; + + // Update the scrollbar (if one exists). + if (this.scrollbar_) { + this.scrollbar_.resize(); + } +}; + +/** + * Is the flyout visible? + * @return {boolean} True if visible. + */ +Blockly.Flyout.prototype.isVisible = function() { + return this.svgGroup_.style.display == 'block'; +}; + +/** + * Hide and empty the flyout. + */ +Blockly.Flyout.prototype.hide = function() { + if (!this.isVisible()) { + return; + } + this.svgGroup_.style.display = 'none'; + // Delete all the event listeners. + for (var x = 0, listen; listen = this.listeners_[x]; x++) { + Blockly.unbindEvent_(listen); + } + this.listeners_.splice(0); + if (this.reflowWrapper_) { + Blockly.unbindEvent_(this.reflowWrapper_); + this.reflowWrapper_ = null; + } + // Delete all the blocks. + var blocks = this.workspace_.getTopBlocks(false); + for (var x = 0, block; block = blocks[x]; x++) { + if (block.workspace == this.workspace_) { + block.dispose(false, false); + } + } + // Delete all the background buttons. + for (var x = 0, rect; rect = this.buttons_[x]; x++) { + goog.dom.removeNode(rect); + } + this.buttons_.splice(0); +}; + +/** + * Show and populate the flyout. + * @param {!Array|string} xmlList List of blocks to show. + * Variables and procedures have a custom set of blocks. + */ +Blockly.Flyout.prototype.show = function(xmlList) { + this.hide(); + var margin = this.CORNER_RADIUS; + this.svgGroup_.style.display = 'block'; + + // Create the blocks to be shown in this flyout. + var blocks = []; + var gaps = []; + if (xmlList == Blockly.Variables.NAME_TYPE) { + // Special category for variables. + Blockly.Variables.flyoutCategory(blocks, gaps, margin, + /** @type {!Blockly.Workspace} */ (this.workspace_)); + } else if (xmlList == Blockly.Procedures.NAME_TYPE) { + // Special category for procedures. + Blockly.Procedures.flyoutCategory(blocks, gaps, margin, + /** @type {!Blockly.Workspace} */ (this.workspace_)); + } else { + for (var i = 0, xml; xml = xmlList[i]; i++) { + if (xml.tagName && xml.tagName.toUpperCase() == 'BLOCK') { + var block = Blockly.Xml.domToBlock_( + /** @type {!Blockly.Workspace} */ (this.workspace_), xml); + blocks.push(block); + gaps.push(margin * 3); + } + } + } + + // Lay out the blocks vertically. + var cursorY = margin; + for (var i = 0, block; block = blocks[i]; i++) { + var allBlocks = block.getDescendants(); + for (var j = 0, child; child = allBlocks[j]; j++) { + // Mark blocks as being inside a flyout. This is used to detect and + // prevent the closure of the flyout if the user right-clicks on such a + // block. + child.isInFlyout = true; + // There is no good way to handle comment bubbles inside the flyout. + // Blocks shouldn't come with predefined comments, but someone will + // try this, I'm sure. Kill the comment. + Blockly.Comment && child.setCommentText(null); + } + block.render(); + var root = block.getSvgRoot(); + var blockHW = block.getHeightWidth(); + var x = Blockly.RTL ? 0 : margin + Blockly.BlockSvg.TAB_WIDTH; + block.moveBy(x, cursorY); + cursorY += blockHW.height + gaps[i]; + + // Create an invisible rectangle under the block to act as a button. Just + // using the block as a button is poor, since blocks have holes in them. + var rect = Blockly.createSvgElement('rect', {'fill-opacity': 0}, null); + // Add the rectangles under the blocks, so that the blocks' tooltips work. + this.workspace_.getCanvas().insertBefore(rect, block.getSvgRoot()); + block.flyoutRect_ = rect; + this.buttons_[i] = rect; + + if (this.autoClose) { + this.listeners_.push(Blockly.bindEvent_(root, 'mousedown', null, + this.createBlockFunc_(block))); + } else { + this.listeners_.push(Blockly.bindEvent_(root, 'mousedown', null, + this.blockMouseDown_(block))); + } + this.listeners_.push(Blockly.bindEvent_(root, 'mouseover', block.svg_, + block.svg_.addSelect)); + this.listeners_.push(Blockly.bindEvent_(root, 'mouseout', block.svg_, + block.svg_.removeSelect)); + this.listeners_.push(Blockly.bindEvent_(rect, 'mousedown', null, + this.createBlockFunc_(block))); + this.listeners_.push(Blockly.bindEvent_(rect, 'mouseover', block.svg_, + block.svg_.addSelect)); + this.listeners_.push(Blockly.bindEvent_(rect, 'mouseout', block.svg_, + block.svg_.removeSelect)); + } + this.width_ = 0; + this.reflow(); + + this.filterForCapacity_(); + + // Fire a resize event to update the flyout's scrollbar. + Blockly.fireUiEvent(window, 'resize'); + this.reflowWrapper_ = Blockly.bindEvent_(this.workspace_.getCanvas(), + 'blocklyWorkspaceChange', this, this.reflow); + this.workspace_.fireChangeEvent(); +}; + +/** + * Compute width of flyout. Position button under each block. + * For RTL: Lay out the blocks right-aligned. + */ +Blockly.Flyout.prototype.reflow = function() { + var flyoutWidth = 0; + var margin = this.CORNER_RADIUS; + var blocks = this.workspace_.getTopBlocks(false); + for (var x = 0, block; block = blocks[x]; x++) { + var root = block.getSvgRoot(); + var blockHW = block.getHeightWidth(); + flyoutWidth = Math.max(flyoutWidth, blockHW.width); + } + flyoutWidth += margin + Blockly.BlockSvg.TAB_WIDTH + margin / 2 + + Blockly.Scrollbar.scrollbarThickness; + if (this.width_ != flyoutWidth) { + for (var x = 0, block; block = blocks[x]; x++) { + var blockHW = block.getHeightWidth(); + var blockXY = block.getRelativeToSurfaceXY(); + if (Blockly.RTL) { + // With the flyoutWidth known, right-align the blocks. + var dx = flyoutWidth - margin - Blockly.BlockSvg.TAB_WIDTH - blockXY.x; + block.moveBy(dx, 0); + blockXY.x += dx; + } + if (block.flyoutRect_) { + block.flyoutRect_.setAttribute('width', blockHW.width); + block.flyoutRect_.setAttribute('height', blockHW.height); + block.flyoutRect_.setAttribute('x', + Blockly.RTL ? blockXY.x - blockHW.width : blockXY.x); + block.flyoutRect_.setAttribute('y', blockXY.y); + } + } + // Record the width for .getMetrics_ and .position_. + this.width_ = flyoutWidth; + // Fire a resize event to update the flyout's scrollbar. + Blockly.fireUiEvent(window, 'resize'); + } +}; + +/** + * Move a block to a specific location on the drawing surface. + * @param {number} dx Horizontal location. + * @param {number} dy Vertical location. + */ +Blockly.Block.prototype.moveTo = function(x, y) { + var oldXY = this.getRelativeToSurfaceXY(); + this.svg_.getRootElement().setAttribute('transform', + 'translate(' + x + ', ' + y + ')'); + this.moveConnections_(x - oldXY.x, y - oldXY.y); +}; + +/** + * Handle a mouse-down on an SVG block in a non-closing flyout. + * @param {!Blockly.Block} originBlock The flyout block to copy. + * @return {!Function} Function to call when block is clicked. + * @private + */ +Blockly.Flyout.prototype.blockMouseDown_ = function(block) { + var flyout = this; + return function(e) { + Blockly.terminateDrag_(); + Blockly.hideChaff(); + if (Blockly.isRightButton(e)) { + // Right-click. + if (Blockly.ContextMenu) { + block.showContextMenu_(Blockly.mouseToSvg(e)); + } + } else { + // Left-click (or middle click) + Blockly.removeAllRanges(); + Blockly.setCursorHand_(true); + // Record the current mouse position. + Blockly.Flyout.startDragMouseX_ = e.clientX; + Blockly.Flyout.startDragMouseY_ = e.clientY; + Blockly.Flyout.startBlock_ = block; + Blockly.Flyout.startFlyout_ = flyout; + Blockly.Flyout.onMouseUpWrapper_ = Blockly.bindEvent_(document, + 'mouseup', this, Blockly.terminateDrag_); + Blockly.Flyout.onMouseMoveWrapper_ = Blockly.bindEvent_(document, + 'mousemove', this, flyout.onMouseMove_); + } + // This event has been handled. No need to bubble up to the document. + e.stopPropagation(); + }; +}; + +/** + * Mouse button is down on a block in a non-closing flyout. Create the block + * if the mouse moves beyond a small radius. This allows one to play with + * fields without instantiating blocks that instantly self-destruct. + * @param {!Event} e Mouse move event. + * @private + */ +Blockly.Flyout.prototype.onMouseMove_ = function(e) { + if (e.type == 'mousemove' && e.clientX <= 1 && e.clientY == 0 && + e.button == 0) { + /* HACK: + Safari Mobile 6.0 and Chrome for Android 18.0 fire rogue mousemove events + on certain touch actions. Ignore events with these signatures. + This may result in a one-pixel blind spot in other browsers, + but this shouldn't be noticable. */ + e.stopPropagation(); + return; + } + Blockly.removeAllRanges(); + var dx = e.clientX - Blockly.Flyout.startDragMouseX_; + var dy = e.clientY - Blockly.Flyout.startDragMouseY_; + // Still dragging within the sticky DRAG_RADIUS. + var dr = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)); + if (dr > Blockly.DRAG_RADIUS) { + // Create the block. + Blockly.Flyout.startFlyout_.createBlockFunc_(Blockly.Flyout.startBlock_)(e); + } +}; + +/** + * Create a copy of this block on the workspace. + * @param {!Blockly.Block} originBlock The flyout block to copy. + * @return {!Function} Function to call when block is clicked. + * @private + */ +Blockly.Flyout.prototype.createBlockFunc_ = function(originBlock) { + var flyout = this; + return function(e) { + if (Blockly.isRightButton(e)) { + // Right-click. Don't create a block, let the context menu show. + return; + } + if (originBlock.disabled) { + // Beyond capacity. + return; + } + // Create the new block by cloning the block in the flyout (via XML). + var xml = Blockly.Xml.blockToDom_(originBlock); + var block = Blockly.Xml.domToBlock_(flyout.targetWorkspace_, xml); + // Place it in the same spot as the flyout copy. + var svgRootOld = originBlock.getSvgRoot(); + if (!svgRootOld) { + throw 'originBlock is not rendered.'; + } + var xyOld = Blockly.getSvgXY_(svgRootOld); + var svgRootNew = block.getSvgRoot(); + if (!svgRootNew) { + throw 'block is not rendered.'; + } + var xyNew = Blockly.getSvgXY_(svgRootNew); + block.moveBy(xyOld.x - xyNew.x, xyOld.y - xyNew.y); + if (flyout.autoClose) { + flyout.hide(); + } else { + flyout.filterForCapacity_(); + } + // Start a dragging operation on the new block. + block.onMouseDown_(e); + }; +}; + +/** + * Filter the blocks on the flyout to disable the ones that are above the + * capacity limit. + * @private + */ +Blockly.Flyout.prototype.filterForCapacity_ = function() { + var remainingCapacity = this.targetWorkspace_.remainingCapacity(); + var blocks = this.workspace_.getTopBlocks(false); + for (var i = 0, block; block = blocks[i]; i++) { + var allBlocks = block.getDescendants(); + var disabled = allBlocks.length > remainingCapacity; + block.setDisabled(disabled); + } +}; + +/** + * Stop binding to the global mouseup and mousemove events. + * @private + */ +Blockly.Flyout.terminateDrag_ = function() { + if (Blockly.Flyout.onMouseUpWrapper_) { + Blockly.unbindEvent_(Blockly.Flyout.onMouseUpWrapper_); + Blockly.Flyout.onMouseUpWrapper_ = null; + } + if (Blockly.Flyout.onMouseMoveWrapper_) { + Blockly.unbindEvent_(Blockly.Flyout.onMouseMoveWrapper_); + Blockly.Flyout.onMouseMoveWrapper_ = null; + } + Blockly.Flyout.startDragMouseX_ = 0; + Blockly.Flyout.startDragMouseY_ = 0; + Blockly.Flyout.startBlock_ = null; + Blockly.Flyout.startFlyout_ = null; +}; diff --git a/core/generator.js b/core/generator.js new file mode 100644 index 000000000..6d93dc3c9 --- /dev/null +++ b/core/generator.js @@ -0,0 +1,219 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Utility functions for generating executable code from + * Blockly code. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Generator'); + +goog.require('Blockly.Block'); + + +/** + * Class for a code generator that translates the blocks into a language. + * @param {string} name Language name of this generator. + * @constructor + */ +Blockly.Generator = function(name) { + this.name_ = name; + this.RESERVED_WORDS_ = ''; +}; + +/** + * Category to separate generated function names from variables and procedures. + */ +Blockly.Generator.NAME_TYPE = 'generated_function'; + +/** + * Generate code for all blocks in the workspace to the specified language. + * @return {string} Generated code. + */ +Blockly.Generator.prototype.workspaceToCode = function() { + var code = []; + this.init(); + var blocks = Blockly.mainWorkspace.getTopBlocks(true); + for (var x = 0, block; block = blocks[x]; x++) { + var line = this.blockToCode(block); + if (line instanceof Array) { + // Value blocks return tuples of code and operator order. + // Top-level blocks don't care about operator order. + line = line[0]; + } + if (line) { + if (block.outputConnection && this.scrubNakedValue) { + // This block is a naked value. Ask the language's code generator if + // it wants to append a semicolon, or something. + line = this.scrubNakedValue(line); + } + code.push(line); + } + } + code = code.join('\n'); // Blank line between each section. + code = this.finish(code); + // Final scrubbing of whitespace. + code = code.replace(/^\s+\n/, ''); + code = code.replace(/\n\s+$/, '\n'); + code = code.replace(/[ \t]+\n/g, '\n'); + return code; +}; + +// The following are some helpful functions which can be used by multiple +// languages. + +/** + * Prepend a common prefix onto each line of code. + * @param {string} text The lines of code. + * @param {string} prefix The common prefix. + * @return {string} The prefixed lines of code. + */ +Blockly.Generator.prototype.prefixLines = function(text, prefix) { + return prefix + text.replace(/\n(.)/g, '\n' + prefix + '$1'); +}; + +/** + * Recursively spider a tree of blocks, returning all their comments. + * @param {!Blockly.Block} block The block from which to start spidering. + * @return {string} Concatenated list of comments. + */ +Blockly.Generator.prototype.allNestedComments = function(block) { + var comments = []; + var blocks = block.getDescendants(); + for (var x = 0; x < blocks.length; x++) { + var comment = blocks[x].getCommentText(); + if (comment) { + comments.push(comment); + } + } + // Append an empty string to create a trailing line break when joined. + if (comments.length) { + comments.push(''); + } + return comments.join('\n'); +}; + +/** + * Generate code for the specified block (and attached blocks). + * @param {Blockly.Block} block The block to generate code for. + * @return {string|!Array} For statement blocks, the generated code. + * For value blocks, an array containing the generated code and an + * operator order value. Returns '' if block is null. + */ +Blockly.Generator.prototype.blockToCode = function(block) { + if (!block) { + return ''; + } + if (block.disabled) { + // Skip past this block if it is disabled. + var nextBlock = block.nextConnection && block.nextConnection.targetBlock(); + return this.blockToCode(nextBlock); + } + + var func = this[block.type]; + if (!func) { + throw 'Language "' + this.name_ + '" does not know how to generate code ' + + 'for block type "' + block.type + '".'; + } + // First argument to func.call is the value of 'this' in the generator. + // Prior to 24 September 2013 'this' was the only way to access the block. + // The current prefered method of accessing the block is through the second + // argument to func.call, which becomes the first parameter to the generator. + var code = func.call(block, block); + if (code instanceof Array) { + // Value blocks return tuples of code and operator order. + return [this.scrub_(block, code[0]), code[1]]; + } else { + return this.scrub_(block, code); + } +}; + +/** + * Generate code representing the specified value input. + * @param {!Blockly.Block} block The block containing the input. + * @param {string} name The name of the input. + * @param {number} order The maximum binding strength (minimum order value) + * of any operators adjacent to "block". + * @return {string} Generated code or '' if no blocks are connected or the + * specified input does not exist. + */ +Blockly.Generator.prototype.valueToCode = function(block, name, order) { + if (isNaN(order)) { + throw 'Expecting valid order from block "' + block.type + '".'; + } + var targetBlock = block.getInputTargetBlock(name); + if (!targetBlock) { + return ''; + } + var tuple = this.blockToCode(targetBlock); + if (tuple === '') { + // Disabled block. + return ''; + } + if (!(tuple instanceof Array)) { + // Value blocks must return code and order of operations info. + // Statement blocks must only return code. + throw 'Expecting tuple from value block "' + targetBlock.type + '".'; + } + var code = tuple[0]; + var innerOrder = tuple[1]; + if (isNaN(innerOrder)) { + throw 'Expecting valid order from value block "' + targetBlock.type + '".'; + } + if (code && order <= innerOrder) { + // The operators outside this code are stonger than the operators + // inside this code. To prevent the code from being pulled apart, + // wrap the code in parentheses. + // Technically, this should be handled on a language-by-language basis. + // However all known (sane) languages use parentheses for grouping. + code = '(' + code + ')'; + } + return code; +}; + +/** + * Generate code representing the statement. Indent the code. + * @param {!Blockly.Block} block The block containing the input. + * @param {string} name The name of the input. + * @return {string} Generated code or '' if no blocks are connected. + */ +Blockly.Generator.prototype.statementToCode = function(block, name) { + var targetBlock = block.getInputTargetBlock(name); + var code = this.blockToCode(targetBlock); + if (!goog.isString(code)) { + // Value blocks must return code and order of operations info. + // Statement blocks must only return code. + throw 'Expecting code from statement block "' + targetBlock.type + '".'; + } + if (code) { + code = this.prefixLines(/** @type {string} */ (code), ' '); + } + return code; +}; + +/** + * Add one or more words to the list of reserved words for this language. + * @param {string} words Comma-separated list of words to add to the list. + * No spaces. Duplicates are ok. + */ +Blockly.Generator.prototype.addReservedWords = function(words) { + this.RESERVED_WORDS_ += words + ','; +}; diff --git a/core/icon.js b/core/icon.js new file mode 100644 index 000000000..5465af129 --- /dev/null +++ b/core/icon.js @@ -0,0 +1,191 @@ +/** + * Visual Blocks Editor + * + * Copyright 2013 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Object representing an icon on a block. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Icon'); + +/** + * Class for an icon. + * @param {Blockly.Block} block The block associated with this icon. + * @constructor + */ +Blockly.Icon = function(block) { + this.block_ = block; +}; + +/** + * Radius of icons. + */ +Blockly.Icon.RADIUS = 8; + +/** + * Bubble UI (if visible). + * @type {Blockly.Bubble} + * @private + */ +Blockly.Icon.prototype.bubble_ = null; + +/** + * Absolute X coordinate of icon's center. + * @private + */ +Blockly.Icon.prototype.iconX_ = 0; + +/** + * Absolute Y coordinate of icon's centre. + * @private + */ +Blockly.Icon.prototype.iconY_ = 0; + +/** + * Create the icon on the block. + * @private + */ +Blockly.Icon.prototype.createIcon_ = function() { + /* Here's the markup that will be generated: + + */ + this.iconGroup_ = Blockly.createSvgElement('g', {}, null); + this.block_.getSvgRoot().appendChild(this.iconGroup_); + Blockly.bindEvent_(this.iconGroup_, 'mouseup', this, this.iconClick_); + this.updateEditable(); +}; + +/** + * Dispose of this icon. + */ +Blockly.Icon.prototype.dispose = function() { + // Dispose of and unlink the icon. + goog.dom.removeNode(this.iconGroup_); + this.iconGroup_ = null; + // Dispose of and unlink the bubble. + this.setVisible(false); + this.block_ = null; +}; + +/** + * Add or remove the UI indicating if this icon may be clicked or not. + */ +Blockly.Icon.prototype.updateEditable = function() { + if (this.block_.isEditable() && !this.block_.isInFlyout) { + Blockly.addClass_(/** @type {!Element} */ (this.iconGroup_), + 'blocklyIconGroup'); + } else { + Blockly.removeClass_(/** @type {!Element} */ (this.iconGroup_), + 'blocklyIconGroup'); + } +}; + +/** + * Is the associated bubble visible? + * @return {boolean} True if the bubble is visible. + */ +Blockly.Icon.prototype.isVisible = function() { + return !!this.bubble_; +}; + +/** + * Clicking on the icon toggles if the bubble is visible. + * @param {!Event} e Mouse click event. + * @private + */ +Blockly.Icon.prototype.iconClick_ = function(e) { + if (this.block_.isEditable() && !this.block_.isInFlyout) { + this.setVisible(!this.isVisible()); + } +}; + +/** + * Change the colour of the associated bubble to match its block. + */ +Blockly.Icon.prototype.updateColour = function() { + if (this.isVisible()) { + var hexColour = Blockly.makeColour(this.block_.getColour()); + this.bubble_.setColour(hexColour); + } +}; + +/** + * Render the icon. + * @param {number} cursorX Horizontal offset at which to position the icon. + * @return {number} Horizontal offset for next item to draw. + */ +Blockly.Icon.prototype.renderIcon = function(cursorX) { + if (this.block_.isCollapsed()) { + this.iconGroup_.setAttribute('display', 'none'); + return cursorX; + } + this.iconGroup_.setAttribute('display', 'block'); + + var TOP_MARGIN = 5; + var diameter = 2 * Blockly.Icon.RADIUS; + if (Blockly.RTL) { + cursorX -= diameter; + } + this.iconGroup_.setAttribute('transform', + 'translate(' + cursorX + ', ' + TOP_MARGIN + ')'); + this.computeIconLocation(); + if (Blockly.RTL) { + cursorX -= Blockly.BlockSvg.SEP_SPACE_X; + } else { + cursorX += diameter + Blockly.BlockSvg.SEP_SPACE_X; + } + return cursorX; +}; + +/** + * Notification that the icon has moved. Update the arrow accordingly. + * @param {number} x Absolute horizontal location. + * @param {number} y Absolute vertical location. + */ +Blockly.Icon.prototype.setIconLocation = function(x, y) { + this.iconX_ = x; + this.iconY_ = y; + if (this.isVisible()) { + this.bubble_.setAnchorLocation(x, y); + } +}; + +/** + * Notification that the icon has moved, but we don't really know where. + * Recompute the icon's location from scratch. + */ +Blockly.Icon.prototype.computeIconLocation = function() { + // Find coordinates for the centre of the icon and update the arrow. + var blockXY = this.block_.getRelativeToSurfaceXY(); + var iconXY = Blockly.getRelativeXY_(this.iconGroup_); + var newX = blockXY.x + iconXY.x + Blockly.Icon.RADIUS; + var newY = blockXY.y + iconXY.y + Blockly.Icon.RADIUS; + if (newX !== this.iconX_ || newY !== this.iconY_) { + this.setIconLocation(newX, newY); + } +}; + +/** + * Returns the center of the block's icon relative to the surface. + * @return {!Object} Object with x and y properties. + */ +Blockly.Icon.prototype.getIconLocation = function() { + return {x: this.iconX_, y: this.iconY_}; +}; diff --git a/core/inject.js b/core/inject.js new file mode 100644 index 000000000..bc9edd42d --- /dev/null +++ b/core/inject.js @@ -0,0 +1,394 @@ +/** + * Visual Blocks Editor + * + * Copyright 2011 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Functions for injecting Blockly into a web page. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.inject'); + +goog.require('Blockly.Css'); +goog.require('goog.dom'); + + +/** + * Initialize the SVG document with various handlers. + * @param {!Element} container Containing element. + * @param {Object} opt_options Optional dictionary of options. + */ +Blockly.inject = function(container, opt_options) { + // Verify that the container is in document. + if (!goog.dom.contains(document, container)) { + throw 'Error: container is not in current document.'; + } + if (opt_options) { + // TODO(scr): don't mix this in to global variables. + goog.mixin(Blockly, Blockly.parseOptions_(opt_options)); + } + Blockly.createDom_(container); + Blockly.init_(); +}; + +/** + * Configure Blockly to behave according to a set of options. + * @param {!Object} options Dictionary of options. + * @return {Object} Parsed options. + * @private + */ +Blockly.parseOptions_ = function(options) { + var readOnly = !!options['readOnly']; + if (readOnly) { + var hasCategories = false; + var hasTrashcan = false; + var hasCollapse = false; + var tree = null; + } else { + var tree = options['toolbox']; + if (tree) { + if (typeof tree != 'string' && typeof XSLTProcessor == 'undefined') { + // In this case the tree will not have been properly built by the + // browser. The HTML will be contained in the element, but it will + // not have the proper DOM structure since the browser doesn't support + // XSLTProcessor (XML -> HTML). This is the case in IE 9+. + tree = tree.outerHTML; + } + if (typeof tree == 'string') { + tree = Blockly.Xml.textToDom(tree); + } + var hasCategories = !!tree.getElementsByTagName('category').length; + } else { + tree = null; + var hasCategories = false; + } + var hasTrashcan = options['trashcan']; + if (hasTrashcan === undefined) { + hasTrashcan = hasCategories; + } + var hasCollapse = options['collapse']; + if (hasCollapse === undefined) { + hasCollapse = hasCategories; + } + } + if (tree && !hasCategories) { + // Scrollbars are not compatible with a non-flyout toolbox. + var hasScrollbars = false; + } else { + var hasScrollbars = options['scrollbars']; + if (hasScrollbars === undefined) { + hasScrollbars = true; + } + } + return { + RTL: !!options['rtl'], + collapse: hasCollapse, + readOnly: readOnly, + maxBlocks: options['maxBlocks'] || Infinity, + pathToBlockly: options['path'] || './', + hasCategories: hasCategories, + hasScrollbars: hasScrollbars, + hasTrashcan: hasTrashcan, + languageTree: tree + }; +}; + +/** + * Create the SVG image. + * @param {!Element} container Containing element. + * @private + */ +Blockly.createDom_ = function(container) { + // Sadly browsers (Chrome vs Firefox) are currently inconsistent in laying + // out content in RTL mode. Therefore Blockly forces the use of LTR, + // then manually positions content in RTL as needed. + container.setAttribute('dir', 'LTR'); + // Closure can be trusted to create HTML widgets with the proper direction. + goog.ui.Component.setDefaultRightToLeft(Blockly.RTL); + + // Load CSS. + Blockly.Css.inject(); + + // Build the SVG DOM. + /* + + ... + + */ + var svg = Blockly.createSvgElement('svg', { + 'xmlns': 'http://www.w3.org/2000/svg', + 'xmlns:html': 'http://www.w3.org/1999/xhtml', + 'xmlns:xlink': 'http://www.w3.org/1999/xlink', + 'version': '1.1', + 'class': 'blocklySvg' + }, null); + /* + + ... filters go here ... + + */ + var defs = Blockly.createSvgElement('defs', {}, svg); + var filter, feSpecularLighting, feMerge, pattern; + /* + + + + + + + + + */ + filter = Blockly.createSvgElement('filter', {'id': 'blocklyEmboss'}, defs); + Blockly.createSvgElement('feGaussianBlur', + {'in': 'SourceAlpha', 'stdDeviation': 1, 'result': 'blur'}, filter); + feSpecularLighting = Blockly.createSvgElement('feSpecularLighting', + {'in': 'blur', 'surfaceScale': 1, 'specularConstant': 0.5, + 'specularExponent': 10, 'lighting-color': 'white', 'result': 'specOut'}, + filter); + Blockly.createSvgElement('fePointLight', + {'x': -5000, 'y': -10000, 'z': 20000}, feSpecularLighting); + Blockly.createSvgElement('feComposite', + {'in': 'specOut', 'in2': 'SourceAlpha', 'operator': 'in', + 'result': 'specOut'}, filter); + Blockly.createSvgElement('feComposite', + {'in': 'SourceGraphic', 'in2': 'specOut', 'operator': 'arithmetic', + 'k1': 0, 'k2': 1, 'k3': 1, 'k4': 0}, filter); + /* + + + + + + + + + */ + filter = Blockly.createSvgElement('filter', + {'id': 'blocklyTrashcanShadowFilter'}, defs); + Blockly.createSvgElement('feGaussianBlur', + {'in': 'SourceAlpha', 'stdDeviation': 2, 'result': 'blur'}, filter); + Blockly.createSvgElement('feOffset', + {'in': 'blur', 'dx': 1, 'dy': 1, 'result': 'offsetBlur'}, filter); + feMerge = Blockly.createSvgElement('feMerge', {}, filter); + Blockly.createSvgElement('feMergeNode', {'in': 'offsetBlur'}, feMerge); + Blockly.createSvgElement('feMergeNode', {'in': 'SourceGraphic'}, feMerge); + /* + + + + */ + filter = Blockly.createSvgElement('filter', + {'id': 'blocklyShadowFilter'}, defs); + Blockly.createSvgElement('feGaussianBlur', {'stdDeviation': 2}, filter); + /* + + + + + */ + pattern = Blockly.createSvgElement('pattern', + {'id': 'blocklyDisabledPattern', 'patternUnits': 'userSpaceOnUse', + 'width': 10, 'height': 10}, defs); + Blockly.createSvgElement('rect', + {'width': 10, 'height': 10, 'fill': '#aaa'}, pattern); + Blockly.createSvgElement('path', + {'d': 'M 0 0 L 10 10 M 10 0 L 0 10', 'stroke': '#cc0'}, pattern); + Blockly.mainWorkspace = new Blockly.Workspace( + Blockly.getMainWorkspaceMetrics_, + Blockly.setMainWorkspaceMetrics_); + svg.appendChild(Blockly.mainWorkspace.createDom()); + Blockly.mainWorkspace.maxBlocks = Blockly.maxBlocks; + + if (!Blockly.readOnly) { + // Determine if there needs to be a category tree, or a simple list of + // blocks. This cannot be changed later, since the UI is very different. + if (Blockly.hasCategories) { + Blockly.Toolbox.createDom(svg, container); + } else { + /** + * @type {!Blockly.Flyout} + * @private + */ + Blockly.mainWorkspace.flyout_ = new Blockly.Flyout(); + var flyout = Blockly.mainWorkspace.flyout_; + var flyoutSvg = flyout.createDom(); + flyout.init(Blockly.mainWorkspace, true); + flyout.autoClose = false; + // Insert the flyout behind the workspace so that blocks appear on top. + goog.dom.insertSiblingBefore(flyoutSvg, Blockly.mainWorkspace.svgGroup_); + var workspaceChanged = function() { + if (Blockly.Block.dragMode_ == 0) { + var metrics = Blockly.mainWorkspace.getMetrics(); + if (metrics.contentTop < 0 || + metrics.contentTop + metrics.contentHeight > + metrics.viewHeight + metrics.viewTop || + metrics.contentLeft < (Blockly.RTL ? metrics.viewLeft : 0) || + metrics.contentLeft + metrics.contentWidth > + metrics.viewWidth + (Blockly.RTL ? 2 : 1) * metrics.viewLeft) { + // One or more blocks is out of bounds. Bump them back in. + var MARGIN = 25; + var blocks = Blockly.mainWorkspace.getTopBlocks(false); + for (var b = 0, block; block = blocks[b]; b++) { + var blockXY = block.getRelativeToSurfaceXY(); + var blockHW = block.getHeightWidth(); + // Bump any block that's above the top back inside. + var overflow = metrics.viewTop + MARGIN - blockHW.height - + blockXY.y; + if (overflow > 0) { + block.moveBy(0, overflow); + } + // Bump any block that's below the bottom back inside. + var overflow = metrics.viewTop + metrics.viewHeight - MARGIN - + blockXY.y; + if (overflow < 0) { + block.moveBy(0, overflow); + } + // Bump any block that's off the left back inside. + var overflow = MARGIN + metrics.viewLeft - blockXY.x - + (Blockly.RTL ? 0 : blockHW.width); + if (overflow > 0) { + block.moveBy(overflow, 0); + } + // Bump any block that's off the right back inside. + var overflow = metrics.viewLeft + metrics.viewWidth - MARGIN - + blockXY.x + (Blockly.RTL ? blockHW.width : 0); + if (overflow < 0) { + block.moveBy(overflow, 0); + } + // Delete any block that's sitting on top of the flyout. + if (block.isDeletable() && (Blockly.RTL ? + blockXY.x - 2 * metrics.viewLeft - metrics.viewWidth : + -blockXY.x) > MARGIN * 2) { + block.dispose(false, true); + } + } + } + } + }; + Blockly.addChangeListener(workspaceChanged); + } + } + + Blockly.Tooltip && svg.appendChild(Blockly.Tooltip.createDom()); + if (!Blockly.readOnly && Blockly.FieldDropdown) { + svg.appendChild(Blockly.FieldDropdown.createDom()); + } + + if (Blockly.ContextMenu && Blockly.ContextMenu) { + svg.appendChild(Blockly.ContextMenu.createDom()); + } + + // The SVG is now fully assembled. Add it to the container. + container.appendChild(svg); + Blockly.svg = svg; + Blockly.svgResize(); + + // Create an HTML container for popup overlays (e.g. editor widgets). + Blockly.WidgetDiv.DIV = goog.dom.createDom('div', 'blocklyWidgetDiv'); + document.body.appendChild(Blockly.WidgetDiv.DIV); +}; + + +/** + * Initialize Blockly with various handlers. + * @private + */ +Blockly.init_ = function() { + if (goog.userAgent.WEBKIT) { + /* HACK: + WebKit bug 67298 causes control points to be included in the reported + bounding box. Detect if this browser suffers from this bug by drawing a + shape that is 50px high, and has a control point that sticks up by 5px. + If the getBBox function returns a height of 55px instead of 50px, then + this browser has broken control points. + */ + var path = Blockly.createSvgElement('path', + {'d': 'm 0,0 c 0,-5 0,-5 0,0 H 50 V 50 z'}, Blockly.svg); + if (path.getBBox().height > 50) { + // Chrome (v28) and Opera (v15) report 55, Safari (v6.0.5) reports 53.75. + Blockly.BROKEN_CONTROL_POINTS = true; + } + Blockly.svg.removeChild(path); + } + + // Bind events for scrolling the workspace. + // Most of these events should be bound to the SVG's surface. + // However, 'mouseup' has to be on the whole document so that a block dragged + // out of bounds and released will know that it has been released. + // Also, 'keydown' has to be on the whole document since the browser doesn't + // understand a concept of focus on the SVG image. + Blockly.bindEvent_(Blockly.svg, 'mousedown', null, Blockly.onMouseDown_); + Blockly.bindEvent_(Blockly.svg, 'mousemove', null, Blockly.onMouseMove_); + Blockly.bindEvent_(Blockly.svg, 'contextmenu', null, Blockly.onContextMenu_); + + if (!Blockly.documentEventsBound_) { + // Only bind the window/document events once. + // Destroying and reinjecting Blockly should not bind again. + Blockly.bindEvent_(window, 'resize', document, Blockly.svgResize); + Blockly.bindEvent_(document, 'mouseup', null, Blockly.onMouseUp_); + Blockly.bindEvent_(document, 'keydown', null, Blockly.onKeyDown_); + // Some iPad versions don't fire resize after portrait to landscape change. + if (goog.userAgent.IPAD) { + Blockly.bindEvent_(window, 'orientationchange', document, function() { + Blockly.fireUiEvent(window, 'resize'); + }, false); + } + Blockly.documentEventsBound_ = true; + } + + if (Blockly.languageTree) { + if (Blockly.hasCategories) { + Blockly.Toolbox.init(); + } else { + // Build a fixed flyout with the root blocks. + Blockly.mainWorkspace.flyout_.init(Blockly.mainWorkspace, true); + Blockly.mainWorkspace.flyout_.show(Blockly.languageTree.childNodes); + // Translate the workspace sideways to avoid the fixed flyout. + Blockly.mainWorkspace.scrollX = Blockly.mainWorkspace.flyout_.width_; + var translation = 'translate(' + Blockly.mainWorkspace.scrollX + ', 0)'; + Blockly.mainWorkspace.getCanvas().setAttribute('transform', translation); + Blockly.mainWorkspace.getBubbleCanvas().setAttribute('transform', + translation); + } + } + if (Blockly.hasScrollbars) { + Blockly.mainWorkspace.scrollbar = new Blockly.ScrollbarPair( + Blockly.mainWorkspace); + Blockly.mainWorkspace.scrollbar.resize(); + } + + Blockly.mainWorkspace.addTrashcan(); + + // Load the sounds. + Blockly.loadAudio_( + ['media/click.mp3', 'media/click.wav', 'media/click.ogg'], 'click'); + Blockly.loadAudio_( + ['media/delete.mp3', 'media/delete.ogg', 'media/delete.wav'], 'delete'); +}; diff --git a/core/input.js b/core/input.js new file mode 100644 index 000000000..3c5969136 --- /dev/null +++ b/core/input.js @@ -0,0 +1,184 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Object representing an input (value, statement, or dummy). + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Input'); + +// TODO(scr): Fix circular dependencies +// goog.require('Blockly.Block'); +goog.require('Blockly.Connection'); +goog.require('Blockly.FieldLabel'); + + +/** + * Class for an input with an optional title. + * @param {number} type The type of the input. + * @param {string} name Language-neutral identifier which may used to find this + * input again. + * @param {!Blockly.Block} block The block containing this input. + * @param {Blockly.Connection} connection Optional connection for this input. + * @constructor + */ +Blockly.Input = function(type, name, block, connection) { + this.type = type; + this.name = name; + this.sourceBlock_ = block; + this.connection = connection; + this.titleRow = []; + this.align = Blockly.ALIGN_LEFT; + + this.visible_ = true; +}; + +/** + * Add an item to the end of the input's title row. + * @param {*} title Something to add as a title. + * @param {string} opt_name Language-neutral identifier which may used to find + * this title again. Should be unique to the host block. + * @return {!Blockly.Input} The input being append to (to allow chaining). + */ +Blockly.Input.prototype.appendTitle = function(title, opt_name) { + // Empty string, Null or undefined generates no title, unless title is named. + if (!title && !opt_name) { + return this; + } + // Generate a FieldLabel when given a plain text title. + if (goog.isString(title)) { + title = new Blockly.FieldLabel(/** @type {string} */ (title)); + } + if (this.sourceBlock_.svg_) { + title.init(this.sourceBlock_); + } + title.name = opt_name; + + if (title.prefixTitle) { + // Add any prefix. + this.appendTitle(title.prefixTitle); + } + // Add the title to the title row. + this.titleRow.push(title); + if (title.suffixTitle) { + // Add any suffix. + this.appendTitle(title.suffixTitle); + } + + if (this.sourceBlock_.rendered) { + this.sourceBlock_.render(); + // Adding a title will cause the block to change shape. + this.sourceBlock_.bumpNeighbours_(); + } + return this; +}; + +/** + * Gets whether this input is visible or not. + * @return {boolean} True if visible. + */ +Blockly.Input.prototype.isVisible = function() { + return this.visible_; +}; + +/** + * Sets whether this input is visible or not. + * @param {boolean} visible True if visible. + * @return {!Array.} List of blocks to render. + */ +Blockly.Input.prototype.setVisible = function(visible) { + var renderList = []; + if (this.visible_ == visible) { + return renderList; + } + this.visible_ = visible; + + var display = visible ? 'block' : 'none'; + for (var y = 0, title; title = this.titleRow[y]; y++) { + title.setVisible(visible); + } + if (this.connection) { + // Has a connection. + if (visible) { + renderList = this.connection.unhideAll(); + } else { + renderList = this.connection.hideAll(); + } + var child = this.connection.targetBlock(); + if (child) { + child.svg_.getRootElement().style.display = display; + if (!visible) { + child.rendered = false; + } + } + } + return renderList; +}; + +/** + * Change a connection's compatibility. + * @param {string|Array.|null} check Compatible value type or + * list of value types. Null if all types are compatible. + * @return {!Blockly.Input} The input being modified (to allow chaining). + */ +Blockly.Input.prototype.setCheck = function(check) { + if (!this.connection) { + throw 'This input does not have a connection.'; + } + this.connection.setCheck(check); + return this; +}; + +/** + * Change the alignment of the connection's title(s). + * @param {number} align One of Blockly.ALIGN_LEFT, ALIGN_CENTRE, ALIGN_RIGHT. + * In RTL mode directions are reversed, and ALIGN_RIGHT aligns to the left. + * @return {!Blockly.Input} The input being modified (to allow chaining). + */ +Blockly.Input.prototype.setAlign = function(align) { + this.align = align; + if (this.sourceBlock_.rendered) { + this.sourceBlock_.render(); + } + return this; +}; + +/** + * Initialize the titles on this input. + */ +Blockly.Input.prototype.init = function() { + for (var x = 0; x < this.titleRow.length; x++) { + this.titleRow[x].init(this.sourceBlock_); + } +}; + +/** + * Sever all links to this input. + */ +Blockly.Input.prototype.dispose = function() { + for (var i = 0, title; title = this.titleRow[i]; i++) { + title.dispose(); + } + if (this.connection) { + this.connection.dispose(); + } + this.sourceBlock_ = null; +}; diff --git a/core/msg.js b/core/msg.js new file mode 100644 index 000000000..7f3c16477 --- /dev/null +++ b/core/msg.js @@ -0,0 +1,30 @@ +/** + * Visual Blocks Editor + * + * Copyright 2013 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Core JavaScript library for Blockly. + * @author scr@google.com (Sheridan Rawlins) + */ +'use strict'; + +/** + * Name space for the Msg singleton. + * Msg gets populated in the message files. + */ +goog.provide('Blockly.Msg'); diff --git a/core/mutator.js b/core/mutator.js new file mode 100644 index 000000000..c3255d13f --- /dev/null +++ b/core/mutator.js @@ -0,0 +1,289 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Object representing a mutator dialog. A mutator allows the + * user to change the shape of a block using a nested blocks editor. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Mutator'); + +goog.require('Blockly.Bubble'); +goog.require('Blockly.Icon'); + + +/** + * Class for a mutator dialog. + * @param {!Array.} quarkNames List of names of sub-blocks for flyout. + * @extends {Blockly.Icon} + * @constructor + */ +Blockly.Mutator = function(quarkNames) { + Blockly.Mutator.superClass_.constructor.call(this, null); + this.quarkXml_ = []; + // Convert the list of names into a list of XML objects for the flyout. + for (var x = 0; x < quarkNames.length; x++) { + var element = goog.dom.createDom('block', {'type': quarkNames[x]}); + this.quarkXml_[x] = element; + } +}; +goog.inherits(Blockly.Mutator, Blockly.Icon); + +/** + * Width of workspace. + * @private + */ +Blockly.Mutator.prototype.workspaceWidth_ = 0; + +/** + * Height of workspace. + * @private + */ +Blockly.Mutator.prototype.workspaceHeight_ = 0; + +/** + * Create the icon on the block. + */ +Blockly.Mutator.prototype.createIcon = function() { + Blockly.Icon.prototype.createIcon_.call(this); + /* Here's the markup that will be generated: + + + */ + var quantum = Blockly.Icon.RADIUS / 2; + var iconShield = Blockly.createSvgElement('rect', + {'class': 'blocklyIconShield', + 'width': 4 * quantum, + 'height': 4 * quantum, + 'rx': quantum, + 'ry': quantum}, this.iconGroup_); + this.iconMark_ = Blockly.createSvgElement('text', + {'class': 'blocklyIconMark', + 'x': Blockly.Icon.RADIUS, + 'y': 2 * Blockly.Icon.RADIUS - 4}, this.iconGroup_); + this.iconMark_.appendChild(document.createTextNode('\u2605')); +}; + +/** + * Create the editor for the mutator's bubble. + * @return {!Element} The top-level node of the editor. + * @private + */ +Blockly.Mutator.prototype.createEditor_ = function() { + /* Create the editor. Here's the markup that will be generated: + + + [Flyout] + [Workspace] + + */ + this.svgDialog_ = Blockly.createSvgElement('svg', + {'x': Blockly.Bubble.BORDER_WIDTH, 'y': Blockly.Bubble.BORDER_WIDTH}, + null); + this.svgBackground_ = Blockly.createSvgElement('rect', + {'class': 'blocklyMutatorBackground', + 'height': '100%', 'width': '100%'}, this.svgDialog_); + + var mutator = this; + this.workspace_ = new Blockly.Workspace( + function() {return mutator.getFlyoutMetrics_();}, null); + this.flyout_ = new Blockly.Flyout(); + this.flyout_.autoClose = false; + this.svgDialog_.appendChild(this.flyout_.createDom()); + this.svgDialog_.appendChild(this.workspace_.createDom()); + return this.svgDialog_; +}; + +/** + * Callback function triggered when the bubble has resized. + * Resize the workspace accordingly. + * @private + */ +Blockly.Mutator.prototype.resizeBubble_ = function() { + var doubleBorderWidth = 2 * Blockly.Bubble.BORDER_WIDTH; + var workspaceSize = this.workspace_.getCanvas().getBBox(); + var flyoutMetrics = this.flyout_.getMetrics_(); + var width; + if (Blockly.RTL) { + width = -workspaceSize.x; + } else { + width = workspaceSize.width + workspaceSize.x; + } + var height = Math.max(workspaceSize.height + doubleBorderWidth * 3, + flyoutMetrics.contentHeight + 20); + width += doubleBorderWidth * 3; + // Only resize if the size difference is significant. Eliminates shuddering. + if (Math.abs(this.workspaceWidth_ - width) > doubleBorderWidth || + Math.abs(this.workspaceHeight_ - height) > doubleBorderWidth) { + // Record some layout information for getFlyoutMetrics_. + this.workspaceWidth_ = width; + this.workspaceHeight_ = height; + // Resize the bubble. + this.bubble_.setBubbleSize(width + doubleBorderWidth, + height + doubleBorderWidth); + this.svgDialog_.setAttribute('width', this.workspaceWidth_); + this.svgDialog_.setAttribute('height', this.workspaceHeight_); + } + + if (Blockly.RTL) { + // Scroll the workspace to always left-align. + var translation = 'translate(' + this.workspaceWidth_ + ',0)'; + this.workspace_.getCanvas().setAttribute('transform', translation); + } +}; + +/** + * Show or hide the mutator bubble. + * @param {boolean} visible True if the bubble should be visible. + */ +Blockly.Mutator.prototype.setVisible = function(visible) { + if (visible == this.isVisible()) { + // No change. + return; + } + if (visible) { + // Create the bubble. + this.bubble_ = new Blockly.Bubble(this.block_.workspace, + this.createEditor_(), this.block_.svg_.svgGroup_, + this.iconX_, this.iconY_, null, null); + var thisObj = this; + this.flyout_.init(this.workspace_, false); + this.flyout_.show(this.quarkXml_); + + this.rootBlock_ = this.block_.decompose(this.workspace_); + var blocks = this.rootBlock_.getDescendants(); + for (var i = 0, child; child = blocks[i]; i++) { + child.render(); + } + // The root block should not be dragable or deletable. + this.rootBlock_.setMovable(false); + this.rootBlock_.setDeletable(false); + var margin = this.flyout_.CORNER_RADIUS * 2; + var x = this.flyout_.width_ + margin; + if (Blockly.RTL) { + x = -x; + } + this.rootBlock_.moveBy(x, margin); + // Save the initial connections, then listen for further changes. + if (this.block_.saveConnections) { + this.block_.saveConnections(this.rootBlock_); + this.sourceListener_ = Blockly.bindEvent_( + this.block_.workspace.getCanvas(), + 'blocklyWorkspaceChange', this.block_, + function() {thisObj.block_.saveConnections(thisObj.rootBlock_)}); + } + this.resizeBubble_(); + // When the mutator's workspace changes, update the source block. + Blockly.bindEvent_(this.workspace_.getCanvas(), 'blocklyWorkspaceChange', + this.block_, function() {thisObj.workspaceChanged_();}); + this.updateColour(); + } else { + // Dispose of the bubble. + this.svgDialog_ = null; + this.svgBackground_ = null; + this.flyout_.dispose(); + this.flyout_ = null; + this.workspace_.dispose(); + this.workspace_ = null; + this.rootBlock_ = null; + this.bubble_.dispose(); + this.bubble_ = null; + this.workspaceWidth_ = 0; + this.workspaceHeight_ = 0; + if (this.sourceListener_) { + Blockly.unbindEvent_(this.sourceListener_); + this.sourceListener_ = null; + } + } +}; + +/** + * Update the source block when the mutator's blocks are changed. + * Delete or bump any block that's out of bounds. + * Fired whenever a change is made to the mutator's workspace. + * @private + */ +Blockly.Mutator.prototype.workspaceChanged_ = function() { + if (Blockly.Block.dragMode_ == 0) { + var blocks = this.workspace_.getTopBlocks(false); + var MARGIN = 20; + for (var b = 0, block; block = blocks[b]; b++) { + var blockXY = block.getRelativeToSurfaceXY(); + var blockHW = block.getHeightWidth(); + if (Blockly.RTL ? blockXY.x > -this.flyout_.width_ + MARGIN : + blockXY.x < this.flyout_.width_ - MARGIN) { + // Delete any block that's sitting on top of the flyout. + block.dispose(false, true); + } else if (blockXY.y + blockHW.height < MARGIN) { + // Bump any block that's above the top back inside. + block.moveBy(0, MARGIN - blockHW.height - blockXY.y); + } + } + } + + // When the mutator's workspace changes, update the source block. + if (this.rootBlock_.workspace == this.workspace_) { + // Switch off rendering while the source block is rebuilt. + var savedRendered = this.block_.rendered; + this.block_.rendered = false; + // Allow the source block to rebuild itself. + this.block_.compose(this.rootBlock_); + // Restore rendering and show the changes. + this.block_.rendered = savedRendered; + if (this.block_.rendered) { + this.block_.render(); + } + this.resizeBubble_(); + // The source block may have changed, notify its workspace. + this.block_.workspace.fireChangeEvent(); + } +}; + +/** + * Return an object with all the metrics required to size scrollbars for the + * mutator flyout. The following properties are computed: + * .viewHeight: Height of the visible rectangle, + * .absoluteTop: Top-edge of view. + * .absoluteLeft: Left-edge of view. + * @return {!Object} Contains size and position metrics of mutator dialog's + * workspace. + * @private + */ +Blockly.Mutator.prototype.getFlyoutMetrics_ = function() { + var left = 0; + if (Blockly.RTL) { + left += this.workspaceWidth_; + } + return { + viewHeight: this.workspaceHeight_, + viewWidth: 0, // This seem wrong, but results in correct RTL layout. + absoluteTop: 0, + absoluteLeft: left + }; +}; + +/** + * Dispose of this mutator. + */ +Blockly.Mutator.prototype.dispose = function() { + this.block_.mutator = null; + Blockly.Icon.prototype.dispose.call(this); +}; diff --git a/core/names.js b/core/names.js new file mode 100644 index 000000000..f56298706 --- /dev/null +++ b/core/names.js @@ -0,0 +1,135 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Utility functions for handling variables and procedure names. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Names'); + + +/** + * Class for a database of entity names (variables, functions, etc). + * @param {string} reservedWords A comma-separated string of words that are + * illegal for use as names in a language (e.g. 'new,if,this,...'). + * @constructor + */ +Blockly.Names = function(reservedWords) { + this.reservedDict_ = Object.create(null); + if (reservedWords) { + var splitWords = reservedWords.split(','); + for (var x = 0; x < splitWords.length; x++) { + this.reservedDict_[splitWords[x]] = true; + } + } + this.reset(); +}; + +/** + * When JavaScript (or most other languages) is generated, variable 'foo' and + * procedure 'foo' would collide. However, Blockly has no such problems since + * variable get 'foo' and procedure call 'foo' are unambiguous. + * Therefore, Blockly keeps a separate type name to disambiguate. + * getName('foo', 'variable') -> 'foo' + * getName('foo', 'procedure') -> 'foo2' + */ + +/** + * Empty the database and start from scratch. The reserved words are kept. + */ +Blockly.Names.prototype.reset = function() { + this.db_ = Object.create(null); + this.dbReverse_ = Object.create(null); +}; + +/** + * Convert a Blockly entity name to a legal exportable entity name. + * @param {string} name The Blockly entity name (no constraints). + * @param {string} type The type of entity in Blockly + * ('VARIABLE', 'PROCEDURE', 'BUILTIN', etc...). + * @return {string} An entity name legal for the exported language. + */ +Blockly.Names.prototype.getName = function(name, type) { + var normalized = name.toLowerCase() + '_' + type; + if (normalized in this.db_) { + return this.db_[normalized]; + } + var safeName = this.getDistinctName(name, type); + this.db_[normalized] = safeName; + return safeName; +}; + +/** + * Convert a Blockly entity name to a legal exportable entity name. + * Ensure that this is a new name not overlapping any previously defined name. + * Also check against list of reserved words for the current language and + * ensure name doesn't collide. + * @param {string} name The Blockly entity name (no constraints). + * @param {string} type The type of entity in Blockly + * ('VARIABLE', 'PROCEDURE', 'BUILTIN', etc...). + * @return {string} An entity name legal for the exported language. + */ +Blockly.Names.prototype.getDistinctName = function(name, type) { + var safeName = this.safeName_(name); + var i = ''; + while (this.dbReverse_[safeName + i] || + (safeName + i) in this.reservedDict_) { + // Collision with existing name. Create a unique name. + i = i ? i + 1 : 2; + } + safeName += i; + this.dbReverse_[safeName] = true; + return safeName; +}; + +/** + * Given a proposed entity name, generate a name that conforms to the + * [_A-Za-z][_A-Za-z0-9]* format that most languages consider legal for + * variables. + * @param {string} name Potentially illegal entity name. + * @return {string} Safe entity name. + * @private + */ +Blockly.Names.prototype.safeName_ = function(name) { + if (!name) { + name = 'unnamed'; + } else { + // Unfortunately names in non-latin characters will look like + // _E9_9F_B3_E4_B9_90 which is pretty meaningless. + name = encodeURI(name.replace(/ /g, '_')).replace(/[^\w]/g, '_'); + // Most languages don't allow names with leading numbers. + if ('0123456789'.indexOf(name[0]) != -1) { + name = 'my_' + name; + } + } + return name; +}; + +/** + * Do the given two entity names refer to the same entity? + * Blockly names are case-insensitive. + * @param {string} name1 First name. + * @param {string} name2 Second name. + * @return {boolean} True if names are the same. + */ +Blockly.Names.equals = function(name1, name2) { + return name1.toLowerCase() == name2.toLowerCase(); +}; diff --git a/core/procedures.js b/core/procedures.js new file mode 100644 index 000000000..9bf518725 --- /dev/null +++ b/core/procedures.js @@ -0,0 +1,284 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Utility functions for handling procedures. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Procedures'); + +// TODO(scr): Fix circular dependencies +// goog.require('Blockly.Block'); +goog.require('Blockly.FieldVariable'); +goog.require('Blockly.Names'); +goog.require('Blockly.Workspace'); + + +/** + * Category to separate procedure names from variables and generated functions. + */ +Blockly.Procedures.NAME_TYPE = 'PROCEDURE'; + +/** + * Find all user-created procedure definitions. + * @return {!Array.>} Pair of arrays, the + * first contains procedures without return variables, the second with. + * Each procedure is defined by a three-element list of name, parameter + * list, and return value boolean. + */ +Blockly.Procedures.allProcedures = function() { + var blocks = Blockly.mainWorkspace.getAllBlocks(); + var proceduresReturn = []; + var proceduresNoReturn = []; + for (var x = 0; x < blocks.length; x++) { + var func = blocks[x].getProcedureDef; + if (func) { + var tuple = func.call(blocks[x]); + if (tuple) { + if (tuple[2]) { + proceduresReturn.push(tuple); + } else { + proceduresNoReturn.push(tuple); + } + } + } + } + + proceduresNoReturn.sort(Blockly.Procedures.procTupleComparator_); + proceduresReturn.sort(Blockly.Procedures.procTupleComparator_); + return [proceduresNoReturn, proceduresReturn]; +}; + +/** + * Comparison function for case-insensitive sorting of the first element of + * a tuple. + * @param {!Array} ta First tuple. + * @param {!Array} tb Second tuple. + * @return {number} -1, 0, or 1 to signify greater than, equality, or less than. + * @private + */ +Blockly.Procedures.procTupleComparator_ = function(ta, tb) { + var a = ta[0].toLowerCase(); + var b = tb[0].toLowerCase(); + if (a > b) { + return 1; + } + if (a < b) { + return -1; + } + return 0; +}; + +/** + * Ensure two identically-named procedures don't exist. + * @param {string} name Proposed procedure name. + * @param {!Blockly.Block} block Block to disambiguate. + * @return {string} Non-colliding name. + */ +Blockly.Procedures.findLegalName = function(name, block) { + if (block.isInFlyout) { + // Flyouts can have multiple procedures called 'procedure'. + return name; + } + while (!Blockly.Procedures.isLegalName(name, block.workspace, block)) { + // Collision with another procedure. + var r = name.match(/^(.*?)(\d+)$/); + if (!r) { + name += '2'; + } else { + name = r[1] + (parseInt(r[2], 10) + 1); + } + } + return name; +}; + +/** + * Does this procedure have a legal name? Illegal names include names of + * procedures already defined. + * @param {string} name The questionable name. + * @param {!Blockly.Workspace} workspace The workspace to scan for collisions. + * @param {Blockly.Block} opt_exclude Optional block to exclude from + * comparisons (one doesn't want to collide with oneself). + * @return {boolean} True if the name is legal. + */ +Blockly.Procedures.isLegalName = function(name, workspace, opt_exclude) { + var blocks = workspace.getAllBlocks(); + // Iterate through every block and check the name. + for (var x = 0; x < blocks.length; x++) { + if (blocks[x] == opt_exclude) { + continue; + } + var func = blocks[x].getProcedureDef; + if (func) { + var procName = func.call(blocks[x]); + if (Blockly.Names.equals(procName[0], name)) { + return false; + } + } + } + return true; +}; + +/** + * Rename a procedure. Called by the editable field. + * @param {string} text The proposed new name. + * @return {string} The accepted name. + * @this {!Blockly.FieldVariable} + */ +Blockly.Procedures.rename = function(text) { + // Strip leading and trailing whitespace. Beyond this, all names are legal. + text = text.replace(/^[\s\xa0]+|[\s\xa0]+$/g, ''); + + // Ensure two identically-named procedures don't exist. + text = Blockly.Procedures.findLegalName(text, this.sourceBlock_); + // Rename any callers. + var blocks = this.sourceBlock_.workspace.getAllBlocks(); + for (var x = 0; x < blocks.length; x++) { + var func = blocks[x].renameProcedure; + if (func) { + func.call(blocks[x], this.text_, text); + } + } + return text; +}; + +/** + * Construct the blocks required by the flyout for the procedure category. + * @param {!Array.} blocks List of blocks to show. + * @param {!Array.} gaps List of widths between blocks. + * @param {number} margin Standard margin width for calculating gaps. + * @param {!Blockly.Workspace} workspace The flyout's workspace. + */ +Blockly.Procedures.flyoutCategory = function(blocks, gaps, margin, workspace) { + if (Blockly.Blocks['procedures_defnoreturn']) { + var block = new Blockly.Block(workspace, 'procedures_defnoreturn'); + block.initSvg(); + blocks.push(block); + gaps.push(margin * 2); + } + if (Blockly.Blocks['procedures_defreturn']) { + var block = new Blockly.Block(workspace, 'procedures_defreturn'); + block.initSvg(); + blocks.push(block); + gaps.push(margin * 2); + } + if (Blockly.Blocks['procedures_ifreturn']) { + var block = new Blockly.Block(workspace, 'procedures_ifreturn'); + block.initSvg(); + blocks.push(block); + gaps.push(margin * 2); + } + if (gaps.length) { + // Add slightly larger gap between system blocks and user calls. + gaps[gaps.length - 1] = margin * 3; + } + + function populateProcedures(procedureList, templateName) { + for (var x = 0; x < procedureList.length; x++) { + var block = new Blockly.Block(workspace, templateName); + block.setTitleValue(procedureList[x][0], 'NAME'); + var tempIds = []; + for (var t = 0; t < procedureList[x][1].length; t++) { + tempIds[t] = 'ARG' + t; + } + block.setProcedureParameters(procedureList[x][1], tempIds); + block.initSvg(); + blocks.push(block); + gaps.push(margin * 2); + } + } + + var tuple = Blockly.Procedures.allProcedures(); + populateProcedures(tuple[0], 'procedures_callnoreturn'); + populateProcedures(tuple[1], 'procedures_callreturn'); +}; + +/** + * Find all the callers of a named procedure. + * @param {string} name Name of procedure. + * @param {!Blockly.Workspace} workspace The workspace to find callers in. + * @return {!Array.} Array of caller blocks. + */ +Blockly.Procedures.getCallers = function(name, workspace) { + var callers = []; + var blocks = workspace.getAllBlocks(); + // Iterate through every block and check the name. + for (var x = 0; x < blocks.length; x++) { + var func = blocks[x].getProcedureCall; + if (func) { + var procName = func.call(blocks[x]); + // Procedure name may be null if the block is only half-built. + if (procName && Blockly.Names.equals(procName, name)) { + callers.push(blocks[x]); + } + } + } + return callers; +}; + +/** + * When a procedure definition is disposed of, find and dispose of all its + * callers. + * @param {string} name Name of deleted procedure definition. + * @param {!Blockly.Workspace} workspace The workspace to delete callers from. + */ +Blockly.Procedures.disposeCallers = function(name, workspace) { + var callers = Blockly.Procedures.getCallers(name, workspace); + for (var x = 0; x < callers.length; x++) { + callers[x].dispose(true, false); + } +}; + +/** + * When a procedure definition changes its parameters, find and edit all its + * callers. + * @param {string} name Name of edited procedure definition. + * @param {!Blockly.Workspace} workspace The workspace to delete callers from. + * @param {!Array.} paramNames Array of new parameter names. + * @param {!Array.} paramIds Array of unique parameter IDs. + */ +Blockly.Procedures.mutateCallers = function(name, workspace, + paramNames, paramIds) { + var callers = Blockly.Procedures.getCallers(name, workspace); + for (var x = 0; x < callers.length; x++) { + callers[x].setProcedureParameters(paramNames, paramIds); + } +}; + +/** + * Find the definition block for the named procedure. + * @param {string} name Name of procedure. + * @param {!Blockly.Workspace} workspace The workspace to search. + * @return {Blockly.Block} The procedure definition block, or null not found. + */ +Blockly.Procedures.getDefinition = function(name, workspace) { + var blocks = workspace.getAllBlocks(); + for (var x = 0; x < blocks.length; x++) { + var func = blocks[x].getProcedureDef; + if (func) { + var tuple = func.call(blocks[x]); + if (tuple && Blockly.Names.equals(tuple[0], name)) { + return blocks[x]; + } + } + } + return null; +}; diff --git a/core/scrollbar.js b/core/scrollbar.js new file mode 100644 index 000000000..6c98d5fe9 --- /dev/null +++ b/core/scrollbar.js @@ -0,0 +1,908 @@ +/** + * Visual Blocks Editor + * + * Copyright 2011 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Library for creating scrollbars. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Scrollbar'); +goog.provide('Blockly.ScrollbarPair'); + +goog.require('goog.userAgent'); + + +/** + * Class for a pair of scrollbars. Horizontal and vertical. + * @param {!Blockly.Workspace} workspace Workspace to bind the scrollbars to. + * @constructor + */ +Blockly.ScrollbarPair = function(workspace) { + this.workspace_ = workspace; + this.oldHostMetrics_ = null; + this.hScroll = new Blockly.Scrollbar(workspace, true, true); + this.vScroll = new Blockly.Scrollbar(workspace, false, true); + this.corner_ = Blockly.createSvgElement('rect', + {'height': Blockly.Scrollbar.scrollbarThickness, + 'width': Blockly.Scrollbar.scrollbarThickness, + 'style': 'fill: #fff'}, null); + Blockly.Scrollbar.insertAfter_(this.corner_, workspace.getBubbleCanvas()); +}; + +/** + * Dispose of this pair of scrollbars. + * Unlink from all DOM elements to prevent memory leaks. + */ +Blockly.ScrollbarPair.prototype.dispose = function() { + Blockly.unbindEvent_(this.onResizeWrapper_); + this.onResizeWrapper_ = null; + goog.dom.removeNode(this.corner_); + this.corner_ = null; + this.workspace_ = null; + this.oldHostMetrics_ = null; + this.hScroll.dispose(); + this.hScroll = null; + this.vScroll.dispose(); + this.vScroll = null; +}; + +/** + * Recalculate both of the scrollbars' locations and lengths. + * Also reposition the corner rectangle. + */ +Blockly.ScrollbarPair.prototype.resize = function() { + // Look up the host metrics once, and use for both scrollbars. + var hostMetrics = this.workspace_.getMetrics(); + if (!hostMetrics) { + // Host element is likely not visible. + return; + } + + // Only change the scrollbars if there has been a change in metrics. + var resizeH = false; + var resizeV = false; + if (!this.oldHostMetrics_ || + this.oldHostMetrics_.viewWidth != hostMetrics.viewWidth || + this.oldHostMetrics_.viewHeight != hostMetrics.viewHeight || + this.oldHostMetrics_.absoluteTop != hostMetrics.absoluteTop || + this.oldHostMetrics_.absoluteLeft != hostMetrics.absoluteLeft) { + // The window has been resized or repositioned. + resizeH = true; + resizeV = true; + } else { + // Has the content been resized or moved? + if (!this.oldHostMetrics_ || + this.oldHostMetrics_.contentWidth != hostMetrics.contentWidth || + this.oldHostMetrics_.viewLeft != hostMetrics.viewLeft || + this.oldHostMetrics_.contentLeft != hostMetrics.contentLeft) { + resizeH = true; + } + if (!this.oldHostMetrics_ || + this.oldHostMetrics_.contentHeight != hostMetrics.contentHeight || + this.oldHostMetrics_.viewTop != hostMetrics.viewTop || + this.oldHostMetrics_.contentTop != hostMetrics.contentTop) { + resizeV = true; + } + } + if (resizeH) { + this.hScroll.resize(hostMetrics); + } + if (resizeV) { + this.vScroll.resize(hostMetrics); + } + + // Reposition the corner square. + if (!this.oldHostMetrics_ || + this.oldHostMetrics_.viewWidth != hostMetrics.viewWidth || + this.oldHostMetrics_.absoluteLeft != hostMetrics.absoluteLeft) { + this.corner_.setAttribute('x', this.vScroll.xCoordinate); + } + if (!this.oldHostMetrics_ || + this.oldHostMetrics_.viewHeight != hostMetrics.viewHeight || + this.oldHostMetrics_.absoluteTop != hostMetrics.absoluteTop) { + this.corner_.setAttribute('y', this.hScroll.yCoordinate); + } + + // Cache the current metrics to potentially short-cut the next resize event. + this.oldHostMetrics_ = hostMetrics; +}; + +/** + * Set the sliders of both scrollbars to be at a certain position. + * @param {number} x Horizontal scroll value. + * @param {number} y Vertical scroll value. + */ +Blockly.ScrollbarPair.prototype.set = function(x, y) { + /* HACK: + Two scrollbars are about to have their sliders moved. Moving a scrollbar + will normally result in its onScroll function being called. That function + will update the contents. At issue is what happens when two scrollbars are + moved. Calling onScroll twice may result in two rerenderings of the content + and increase jerkiness during dragging. + In the case of native scrollbars (currently used only by Firefox), onScroll + is called as an event, which means two separate renderings of the content are + performed. However in the case of SVG scrollbars (currently used by all + other browsers), onScroll is called as a function and the browser only + rerenders the contents once at the end of the thread. + */ + if (Blockly.Scrollbar === Blockly.ScrollbarNative) { + // Native scrollbar mode. + // Set both scrollbars and suppress their two separate onScroll events. + this.hScroll.set(x, false); + this.vScroll.set(y, false); + // Redraw the surface once with the new settings for both scrollbars. + var xyRatio = {}; + xyRatio.x = (this.hScroll.outerDiv_.scrollLeft / + this.hScroll.innerImg_.offsetWidth) || 0; + xyRatio.y = (this.vScroll.outerDiv_.scrollTop / + this.vScroll.innerImg_.offsetHeight) || 0; + this.workspace_.setMetrics(xyRatio); + } else { + // SVG scrollbars. + // Set both scrollbars and allow each to call a separate onScroll execution. + this.hScroll.set(x, true); + this.vScroll.set(y, true); + } +}; + +// -------------------------------------------------------------------- + +/** + * Common properties and methods for ScrollbarNative and ScrollbarSvg. + * Prevents the compiler from choosing incompatible names for properties on + * each. + * @interface + */ +Blockly.ScrollbarInterface = function() {}; +/** + * Dispose of this scrollbar. + */ +Blockly.ScrollbarInterface.prototype.dispose = function() {}; +/** + * Recalculate the scrollbar's location and its length. + */ +Blockly.ScrollbarInterface.prototype.resize = function() {}; +/** + * Is the scrollbar visible. + * @return {boolean} True if visible. + */ +Blockly.ScrollbarInterface.prototype.isVisible = function() {}; +/** + * Set whether the scrollbar is visible. + * @param {boolean} visible True if visible. + */ +Blockly.ScrollbarInterface.prototype.setVisible = function(visible) {}; +/** + * Set the scrollbar slider's position. + * @param {number} value The distance from the top/left end of the bar. + * @param {boolean} fireEvents True if onScroll events should be fired. + */ +Blockly.ScrollbarInterface.prototype.set = function(value, fireEvents) {}; + +// -------------------------------------------------------------------- + +/** + * Class for a native widget scrollbar nested in a foreignObject element. + * This technique offers a scrollbar that looks and behaves like the system's + * scrollbars. However it isn't well supported at the moment. + * @param {!Blockly.Workspace} workspace Workspace to bind the scrollbar to. + * @param {?boolean} horizontal True if horizontal, false if vertical. + * Null is used to create a test scrollbar to measure thickness. + * @param {boolean=} opt_pair True if the scrollbar is part of a + * horizontal/vertical pair. + * @constructor + * @implements {Blockly.ScrollbarInterface} + */ +Blockly.ScrollbarNative = function(workspace, horizontal, opt_pair) { + this.workspace_ = workspace; + this.pair_ = opt_pair || false; + this.horizontal_ = horizontal; + + this.createDom_(); + if (horizontal === null) { + // Just return a bare-bones scrollbar DOM for thickness testing. + return; + } + if (!Blockly.Scrollbar.scrollbarThickness) { + // The first time a scrollbar is created, we need to measure the thickness. + Blockly.ScrollbarNative.measureScrollbarThickness_(workspace); + } + + if (horizontal) { + this.foreignObject_.setAttribute('height', + Blockly.Scrollbar.scrollbarThickness); + this.outerDiv_.style.height = + Blockly.Scrollbar.scrollbarThickness + 'px'; + this.outerDiv_.style.overflowX = 'scroll'; + this.outerDiv_.style.overflowY = 'hidden'; + this.innerImg_.style.height = '1px'; + } else { + this.foreignObject_.setAttribute('width', + Blockly.Scrollbar.scrollbarThickness); + this.outerDiv_.style.width = + Blockly.Scrollbar.scrollbarThickness + 'px'; + this.outerDiv_.style.overflowX = 'hidden'; + this.outerDiv_.style.overflowY = 'scroll'; + this.innerImg_.style.width = '1px'; + } + var scrollbar = this; + this.onScrollWrapper_ = Blockly.bindEvent_(this.outerDiv_, 'scroll', + scrollbar, function() {scrollbar.onScroll_();}); + Blockly.bindEvent_(this.foreignObject_, 'mousedown', null, + function(e) {Blockly.hideChaff(true); Blockly.noEvent(e);}); +}; + +/** + * Dispose of this scrollbar. + * Unlink from all DOM elements to prevent memory leaks. + */ +Blockly.ScrollbarNative.prototype.dispose = function() { + Blockly.unbindEvent_(this.onResizeWrapper_); + this.onResizeWrapper_ = null; + Blockly.unbindEvent_(this.onScrollWrapper_); + this.onScrollWrapper_ = null; + goog.dom.removeNode(this.foreignObject_); + this.foreignObject_ = null; + this.workspace_ = null; + this.outerDiv_ = null; + this.innerImg_ = null; +}; + +/** + * Recalculate the scrollbar's location and its length. + * @param {Object=} opt_metrics A data structure of from the describing all the + * required dimensions. If not provided, it will be fetched from the host + * object. + */ +Blockly.ScrollbarNative.prototype.resize = function(opt_metrics) { + // Determine the location, height and width of the host element. + var hostMetrics = opt_metrics; + if (!hostMetrics) { + hostMetrics = this.workspace_.getMetrics(); + if (!hostMetrics) { + // Host element is likely not visible. + return; + } + } + /* hostMetrics is an object with the following properties. + * .viewHeight: Height of the visible rectangle, + * .viewWidth: Width of the visible rectangle, + * .contentHeight: Height of the contents, + * .contentWidth: Width of the content, + * .viewTop: Offset of top edge of visible rectangle from parent, + * .viewLeft: Offset of left edge of visible rectangle from parent, + * .contentTop: Offset of the top-most content from the y=0 coordinate, + * .contentLeft: Offset of the left-most content from the x=0 coordinate, + * .absoluteTop: Top-edge of view. + * .absoluteLeft: Left-edge of view. + */ + if (this.horizontal_) { + var outerLength = hostMetrics.viewWidth; + if (this.pair_) { + // Shorten the scrollbar to make room for the corner square. + outerLength -= Blockly.Scrollbar.scrollbarThickness; + } else { + // Only show the scrollbar if needed. + // Ideally this would also apply to scrollbar pairs, but that's a bigger + // headache (due to interactions with the corner square). + this.setVisible(outerLength < hostMetrics.contentWidth); + } + this.ratio_ = outerLength / hostMetrics.viewWidth; + var innerLength = this.ratio_ * hostMetrics.contentWidth; + var innerOffset = (hostMetrics.viewLeft - hostMetrics.contentLeft) * + this.ratio_; + this.outerDiv_.style.width = outerLength + 'px'; + this.innerImg_.style.width = innerLength + 'px'; + this.xCoordinate = hostMetrics.absoluteLeft; + if (this.pair_ && Blockly.RTL) { + this.xCoordinate += Blockly.Scrollbar.scrollbarThickness; + } + this.yCoordinate = hostMetrics.absoluteTop + hostMetrics.viewHeight - + Blockly.Scrollbar.scrollbarThickness; + this.foreignObject_.setAttribute('x', this.xCoordinate); + this.foreignObject_.setAttribute('y', this.yCoordinate); + this.foreignObject_.setAttribute('width', Math.max(0, outerLength)); + this.outerDiv_.scrollLeft = Math.round(innerOffset); + } else { + var outerLength = hostMetrics.viewHeight; + if (this.pair_) { + // Shorten the scrollbar to make room for the corner square. + outerLength -= Blockly.Scrollbar.scrollbarThickness; + } else { + // Only show the scrollbar if needed. + this.setVisible(outerLength < hostMetrics.contentHeight); + } + this.ratio_ = outerLength / hostMetrics.viewHeight; + var innerLength = this.ratio_ * hostMetrics.contentHeight; + var innerOffset = (hostMetrics.viewTop - hostMetrics.contentTop) * + this.ratio_; + this.outerDiv_.style.height = outerLength + 'px'; + this.innerImg_.style.height = innerLength + 'px'; + this.xCoordinate = hostMetrics.absoluteLeft; + if (!Blockly.RTL) { + this.xCoordinate += hostMetrics.viewWidth - + Blockly.Scrollbar.scrollbarThickness; + } + this.yCoordinate = hostMetrics.absoluteTop; + this.foreignObject_.setAttribute('x', this.xCoordinate); + this.foreignObject_.setAttribute('y', this.yCoordinate); + this.foreignObject_.setAttribute('height', Math.max(0, outerLength)); + this.outerDiv_.scrollTop = Math.round(innerOffset); + } +}; + +/** + * Create all the DOM elements required for a scrollbar. + * The resulting widget is not sized. + * @private + */ +Blockly.ScrollbarNative.prototype.createDom_ = function() { + /* Create the following DOM: + + +
    + +
    + +
    + */ + this.foreignObject_ = Blockly.createSvgElement('foreignObject', {}, null); + var body = document.createElementNS(Blockly.HTML_NS, 'body'); + body.setAttribute('xmlns', Blockly.HTML_NS); + body.setAttribute('class', 'blocklyMinimalBody'); + var outer = document.createElementNS(Blockly.HTML_NS, 'div'); + this.outerDiv_ = outer; + var inner = document.createElementNS(Blockly.HTML_NS, 'img'); + inner.setAttribute('src', Blockly.pathToBlockly + 'media/1x1.gif'); + this.innerImg_ = inner; + + outer.appendChild(inner); + body.appendChild(outer); + this.foreignObject_.appendChild(body); + Blockly.Scrollbar.insertAfter_(this.foreignObject_, + this.workspace_.getBubbleCanvas()); +}; + +/** + * Is the scrollbar visible. Non-paired scrollbars disappear when they aren't + * needed. + * @return {boolean} True if visible. + */ +Blockly.ScrollbarNative.prototype.isVisible = function() { + return this.foreignObject_.style.display != 'none'; +}; + +/** + * Set whether the scrollbar is visible. + * Only applies to non-paired scrollbars. + * @param {boolean} visible True if visible. + */ +Blockly.ScrollbarNative.prototype.setVisible = function(visible) { + if (visible == this.isVisible()) { + return; + } + // Ideally this would also apply to scrollbar pairs, but that's a bigger + // headache (due to interactions with the corner square). + if (this.pair_) { + throw 'Unable to toggle visibility of paired scrollbars.'; + } + if (visible) { + this.foreignObject_.style.display = 'block'; + /* HACK: + For some reason Firefox requires the metrics to be recalculated after + displaying the scrollbar. Even though the metrics are identical and + calculating these metrics has no side effects. Failure to do so + results in a scrollbar that's crushed to 0 in an off-scale range. + */ + this.workspace_.getMetrics(); + } else { + // Hide the scrollbar. + this.workspace_.setMetrics({x: 0, y: 0}); + this.foreignObject_.style.display = 'none'; + } +}; + +/** + * Called when scrollbar is dragged. + * @private + */ +Blockly.ScrollbarNative.prototype.onScroll_ = function() { + var xyRatio = {}; + if (this.horizontal_) { + xyRatio.x = (this.outerDiv_.scrollLeft / this.innerImg_.offsetWidth) || 0; + } else { + xyRatio.y = (this.outerDiv_.scrollTop / this.innerImg_.offsetHeight) || 0; + } + this.workspace_.setMetrics(xyRatio); +}; + +/** + * Set the scrollbar slider's position. + * @param {number} value The distance from the top/left end of the bar. + * @param {boolean} fireEvents True if onScroll events should be fired. + */ +Blockly.ScrollbarNative.prototype.set = function(value, fireEvents) { + // If the scrollbar is part of a pair, it is slightly shorter than the view + // and the value needs to be scaled accordingly. + if (!fireEvents && this.onScrollWrapper_) { + // Temporarily suppress the onscroll event handler. + var scrollFunc = Blockly.unbindEvent_(this.onScrollWrapper_); + } + // Move the scrollbar slider. + if (this.horizontal_) { + this.outerDiv_.scrollLeft = value * this.ratio_; + } else { + this.outerDiv_.scrollTop = value * this.ratio_; + } + if (scrollFunc) { + // Re-enable the onscroll event handler. + var scrollbar = this; + this.onScrollWrapper_ = Blockly.bindEvent_(this.outerDiv_, 'scroll', + scrollbar, scrollFunc); + } +}; + +/** + * Mutilate this scrollbar to measure the thickness of an HTML scrollbar. + * @param {!Blockly.Workspace} workspace Workspace to bind the scrollbar to. + * @private + */ +Blockly.ScrollbarNative.measureScrollbarThickness_ = function(workspace) { + var testBar = new Blockly.ScrollbarNative(workspace, null, false); + + testBar.outerDiv_.style.width = '100px'; + testBar.outerDiv_.style.height = '100px'; + testBar.innerImg_.style.width = '100%'; + testBar.innerImg_.style.height = '200px'; + // Trivia: failure to set a height and width results in Firefox returning + // a scrollbar width of -85 instead of 15. + testBar.foreignObject_.setAttribute('width', 1); + testBar.foreignObject_.setAttribute('height', 1); + + // Measure the width of the inner-most div. + testBar.outerDiv_.style.overflowY = 'scroll'; + var w1 = testBar.innerImg_.offsetWidth; + // Turn off scrollbars and remeasure. + testBar.outerDiv_.style.overflowY = 'hidden'; + var w2 = testBar.innerImg_.offsetWidth; + + // Dispose of the test scrollbar. + goog.dom.removeNode(testBar.foreignObject_); + + var thickness = w2 - w1; + if (thickness <= 0) { + // Chrome for OS X 10.7 (Lion) floats scrollbars over the content, meaning + // that there is no way to measure the thickness. Pick a default. + thickness = 15; + } + Blockly.Scrollbar.scrollbarThickness = thickness; +}; + +// -------------------------------------------------------------------- + +/** + * Class for a pure SVG scrollbar. + * This technique offers a scrollbar that is guaranteed to work, but may not + * look or behave like the system's scrollbars. + * @param {!Blockly.Workspace} workspace Workspace to bind the scrollbar to. + * @param {boolean} horizontal True if horizontal, false if vertical. + * @param {boolean} opt_pair True if the scrollbar is part of a horiz/vert pair. + * @constructor + * @implements {Blockly.ScrollbarInterface} + */ +Blockly.ScrollbarSvg = function(workspace, horizontal, opt_pair) { + this.workspace_ = workspace; + this.pair_ = opt_pair || false; + this.horizontal_ = horizontal; + + this.createDom_(); + + if (horizontal) { + this.svgBackground_.setAttribute('height', + Blockly.Scrollbar.scrollbarThickness); + this.svgKnob_.setAttribute('height', + Blockly.Scrollbar.scrollbarThickness - 6); + this.svgKnob_.setAttribute('y', 3); + } else { + this.svgBackground_.setAttribute('width', + Blockly.Scrollbar.scrollbarThickness); + this.svgKnob_.setAttribute('width', + Blockly.Scrollbar.scrollbarThickness - 6); + this.svgKnob_.setAttribute('x', 3); + } + var scrollbar = this; + this.onMouseDownBarWrapper_ = Blockly.bindEvent_(this.svgBackground_, + 'mousedown', scrollbar, scrollbar.onMouseDownBar_); + this.onMouseDownKnobWrapper_ = Blockly.bindEvent_(this.svgKnob_, + 'mousedown', scrollbar, scrollbar.onMouseDownKnob_); +}; + +/** + * Dispose of this scrollbar. + * Unlink from all DOM elements to prevent memory leaks. + */ +Blockly.ScrollbarSvg.prototype.dispose = function() { + this.onMouseUpKnob_(); + if (this.onResizeWrapper_) { + Blockly.unbindEvent_(this.onResizeWrapper_); + this.onResizeWrapper_ = null; + } + Blockly.unbindEvent_(this.onMouseDownBarWrapper_); + this.onMouseDownBarWrapper_ = null; + Blockly.unbindEvent_(this.onMouseDownKnobWrapper_); + this.onMouseDownKnobWrapper_ = null; + + goog.dom.removeNode(this.svgGroup_); + this.svgGroup_ = null; + this.svgBackground_ = null; + this.svgKnob_ = null; + this.workspace_ = null; +}; + +/** + * Recalculate the scrollbar's location and its length. + * @param {Object=} opt_metrics A data structure of from the describing all the + * required dimensions. If not provided, it will be fetched from the host + * object. + */ +Blockly.ScrollbarSvg.prototype.resize = function(opt_metrics) { + // Determine the location, height and width of the host element. + var hostMetrics = opt_metrics; + if (!hostMetrics) { + hostMetrics = this.workspace_.getMetrics(); + if (!hostMetrics) { + // Host element is likely not visible. + return; + } + } + /* hostMetrics is an object with the following properties. + * .viewHeight: Height of the visible rectangle, + * .viewWidth: Width of the visible rectangle, + * .contentHeight: Height of the contents, + * .contentWidth: Width of the content, + * .viewTop: Offset of top edge of visible rectangle from parent, + * .viewLeft: Offset of left edge of visible rectangle from parent, + * .contentTop: Offset of the top-most content from the y=0 coordinate, + * .contentLeft: Offset of the left-most content from the x=0 coordinate, + * .absoluteTop: Top-edge of view. + * .absoluteLeft: Left-edge of view. + */ + if (this.horizontal_) { + var outerLength = hostMetrics.viewWidth; + if (this.pair_) { + // Shorten the scrollbar to make room for the corner square. + outerLength -= Blockly.Scrollbar.scrollbarThickness; + } else { + // Only show the scrollbar if needed. + // Ideally this would also apply to scrollbar pairs, but that's a bigger + // headache (due to interactions with the corner square). + this.setVisible(outerLength < hostMetrics.contentHeight); + } + this.ratio_ = outerLength / hostMetrics.contentWidth; + if (this.ratio_ === -Infinity || this.ratio_ === Infinity || + isNaN(this.ratio_)) { + this.ratio_ = 0; + } + var innerLength = hostMetrics.viewWidth * this.ratio_; + var innerOffset = (hostMetrics.viewLeft - hostMetrics.contentLeft) * + this.ratio_; + this.svgKnob_.setAttribute('width', Math.max(0, innerLength)); + this.xCoordinate = hostMetrics.absoluteLeft; + if (this.pair_ && Blockly.RTL) { + this.xCoordinate += hostMetrics.absoluteLeft + + Blockly.Scrollbar.scrollbarThickness; + } + this.yCoordinate = hostMetrics.absoluteTop + hostMetrics.viewHeight - + Blockly.Scrollbar.scrollbarThickness; + this.svgGroup_.setAttribute('transform', + 'translate(' + this.xCoordinate + ', ' + this.yCoordinate + ')'); + this.svgBackground_.setAttribute('width', Math.max(0, outerLength)); + this.svgKnob_.setAttribute('x', this.constrainKnob_(innerOffset)); + } else { + var outerLength = hostMetrics.viewHeight; + if (this.pair_) { + // Shorten the scrollbar to make room for the corner square. + outerLength -= Blockly.Scrollbar.scrollbarThickness; + } else { + // Only show the scrollbar if needed. + this.setVisible(outerLength < hostMetrics.contentHeight); + } + this.ratio_ = outerLength / hostMetrics.contentHeight; + if (this.ratio_ === -Infinity || this.ratio_ === Infinity || + isNaN(this.ratio_)) { + this.ratio_ = 0; + } + var innerLength = hostMetrics.viewHeight * this.ratio_; + var innerOffset = (hostMetrics.viewTop - hostMetrics.contentTop) * + this.ratio_; + this.svgKnob_.setAttribute('height', Math.max(0, innerLength)); + this.xCoordinate = hostMetrics.absoluteLeft; + if (!Blockly.RTL) { + this.xCoordinate += hostMetrics.viewWidth - + Blockly.Scrollbar.scrollbarThickness; + } + this.yCoordinate = hostMetrics.absoluteTop; + this.svgGroup_.setAttribute('transform', + 'translate(' + this.xCoordinate + ', ' + this.yCoordinate + ')'); + this.svgBackground_.setAttribute('height', Math.max(0, outerLength)); + this.svgKnob_.setAttribute('y', this.constrainKnob_(innerOffset)); + } + // Resizing may have caused some scrolling. + this.onScroll_(); +}; + +/** + * Create all the DOM elements required for a scrollbar. + * The resulting widget is not sized. + * @private + */ +Blockly.ScrollbarSvg.prototype.createDom_ = function() { + /* Create the following DOM: + + + + + */ + this.svgGroup_ = Blockly.createSvgElement('g', {}, null); + this.svgBackground_ = Blockly.createSvgElement('rect', + {'class': 'blocklyScrollbarBackground'}, this.svgGroup_); + var radius = Math.floor((Blockly.Scrollbar.scrollbarThickness - 6) / 2); + this.svgKnob_ = Blockly.createSvgElement('rect', + {'class': 'blocklyScrollbarKnob', 'rx': radius, 'ry': radius}, + this.svgGroup_); + Blockly.Scrollbar.insertAfter_(this.svgGroup_, + this.workspace_.getBubbleCanvas()); +}; + +/** + * Is the scrollbar visible. Non-paired scrollbars disappear when they aren't + * needed. + * @return {boolean} True if visible. + */ +Blockly.ScrollbarSvg.prototype.isVisible = function() { + return this.svgGroup_.getAttribute('display') != 'none'; +}; + +/** + * Set whether the scrollbar is visible. + * Only applies to non-paired scrollbars. + * @param {boolean} visible True if visible. + */ +Blockly.ScrollbarSvg.prototype.setVisible = function(visible) { + if (visible == this.isVisible()) { + return; + } + // Ideally this would also apply to scrollbar pairs, but that's a bigger + // headache (due to interactions with the corner square). + if (this.pair_) { + throw 'Unable to toggle visibility of paired scrollbars.'; + } + if (visible) { + this.svgGroup_.setAttribute('display', 'block'); + } else { + // Hide the scrollbar. + this.workspace_.setMetrics({x: 0, y: 0}); + this.svgGroup_.setAttribute('display', 'none'); + } +}; + +/** + * Scroll by one pageful. + * Called when scrollbar background is clicked. + * @param {!Event} e Mouse down event. + * @private + */ +Blockly.ScrollbarSvg.prototype.onMouseDownBar_ = function(e) { + Blockly.hideChaff(true); + if (Blockly.isRightButton(e)) { + // Right-click. + // Scrollbars have no context menu. + e.stopPropagation(); + return; + } + var mouseXY = Blockly.mouseToSvg(e); + var mouseLocation = this.horizontal_ ? mouseXY.x : mouseXY.y; + + var knobXY = Blockly.getSvgXY_(this.svgKnob_); + var knobStart = this.horizontal_ ? knobXY.x : knobXY.y; + var knobLength = parseFloat( + this.svgKnob_.getAttribute(this.horizontal_ ? 'width' : 'height')); + var knobValue = parseFloat( + this.svgKnob_.getAttribute(this.horizontal_ ? 'x' : 'y')); + + var pageLength = knobLength * 0.95; + if (mouseLocation <= knobStart) { + // Decrease the scrollbar's value by a page. + knobValue -= pageLength; + } else if (mouseLocation >= knobStart + knobLength) { + // Increase the scrollbar's value by a page. + knobValue += pageLength; + } + this.svgKnob_.setAttribute(this.horizontal_ ? 'x' : 'y', + this.constrainKnob_(knobValue)); + this.onScroll_(); + e.stopPropagation(); +}; + +/** + * Start a dragging operation. + * Called when scrollbar knob is clicked. + * @param {!Event} e Mouse down event. + * @private + */ +Blockly.ScrollbarSvg.prototype.onMouseDownKnob_ = function(e) { + Blockly.hideChaff(true); + this.onMouseUpKnob_(); + if (Blockly.isRightButton(e)) { + // Right-click. + // Scrollbars have no context menu. + e.stopPropagation(); + return; + } + // Look up the current translation and record it. + this.startDragKnob = parseFloat( + this.svgKnob_.getAttribute(this.horizontal_ ? 'x' : 'y')); + // Record the current mouse position. + this.startDragMouse = this.horizontal_ ? e.clientX : e.clientY; + Blockly.ScrollbarSvg.onMouseUpWrapper_ = Blockly.bindEvent_(document, + 'mouseup', this, this.onMouseUpKnob_); + Blockly.ScrollbarSvg.onMouseMoveWrapper_ = Blockly.bindEvent_(document, + 'mousemove', this, this.onMouseMoveKnob_); + e.stopPropagation(); +}; + +/** + * Drag the scrollbar's knob. + * @param {!Event} e Mouse up event. + * @private + */ +Blockly.ScrollbarSvg.prototype.onMouseMoveKnob_ = function(e) { + var currentMouse = this.horizontal_ ? e.clientX : e.clientY; + var mouseDelta = currentMouse - this.startDragMouse; + var knobValue = this.startDragKnob + mouseDelta; + // Position the bar. + this.svgKnob_.setAttribute(this.horizontal_ ? 'x' : 'y', + this.constrainKnob_(knobValue)); + this.onScroll_(); +}; + +/** + * Stop binding to the global mouseup and mousemove events. + * @private + */ +Blockly.ScrollbarSvg.prototype.onMouseUpKnob_ = function() { + if (Blockly.ScrollbarSvg.onMouseUpWrapper_) { + Blockly.unbindEvent_(Blockly.ScrollbarSvg.onMouseUpWrapper_); + Blockly.ScrollbarSvg.onMouseUpWrapper_ = null; + } + if (Blockly.ScrollbarSvg.onMouseMoveWrapper_) { + Blockly.unbindEvent_(Blockly.ScrollbarSvg.onMouseMoveWrapper_); + Blockly.ScrollbarSvg.onMouseMoveWrapper_ = null; + } +}; + +/** + * Constrain the knob's position within the minimum (0) and maximum + * (length of scrollbar) values allowed for the scrollbar. + * @param {number} value Value that is potentially out of bounds. + * @return {number} Constrained value. + * @private + */ +Blockly.ScrollbarSvg.prototype.constrainKnob_ = function(value) { + if (value <= 0 || isNaN(value)) { + value = 0; + } else { + var axis = this.horizontal_ ? 'width' : 'height'; + var barLength = parseFloat(this.svgBackground_.getAttribute(axis)); + var knobLength = parseFloat(this.svgKnob_.getAttribute(axis)); + value = Math.min(value, barLength - knobLength); + } + return value; +}; + +/** + * Called when scrollbar is moved. + * @private + */ +Blockly.ScrollbarSvg.prototype.onScroll_ = function() { + var knobValue = parseFloat( + this.svgKnob_.getAttribute(this.horizontal_ ? 'x' : 'y')); + var barLength = parseFloat( + this.svgBackground_.getAttribute(this.horizontal_ ? 'width' : 'height')); + var ratio = knobValue / barLength; + if (isNaN(ratio)) { + ratio = 0; + } + var xyRatio = {}; + if (this.horizontal_) { + xyRatio.x = ratio; + } else { + xyRatio.y = ratio; + } + this.workspace_.setMetrics(xyRatio); +}; + +/** + * Set the scrollbar slider's position. + * @param {number} value The distance from the top/left end of the bar. + * @param {boolean} fireEvents True if onScroll events should be fired. + */ +Blockly.ScrollbarSvg.prototype.set = function(value, fireEvents) { + // Move the scrollbar slider. + this.svgKnob_.setAttribute(this.horizontal_ ? 'x' : 'y', value * this.ratio_); + + if (fireEvents) { + this.onScroll_(); + } +}; + +// -------------------------------------------------------------------- + +/** + * Choose between the native and the SVG implementations. The native one is + * preferred, provided that the browser supports it. + * To test, see: tests/native_scrollbar_test.html + * Known good user agents: + * Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:10.0.2) + * Gecko/20100101 Firefox/10.0.2 + * Mozilla/5.0 (Ubuntu; X11; Linux x86_64; rv:9.0.1) + * Gecko/20100101 Firefox/9.0.1 + */ +if (goog.userAgent.GECKO && + (goog.userAgent.MAC || goog.userAgent.LINUX)) { + /** + * Class for a scrollbar. + */ + Blockly.Scrollbar = Blockly.ScrollbarNative; + /** + * Width of vertical scrollbar or height of horizontal scrollbar. + * Automatically measured and set after first scrollbar is created. + */ + Blockly.Scrollbar.scrollbarThickness = 0; +} else { + /** + * Class for a scrollbar. + */ + Blockly.Scrollbar = Blockly.ScrollbarSvg; + /** + * Width of vertical scrollbar or height of horizontal scrollbar. + */ + Blockly.Scrollbar.scrollbarThickness = 15; +} + +/** + * Insert a node after a reference node. + * Contrast with node.insertBefore function. + * @param {!Element} newNode New element to insert. + * @param {!Element} refNode Existing element to precede new node. + * @private + */ +Blockly.Scrollbar.insertAfter_ = function(newNode, refNode) { + var siblingNode = refNode.nextSibling; + var parentNode = refNode.parentNode; + if (!parentNode) { + throw 'Reference node has no parent.'; + } + if (siblingNode) { + parentNode.insertBefore(newNode, siblingNode); + } else { + parentNode.appendChild(newNode); + } +}; diff --git a/core/toolbox.js b/core/toolbox.js new file mode 100644 index 000000000..7b1bd0260 --- /dev/null +++ b/core/toolbox.js @@ -0,0 +1,338 @@ +/** + * Visual Blocks Editor + * + * Copyright 2011 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Toolbox from whence to create blocks. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Toolbox'); + +goog.require('Blockly.Flyout'); +goog.require('goog.events.BrowserFeature'); +goog.require('goog.style'); +goog.require('goog.ui.tree.TreeControl'); +goog.require('goog.ui.tree.TreeNode'); + + +/** + * Width of the toolbox. + * @type {number} + */ +Blockly.Toolbox.width = 0; + +/** + * The SVG group currently selected. + * @type {SVGGElement} + * @private + */ +Blockly.Toolbox.selectedOption_ = null; + +/** + * Configuration constants for Closure's tree UI. + * @type {Object.} + * @const + * @private + */ +Blockly.Toolbox.CONFIG_ = { + indentWidth: 19, + cssRoot: 'blocklyTreeRoot', + cssHideRoot: 'blocklyHidden', + cssItem: '', + cssTreeRow: 'blocklyTreeRow', + cssItemLabel: 'blocklyTreeLabel', + cssTreeIcon: 'blocklyTreeIcon', + cssExpandedFolderIcon: 'blocklyTreeIconOpen', + cssFileIcon: 'blocklyTreeIconNone', + cssSelectedRow: 'blocklyTreeSelected' +}; + +/** + * Creates the toolbox's DOM. Only needs to be called once. + * @param {!Element} svg The top-level SVG element. + * @param {!Element} container The SVG's HTML parent element. + */ +Blockly.Toolbox.createDom = function(svg, container) { + // Create an HTML container for the Toolbox menu. + Blockly.Toolbox.HtmlDiv = goog.dom.createDom('div', 'blocklyToolboxDiv'); + Blockly.Toolbox.HtmlDiv.setAttribute('dir', Blockly.RTL ? 'RTL' : 'LTR'); + container.appendChild(Blockly.Toolbox.HtmlDiv); + + /** + * @type {!Blockly.Flyout} + * @private + */ + Blockly.Toolbox.flyout_ = new Blockly.Flyout(); + svg.appendChild(Blockly.Toolbox.flyout_.createDom()); + + // Clicking on toolbar closes popups. + Blockly.bindEvent_(Blockly.Toolbox.HtmlDiv, 'mousedown', null, + function(e) { + if (Blockly.isRightButton(e) || e.target == Blockly.Toolbox.HtmlDiv) { + // Close flyout. + Blockly.hideChaff(false); + } else { + // Just close popups. + Blockly.hideChaff(true); + } + }); +}; + +/** + * Initializes the toolbox. + */ +Blockly.Toolbox.init = function() { + Blockly.Toolbox.CONFIG_['cleardotPath'] = + Blockly.pathToBlockly + 'media/1x1.gif'; + Blockly.Toolbox.CONFIG_['cssCollapsedFolderIcon'] = + 'blocklyTreeIconClosed' + (Blockly.RTL ? 'Rtl' : 'Ltr'); + var tree = new Blockly.Toolbox.TreeControl('root', Blockly.Toolbox.CONFIG_); + Blockly.Toolbox.tree_ = tree; + tree.setShowRootNode(false); + tree.setShowLines(false); + tree.setShowExpandIcons(false); + tree.setSelectedItem(null); + + Blockly.Toolbox.HtmlDiv.style.display = 'block'; + Blockly.Toolbox.flyout_.init(Blockly.mainWorkspace, true); + Blockly.Toolbox.populate_(); + tree.render(Blockly.Toolbox.HtmlDiv); + + // If the document resizes, reposition the toolbox. + goog.events.listen(window, goog.events.EventType.RESIZE, + Blockly.Toolbox.position_); + Blockly.Toolbox.position_(); +}; + +/** + * Move the toolbox to the edge. + * @private + */ +Blockly.Toolbox.position_ = function() { + var treeDiv = Blockly.Toolbox.HtmlDiv; + var svgBox = goog.style.getBorderBox(Blockly.svg); + var svgSize = Blockly.svgSize(); + if (Blockly.RTL) { + var xy = Blockly.convertCoordinates(0, 0, false); + treeDiv.style.left = (xy.x + svgSize.width - treeDiv.offsetWidth) + 'px'; + } else { + treeDiv.style.marginLeft = svgBox.left; + } + treeDiv.style.height = (svgSize.height + 1) + 'px'; + Blockly.Toolbox.width = treeDiv.offsetWidth; + if (!Blockly.RTL) { + // For some reason the LTR toolbox now reports as 1px too wide. + Blockly.Toolbox.width -= 1; + } +}; + +/** + * Fill the toolbox with categories and blocks. + * @private + */ +Blockly.Toolbox.populate_ = function() { + var rootOut = Blockly.Toolbox.tree_; + rootOut.blocks = []; + function syncTrees(treeIn, treeOut) { + for (var i = 0, childIn; childIn = treeIn.childNodes[i]; i++) { + if (!childIn.tagName) { + // Skip over text. + continue; + } + var name = childIn.tagName.toUpperCase(); + if (name == 'CATEGORY') { + var childOut = rootOut.createNode(childIn.getAttribute('name')); + childOut.blocks = []; + treeOut.add(childOut); + var custom = childIn.getAttribute('custom'); + if (custom) { + // Variables and procedures have special categories that are dynamic. + childOut.blocks = custom; + } else { + syncTrees(childIn, childOut); + } + } else if (name == 'BLOCK') { + treeOut.blocks.push(childIn); + } + } + } + syncTrees(Blockly.languageTree, Blockly.Toolbox.tree_); + + if (rootOut.blocks.length) { + throw 'Toolbox cannot have both blocks and categories in the root level.'; + } + + // Fire a resize event since the toolbox may have changed width and height. + Blockly.fireUiEvent(window, 'resize'); +}; + +/** + * Unhighlight any previously specified option. + */ +Blockly.Toolbox.clearSelection = function() { + Blockly.Toolbox.tree_.setSelectedItem(null); +}; + +// Extending Closure's Tree UI. + +/** + * Extention of a TreeControl object that uses a custom tree node. + * @param {string} html The HTML content of the node label. + * @param {Object=} opt_config The configuration for the tree. See + * goog.ui.tree.TreeControl.DefaultConfig. If not specified, a default config + * will be used. + * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper. + * @constructor + * @extends {goog.ui.tree.TreeControl} + */ +Blockly.Toolbox.TreeControl = function(html, opt_config, opt_domHelper) { + goog.ui.tree.TreeControl.call(this, html, opt_config, opt_domHelper); +}; +goog.inherits(Blockly.Toolbox.TreeControl, goog.ui.tree.TreeControl); + +/** + * Adds touch handling to TreeControl. + * @override + */ +Blockly.Toolbox.TreeControl.prototype.enterDocument = function() { + Blockly.Toolbox.TreeControl.superClass_.enterDocument.call(this); + + // Add touch handler. + if (goog.events.BrowserFeature.TOUCH_ENABLED) { + var el = this.getElement(); + Blockly.bindEvent_(el, goog.events.EventType.TOUCHSTART, this, + this.handleTouchEvent_); + } +}; +/** + * Handles touch events. + * @param {!goog.events.BrowserEvent} e The browser event. + * @private + */ +Blockly.Toolbox.TreeControl.prototype.handleTouchEvent_ = function(e) { + e.preventDefault(); + var node = this.getNodeFromEvent_(e); + if (node && e.type === goog.events.EventType.TOUCHSTART) { + // Fire asynchronously since onMouseDown takes long enough that the browser + // would fire the default mouse event before this method returns. + window.setTimeout(function() { + node.onMouseDown(e); // Same behavior for click and touch. + }, 1); + } +}; + +/** + * Creates a new tree node using a custom tree node. + * @param {string} html The html content of the node label. + * @return {goog.ui.tree.TreeNode} The new item. + * @override + */ +Blockly.Toolbox.TreeControl.prototype.createNode = function(html) { + return new Blockly.Toolbox.TreeNode(html || '', this.getConfig(), + this.getDomHelper()); +}; + +/** + * Display/hide the flyout when an item is selected. + * @param {goog.ui.tree.BaseNode} node The item to select. + * @override + */ +Blockly.Toolbox.TreeControl.prototype.setSelectedItem = function(node) { + if (this.selectedItem_ == node) { + return; + } + goog.ui.tree.TreeControl.prototype.setSelectedItem.call(this, node); + if (node && node.blocks && node.blocks.length) { + Blockly.Toolbox.flyout_.show(node.blocks); + } else { + // Hide the flyout. + Blockly.Toolbox.flyout_.hide(); + } +}; + +/** + * An single node in the tree, customized for Blockly's UI. + * @param {string} html The html content of the node label. + * @param {Object=} opt_config The configuration for the tree. See + * goog.ui.tree.TreeControl.DefaultConfig. If not specified, a default config + * will be used. + * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper. + * @constructor + * @extends {goog.ui.tree.TreeNode} + */ +Blockly.Toolbox.TreeNode = function(html, opt_config, opt_domHelper) { + goog.ui.tree.TreeNode.call(this, html, opt_config, opt_domHelper); + var resize = function() { + Blockly.fireUiEvent(window, 'resize'); + }; + // Fire a resize event since the toolbox may have changed width. + goog.events.listen(Blockly.Toolbox.tree_, + goog.ui.tree.BaseNode.EventType.EXPAND, resize); + goog.events.listen(Blockly.Toolbox.tree_, + goog.ui.tree.BaseNode.EventType.COLLAPSE, resize); +}; +goog.inherits(Blockly.Toolbox.TreeNode, goog.ui.tree.TreeNode); + +/** + * Do not show the +/- icon. + * @return {string} The source for the icon. + * @override + */ +Blockly.Toolbox.TreeNode.prototype.getExpandIconHtml = function() { + return ''; +}; + +/** + * Supress population of the +/- icon. + * @return {null} Null. + * @protected + * @override + */ +Blockly.Toolbox.TreeNode.prototype.getExpandIconElement = function() { + return null; +}; + +/** + * Expand or collapse the node on mouse click. + * @param {!goog.events.BrowserEvent} e The browser event. + * @override + */ +Blockly.Toolbox.TreeNode.prototype.onMouseDown = function(e) { + // Expand icon. + if (this.hasChildren() && this.isUserCollapsible_) { + this.toggle(); + this.select(); + } else if (this.isSelected()) { + this.getTree().setSelectedItem(null); + } else { + this.select(); + } + this.updateRow(); +}; + +/** + * Supress the inherited double-click behaviour. + * @param {!goog.events.BrowserEvent} e The browser event. + * @override + * @private + */ +Blockly.Toolbox.TreeNode.prototype.onDoubleClick_ = function(e) { + // NOP. +}; diff --git a/core/tooltip.js b/core/tooltip.js new file mode 100644 index 000000000..45f0ba332 --- /dev/null +++ b/core/tooltip.js @@ -0,0 +1,319 @@ +/** + * Visual Blocks Editor + * + * Copyright 2011 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Library to create tooltips for Blockly. + * First, call Blockly.Tooltip.init() after onload. + * Second, set the 'tooltip' property on any SVG element that needs a tooltip. + * If the tooltip is a string, then that message will be displayed. + * If the tooltip is an SVG element, then that object's tooltip will be used. + * Third, call Blockly.Tooltip.bindMouseEvents(e) passing the SVG element. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Tooltip'); + + +/** + * Is a tooltip currently showing? + */ +Blockly.Tooltip.visible = false; + +/** + * PID of suspended thread to clear tooltip on mouse out. + * @private + */ +Blockly.Tooltip.mouseOutPid_ = 0; + +/** + * PID of suspended thread to show the tooltip. + * @private + */ +Blockly.Tooltip.showPid_ = 0; + +/** + * Last observed location of the mouse pointer (freezes when tooltip appears). + * @private + */ +Blockly.Tooltip.lastXY_ = {x: 0, y: 0}; + +/** + * Current element being pointed at. + * @private + */ +Blockly.Tooltip.element_ = null; + +/** + * Once a tooltip has opened for an element, that element is 'poisoned' and + * cannot respawn a tooltip until the pointer moves over a different element. + * @private + */ +Blockly.Tooltip.poisonedElement_ = null; + +/** + * Tooltip's SVG group element. + * @type {Element} + * @private + */ +Blockly.Tooltip.svgGroup_ = null; + +/** + * Tooltip's SVG text element. + * @type {SVGTextElement} + * @private + */ +Blockly.Tooltip.svgText_ = null; + +/** + * Tooltip's SVG background rectangle. + * @type {Element} + * @private + */ +Blockly.Tooltip.svgBackground_ = null; + +/** + * Tooltip's SVG shadow rectangle. + * @type {Element} + * @private + */ +Blockly.Tooltip.svgShadow_ = null; + +/** + * Horizontal offset between mouse cursor and tooltip. + */ +Blockly.Tooltip.OFFSET_X = 0; + +/** + * Vertical offset between mouse cursor and tooltip. + */ +Blockly.Tooltip.OFFSET_Y = 10; + +/** + * Radius mouse can move before killing tooltip. + */ +Blockly.Tooltip.RADIUS_OK = 10; + +/** + * Delay before tooltip appears. + */ +Blockly.Tooltip.HOVER_MS = 1000; + +/** + * Horizontal padding between text and background. + */ +Blockly.Tooltip.MARGINS = 5; + +/** + * Create the tooltip elements. Only needs to be called once. + * @return {!SVGGElement} The tooltip's SVG group. + */ +Blockly.Tooltip.createDom = function() { + /* + + + + + + */ + var svgGroup = /** @type {!SVGGElement} */ ( + Blockly.createSvgElement('g', {'class': 'blocklyHidden'}, null)); + Blockly.Tooltip.svgGroup_ = svgGroup; + Blockly.Tooltip.svgShadow_ = /** @type {!SVGRectElement} */ ( + Blockly.createSvgElement( + 'rect', {'class': 'blocklyTooltipShadow', 'x': 2, 'y': 2}, svgGroup)); + Blockly.Tooltip.svgBackground_ = /** @type {!SVGRectElement} */ ( + Blockly.createSvgElement( + 'rect', {'class': 'blocklyTooltipBackground'}, svgGroup)); + Blockly.Tooltip.svgText_ = /** @type {!SVGTextElement} */ ( + Blockly.createSvgElement( + 'text', {'class': 'blocklyTooltipText'}, svgGroup)); + return svgGroup; +}; + +/** + * Binds the required mouse events onto an SVG element. + * @param {!Element} element SVG element onto which tooltip is to be bound. + */ +Blockly.Tooltip.bindMouseEvents = function(element) { + Blockly.bindEvent_(element, 'mouseover', null, Blockly.Tooltip.onMouseOver_); + Blockly.bindEvent_(element, 'mouseout', null, Blockly.Tooltip.onMouseOut_); + Blockly.bindEvent_(element, 'mousemove', null, Blockly.Tooltip.onMouseMove_); +}; + +/** + * Hide the tooltip if the mouse is over a different object. + * Initialize the tooltip to potentially appear for this object. + * @param {!Event} e Mouse event. + * @private + */ +Blockly.Tooltip.onMouseOver_ = function(e) { + // If the tooltip is an object, treat it as a pointer to the next object in + // the chain to look at. Terminate when a string or function is found. + var element = e.target; + while (!goog.isString(element.tooltip) && !goog.isFunction(element.tooltip)) { + element = element.tooltip; + } + if (Blockly.Tooltip.element_ != element) { + Blockly.Tooltip.hide(); + Blockly.Tooltip.poisonedElement_ = null; + Blockly.Tooltip.element_ = element; + } + // Forget about any immediately preceeding mouseOut event. + window.clearTimeout(Blockly.Tooltip.mouseOutPid_); +}; + +/** + * Hide the tooltip if the mouse leaves the object and enters the workspace. + * @param {!Event} e Mouse event. + * @private + */ +Blockly.Tooltip.onMouseOut_ = function(e) { + // Moving from one element to another (overlapping or with no gap) generates + // a mouseOut followed instantly by a mouseOver. Fork off the mouseOut + // event and kill it if a mouseOver is received immediately. + // This way the task only fully executes if mousing into the void. + Blockly.Tooltip.mouseOutPid_ = window.setTimeout(function() { + Blockly.Tooltip.element_ = null; + Blockly.Tooltip.poisonedElement_ = null; + Blockly.Tooltip.hide(); + }, 1); + window.clearTimeout(Blockly.Tooltip.showPid_); +}; + +/** + * When hovering over an element, schedule a tooltip to be shown. If a tooltip + * is already visible, hide it if the mouse strays out of a certain radius. + * @param {!Event} e Mouse event. + * @private + */ +Blockly.Tooltip.onMouseMove_ = function(e) { + if (!Blockly.Tooltip.element_ || !Blockly.Tooltip.element_.tooltip) { + // No tooltip here to show. + return; + } else if ((Blockly.ContextMenu && Blockly.ContextMenu.visible) || + Blockly.Block.dragMode_ != 0) { + // Don't display a tooltip when a context menu is active, or during a drag. + return; + } + if (Blockly.Tooltip.visible) { + // Compute the distance between the mouse position when the tooltip was + // shown and the current mouse position. Pythagorean theorem. + var mouseXY = Blockly.mouseToSvg(e); + var dx = Blockly.Tooltip.lastXY_.x - mouseXY.x; + var dy = Blockly.Tooltip.lastXY_.y - mouseXY.y; + var dr = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)); + if (dr > Blockly.Tooltip.RADIUS_OK) { + Blockly.Tooltip.hide(); + } + } else if (Blockly.Tooltip.poisonedElement_ != Blockly.Tooltip.element_) { + // The mouse moved, clear any previously scheduled tooltip. + window.clearTimeout(Blockly.Tooltip.showPid_); + // Maybe this time the mouse will stay put. Schedule showing of tooltip. + Blockly.Tooltip.lastXY_ = Blockly.mouseToSvg(e); + Blockly.Tooltip.showPid_ = + window.setTimeout(Blockly.Tooltip.show_, Blockly.Tooltip.HOVER_MS); + } +}; + +/** + * Hide the tooltip. + */ +Blockly.Tooltip.hide = function() { + if (Blockly.Tooltip.visible) { + Blockly.Tooltip.visible = false; + if (Blockly.Tooltip.svgGroup_) { + Blockly.Tooltip.svgGroup_.style.display = 'none'; + } + } + window.clearTimeout(Blockly.Tooltip.showPid_); +}; + +/** + * Create the tooltip and show it. + * @private + */ +Blockly.Tooltip.show_ = function() { + Blockly.Tooltip.poisonedElement_ = Blockly.Tooltip.element_; + if (!Blockly.Tooltip.svgGroup_) { + return; + } + // Erase all existing text. + goog.dom.removeChildren( + /** @type {!Element} */ (Blockly.Tooltip.svgText_)); + // Create new text, line by line. + var tip = Blockly.Tooltip.element_.tooltip; + if (goog.isFunction(tip)) { + tip = tip(); + } + var lines = tip.split('\n'); + for (var i = 0; i < lines.length; i++) { + var tspanElement = Blockly.createSvgElement('tspan', + {'dy': '1em', 'x': Blockly.Tooltip.MARGINS}, Blockly.Tooltip.svgText_); + var textNode = document.createTextNode(lines[i]); + tspanElement.appendChild(textNode); + } + // Display the tooltip. + Blockly.Tooltip.visible = true; + Blockly.Tooltip.svgGroup_.style.display = 'block'; + // Resize the background and shadow to fit. + var bBox = Blockly.Tooltip.svgText_.getBBox(); + var width = 2 * Blockly.Tooltip.MARGINS + bBox.width; + var height = bBox.height; + Blockly.Tooltip.svgBackground_.setAttribute('width', width); + Blockly.Tooltip.svgBackground_.setAttribute('height', height); + Blockly.Tooltip.svgShadow_.setAttribute('width', width); + Blockly.Tooltip.svgShadow_.setAttribute('height', height); + if (Blockly.RTL) { + // Right-align the paragraph. + // This cannot be done until the tooltip is rendered on screen. + var maxWidth = bBox.width; + for (var x = 0, textElement; + textElement = Blockly.Tooltip.svgText_.childNodes[x]; x++) { + textElement.setAttribute('text-anchor', 'end'); + textElement.setAttribute('x', maxWidth + Blockly.Tooltip.MARGINS); + } + } + // Move the tooltip to just below the cursor. + var anchorX = Blockly.Tooltip.lastXY_.x; + if (Blockly.RTL) { + anchorX -= Blockly.Tooltip.OFFSET_X + width; + } else { + anchorX += Blockly.Tooltip.OFFSET_X; + } + var anchorY = Blockly.Tooltip.lastXY_.y + Blockly.Tooltip.OFFSET_Y; + + var svgSize = Blockly.svgSize(); + if (anchorY + bBox.height > svgSize.height) { + // Falling off the bottom of the screen; shift the tooltip up. + anchorY -= bBox.height + 2 * Blockly.Tooltip.OFFSET_Y; + } + if (Blockly.RTL) { + // Prevent falling off left edge in RTL mode. + anchorX = Math.max(Blockly.Tooltip.MARGINS, anchorX); + } else { + if (anchorX + bBox.width > svgSize.width - 2 * Blockly.Tooltip.MARGINS) { + // Falling off the right edge of the screen; + // clamp the tooltip on the edge. + anchorX = svgSize.width - bBox.width - 2 * Blockly.Tooltip.MARGINS; + } + } + Blockly.Tooltip.svgGroup_.setAttribute('transform', + 'translate(' + anchorX + ',' + anchorY + ')'); +}; diff --git a/core/trashcan.js b/core/trashcan.js new file mode 100644 index 000000000..de68b7ba6 --- /dev/null +++ b/core/trashcan.js @@ -0,0 +1,282 @@ +/** + * Visual Blocks Editor + * + * Copyright 2011 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Object representing a trash can icon. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Trashcan'); + +goog.require('goog.Timer'); + + +/** + * Class for a trash can. + * @param {!Blockly.Workspace} workspace The workspace to sit in. + * @constructor + */ +Blockly.Trashcan = function(workspace) { + this.workspace_ = workspace; +}; + +/** + * URL of the trashcan image (minus lid). + * @type {string} + * @private + */ +Blockly.Trashcan.prototype.BODY_URL_ = 'media/trashbody.png'; + +/** + * URL of the lid image. + * @type {string} + * @private + */ +Blockly.Trashcan.prototype.LID_URL_ = 'media/trashlid.png'; + +/** + * Width of both the trash can and lid images. + * @type {number} + * @private + */ +Blockly.Trashcan.prototype.WIDTH_ = 47; + +/** + * Height of the trashcan image (minus lid). + * @type {number} + * @private + */ +Blockly.Trashcan.prototype.BODY_HEIGHT_ = 45; + +/** + * Height of the lid image. + * @type {number} + * @private + */ +Blockly.Trashcan.prototype.LID_HEIGHT_ = 15; + +/** + * Distance between trashcan and bottom edge of workspace. + * @type {number} + * @private + */ +Blockly.Trashcan.prototype.MARGIN_BOTTOM_ = 35; + +/** + * Distance between trashcan and right edge of workspace. + * @type {number} + * @private + */ +Blockly.Trashcan.prototype.MARGIN_SIDE_ = 35; + +/** + * Current open/close state of the lid. + * @type {boolean} + */ +Blockly.Trashcan.prototype.isOpen = false; + +/** + * The SVG group containing the trash can. + * @type {Element} + * @private + */ +Blockly.Trashcan.prototype.svgGroup_ = null; + +/** + * The SVG image element of the trash can body. + * @type {Element} + * @private + */ +Blockly.Trashcan.prototype.svgBody_ = null; + +/** + * The SVG image element of the trash can lid. + * @type {Element} + * @private + */ +Blockly.Trashcan.prototype.svgLid_ = null; + +/** + * Task ID of opening/closing animation. + * @type {number} + * @private + */ +Blockly.Trashcan.prototype.lidTask_ = 0; + +/** + * Current angle of the lid. + * @type {number} + * @private + */ +Blockly.Trashcan.prototype.lidAngle_ = 0; + +/** + * Left coordinate of the trash can. + * @type {number} + * @private + */ +Blockly.Trashcan.prototype.left_ = 0; + +/** + * Top coordinate of the trash can. + * @type {number} + * @private + */ +Blockly.Trashcan.prototype.top_ = 0; + +/** + * Create the trash can elements. + * @return {!Element} The trash can's SVG group. + */ +Blockly.Trashcan.prototype.createDom = function() { + /* + + + + + */ + this.svgGroup_ = Blockly.createSvgElement('g', + {'filter': 'url(#blocklyTrashcanShadowFilter)'}, null); + this.svgBody_ = Blockly.createSvgElement('image', + {'width': this.WIDTH_, 'height': this.BODY_HEIGHT_}, + this.svgGroup_); + this.svgBody_.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', + Blockly.pathToBlockly + this.BODY_URL_); + this.svgBody_.setAttribute('y', this.LID_HEIGHT_); + this.svgLid_ = Blockly.createSvgElement('image', + {'width': this.WIDTH_, 'height': this.LID_HEIGHT_}, + this.svgGroup_); + this.svgLid_.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', + Blockly.pathToBlockly + this.LID_URL_); + return this.svgGroup_; +}; + +/** + * Initialize the trash can. + */ +Blockly.Trashcan.prototype.init = function() { + this.setOpen_(false); + this.position_(); + // If the document resizes, reposition the trash can. + Blockly.bindEvent_(window, 'resize', this, this.position_); +}; + +/** + * Dispose of this trash can. + * Unlink from all DOM elements to prevent memory leaks. + */ +Blockly.Trashcan.prototype.dispose = function() { + if (this.svgGroup_) { + goog.dom.removeNode(this.svgGroup_); + this.svgGroup_ = null; + } + this.svgBody_ = null; + this.svgLid_ = null; + this.workspace_ = null; + goog.Timer.clear(this.lidTask_); +}; + +/** + * Move the trash can to the bottom-right corner. + * @private + */ +Blockly.Trashcan.prototype.position_ = function() { + var metrics = this.workspace_.getMetrics(); + if (!metrics) { + // There are no metrics available (workspace is probably not visible). + return; + } + if (Blockly.RTL) { + this.left_ = this.MARGIN_SIDE_; + } else { + this.left_ = metrics.viewWidth + metrics.absoluteLeft - + this.WIDTH_ - this.MARGIN_SIDE_; + } + this.top_ = metrics.viewHeight + metrics.absoluteTop - + (this.BODY_HEIGHT_ + this.LID_HEIGHT_) - this.MARGIN_BOTTOM_; + this.svgGroup_.setAttribute('transform', + 'translate(' + this.left_ + ',' + this.top_ + ')'); +}; + +/** + * Determines if the mouse is currently over the trash can. + * Opens/closes the lid and sets the isOpen flag. + * @param {!Event} e Mouse move event. + */ +Blockly.Trashcan.prototype.onMouseMove = function(e) { + /* + An alternative approach would be to use onMouseOver and onMouseOut events. + However the selected block will be between the mouse and the trash can, + thus these events won't fire. + Another approach is to use HTML5's drag & drop API, but it's widely hated. + Instead, we'll just have the block's drag_ function call us. + */ + if (!this.svgGroup_) { + return; + } + var mouseXY = Blockly.mouseToSvg(e); + var trashXY = Blockly.getSvgXY_(this.svgGroup_); + var over = (mouseXY.x > trashXY.x) && + (mouseXY.x < trashXY.x + this.WIDTH_) && + (mouseXY.y > trashXY.y) && + (mouseXY.y < trashXY.y + this.BODY_HEIGHT_ + this.LID_HEIGHT_); + // For bonus points we might want to match the trapezoidal outline. + if (this.isOpen != over) { + this.setOpen_(over); + } +}; + +/** + * Flip the lid open or shut. + * @param {boolean} state True if open. + * @private + */ +Blockly.Trashcan.prototype.setOpen_ = function(state) { + if (this.isOpen == state) { + return; + } + goog.Timer.clear(this.lidTask_); + this.isOpen = state; + this.animateLid_(); +}; + +/** + * Rotate the lid open or closed by one step. Then wait and recurse. + * @private + */ +Blockly.Trashcan.prototype.animateLid_ = function() { + this.lidAngle_ += this.isOpen ? 10 : -10; + this.lidAngle_ = Math.max(0, this.lidAngle_); + this.svgLid_.setAttribute('transform', 'rotate(' + + (Blockly.RTL ? -this.lidAngle_ : this.lidAngle_) + ', ' + + (Blockly.RTL ? 4 : this.WIDTH_ - 4) + ', ' + + (this.LID_HEIGHT_ - 2) + ')'); + if (this.isOpen ? (this.lidAngle_ < 45) : (this.lidAngle_ > 0)) { + this.lidTask_ = goog.Timer.callOnce(this.animateLid_, 5, this); + } +}; + +/** + * Flip the lid shut. + * Called externally after a drag. + */ +Blockly.Trashcan.prototype.close = function() { + this.setOpen_(false); +}; diff --git a/core/utils.js b/core/utils.js new file mode 100644 index 000000000..d1679b093 --- /dev/null +++ b/core/utils.js @@ -0,0 +1,413 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Utility methods. + * These methods are not specific to Blockly, and could be factored out if + * a JavaScript framework such as Closure were used. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.utils'); + + +/** + * Add a CSS class to a element. + * Similar to Closure's goog.dom.classes.add, except it handles SVG elements. + * @param {!Element} element DOM element to add class to. + * @param {string} className Name of class to add. + * @private + */ +Blockly.addClass_ = function(element, className) { + var classes = element.getAttribute('class') || ''; + if ((' ' + classes + ' ').indexOf(' ' + className + ' ') == -1) { + if (classes) { + classes += ' '; + } + element.setAttribute('class', classes + className); + } +}; + +/** + * Remove a CSS class from a element. + * Similar to Closure's goog.dom.classes.remove, except it handles SVG elements. + * @param {!Element} element DOM element to remove class from. + * @param {string} className Name of class to remove. + * @private + */ +Blockly.removeClass_ = function(element, className) { + var classes = element.getAttribute('class'); + if ((' ' + classes + ' ').indexOf(' ' + className + ' ') != -1) { + var classList = classes.split(/\s+/); + for (var i = 0; i < classList.length; i++) { + if (!classList[i] || classList[i] == className) { + classList.splice(i, 1); + i--; + } + } + if (classList.length) { + element.setAttribute('class', classList.join(' ')); + } else { + element.removeAttribute('class'); + } + } +}; + +/** + * Bind an event to a function call. + * @param {!Element} element Element upon which to listen. + * @param {string} name Event name to listen to (e.g. 'mousedown'). + * @param {Object} thisObject The value of 'this' in the function. + * @param {!Function} func Function to call when event is triggered. + * @return {!Array.} Opaque data that can be passed to unbindEvent_. + * @private + */ +Blockly.bindEvent_ = function(element, name, thisObject, func) { + var bindData = []; + var wrapFunc; + if (!element.addEventListener) { + throw 'Element is not a DOM node with addEventListener.'; + } + wrapFunc = function(e) { + func.apply(thisObject, arguments); + }; + element.addEventListener(name, wrapFunc, false); + bindData.push([element, name, wrapFunc]); + // Add equivalent touch event. + if (name in Blockly.bindEvent_.TOUCH_MAP) { + wrapFunc = function(e) { + // Punt on multitouch events. + if (e.changedTouches.length == 1) { + // Map the touch event's properties to the event. + var touchPoint = e.changedTouches[0]; + e.clientX = touchPoint.clientX; + e.clientY = touchPoint.clientY; + } + func.apply(thisObject, arguments); + // Stop the browser from scrolling/zooming the page + e.preventDefault(); + }; + element.addEventListener(Blockly.bindEvent_.TOUCH_MAP[name], + wrapFunc, false); + bindData.push([element, Blockly.bindEvent_.TOUCH_MAP[name], wrapFunc]); + } + return bindData; +}; + +/** + * The TOUCH_MAP lookup dictionary specifies additional touch events to fire, + * in conjunction with mouse events. + * @type {Object} + */ +Blockly.bindEvent_.TOUCH_MAP = {}; +if ('ontouchstart' in document.documentElement) { + Blockly.bindEvent_.TOUCH_MAP = { + mousedown: 'touchstart', + mousemove: 'touchmove', + mouseup: 'touchend' + }; +} + +/** + * Unbind one or more events event from a function call. + * @param {!Array.} bindData Opaque data from bindEvent_. This list is + * emptied during the course of calling this function. + * @return {!Function} The function call. + * @private + */ +Blockly.unbindEvent_ = function(bindData) { + while (bindData.length) { + var bindDatum = bindData.pop(); + var element = bindDatum[0]; + var name = bindDatum[1]; + var func = bindDatum[2]; + element.removeEventListener(name, func, false); + } + return func; +}; + +/** + * Fire a synthetic event. + * @param {!Element} element The event's target element. + * @param {string} eventName Name of event (e.g. 'click'). + */ +Blockly.fireUiEvent = function(element, eventName) { + var doc = document; + if (doc.createEvent) { + // W3 + var evt = doc.createEvent('UIEvents'); + evt.initEvent(eventName, true, true); // event type, bubbling, cancelable + element.dispatchEvent(evt); + } else if (doc.createEventObject) { + // MSIE + var evt = doc.createEventObject(); + element.fireEvent('on' + eventName, evt); + } else { + throw 'FireEvent: No event creation mechanism.'; + } +}; + +/** + * Don't do anything for this event, just halt propagation. + * @param {!Event} e An event. + */ +Blockly.noEvent = function(e) { + // This event has been handled. No need to bubble up to the document. + e.preventDefault(); + e.stopPropagation(); +}; + +/** + * Return the coordinates of the top-left corner of this element relative to + * its parent. + * @param {!Element} element Element to find the coordinates of. + * @return {!Object} Object with .x and .y properties. + * @private + */ +Blockly.getRelativeXY_ = function(element) { + var xy = {x: 0, y: 0}; + // First, check for x and y attributes. + var x = element.getAttribute('x'); + if (x) { + xy.x = parseInt(x, 10); + } + var y = element.getAttribute('y'); + if (y) { + xy.y = parseInt(y, 10); + } + // Second, check for transform="translate(...)" attribute. + var transform = element.getAttribute('transform'); + // Note that Firefox and IE (9,10) return 'translate(12)' instead of + // 'translate(12, 0)'. + // Note that IE (9,10) returns 'translate(16 8)' instead of + // 'translate(16, 8)'. + var r = transform && + transform.match(/translate\(\s*([-\d.]+)([ ,]\s*([-\d.]+)\s*\))?/); + if (r) { + xy.x += parseInt(r[1], 10); + if (r[3]) { + xy.y += parseInt(r[3], 10); + } + } + return xy; +}; + +/** + * Return the absolute coordinates of the top-left corner of this element. + * The origin (0,0) is the top-left corner of the Blockly svg. + * @param {!Element} element Element to find the coordinates of. + * @return {!Object} Object with .x and .y properties. + * @private + */ +Blockly.getSvgXY_ = function(element) { + var x = 0; + var y = 0; + do { + // Loop through this block and every parent. + var xy = Blockly.getRelativeXY_(element); + x += xy.x; + y += xy.y; + element = element.parentNode; + } while (element && element != Blockly.svg); + return {x: x, y: y}; +}; + +/** + * Return the absolute coordinates of the top-left corner of this element. + * The origin (0,0) is the top-left corner of the page body. + * @param {!Element} element Element to find the coordinates of. + * @return {!Object} Object with .x and .y properties. + * @private + */ +Blockly.getAbsoluteXY_ = function(element) { + var xy = Blockly.getSvgXY_(element); + return Blockly.convertCoordinates(xy.x, xy.y, false); +}; + +/** + * Helper method for creating SVG elements. + * @param {string} name Element's tag name. + * @param {!Object} attrs Dictionary of attribute names and values. + * @param {Element=} opt_parent Optional parent on which to append the element. + * @return {!SVGElement} Newly created SVG element. + */ +Blockly.createSvgElement = function(name, attrs, opt_parent) { + var e = /** @type {!SVGElement} */ ( + document.createElementNS(Blockly.SVG_NS, name)); + for (var key in attrs) { + e.setAttribute(key, attrs[key]); + } + // IE defines a unique attribute "runtimeStyle", it is NOT applied to + // elements created with createElementNS. However, Closure checks for IE + // and assumes the presence of the attribute and crashes. + if (document.body.runtimeStyle) { // Indicates presence of IE-only attr. + e.runtimeStyle = e.currentStyle = e.style; + } + if (opt_parent) { + opt_parent.appendChild(e); + } + return e; +}; + +/** + * Is this event a right-click? + * @param {!Event} e Mouse event. + * @return {boolean} True if right-click. + */ +Blockly.isRightButton = function(e) { + // Control-clicking in WebKit on Mac OS X fails to change button to 2. + return e.button == 2 || e.ctrlKey; +}; + +/** + * Convert between HTML coordinates and SVG coordinates. + * @param {number} x X input coordinate. + * @param {number} y Y input coordinate. + * @param {boolean} toSvg True to convert to SVG coordinates. + * False to convert to mouse/HTML coordinates. + * @return {!Object} Object with x and y properties in output coordinates. + */ +Blockly.convertCoordinates = function(x, y, toSvg) { + if (toSvg) { + x -= window.scrollX || window.pageXOffset; + y -= window.scrollY || window.pageYOffset; + } + var svgPoint = Blockly.svg.createSVGPoint(); + svgPoint.x = x; + svgPoint.y = y; + var matrix = Blockly.svg.getScreenCTM(); + if (toSvg) { + matrix = matrix.inverse(); + } + var xy = svgPoint.matrixTransform(matrix); + if (!toSvg) { + xy.x += window.scrollX || window.pageXOffset; + xy.y += window.scrollY || window.pageYOffset; + } + return xy; +}; + +/** + * Return the converted coordinates of the given mouse event. + * The origin (0,0) is the top-left corner of the Blockly svg. + * @param {!Event} e Mouse event. + * @return {!Object} Object with .x and .y properties. + */ +Blockly.mouseToSvg = function(e) { + var scrollX = window.scrollX || window.pageXOffset; + var scrollY = window.scrollY || window.pageYOffset; + return Blockly.convertCoordinates(e.clientX + scrollX, + e.clientY + scrollY, true); +}; + +/** + * Given an array of strings, return the length of the shortest one. + * @param {!Array} array Array of strings. + * @return {number} Length of shortest string. + */ +Blockly.shortestStringLength = function(array) { + if (!array.length) { + return 0; + } + var len = array[0].length; + for (var i = 1; i < array.length; i++) { + len = Math.min(len, array[i].length); + } + return len; +}; + +/** + * Given an array of strings, return the length of the common prefix. + * Words may not be split. Any space after a word is included in the length. + * @param {!Array} array Array of strings. + * @param {?number} opt_shortest Length of shortest string. + * @return {number} Length of common prefix. + */ +Blockly.commonWordPrefix = function(array, opt_shortest) { + if (!array.length) { + return 0; + } else if (array.length == 1) { + return array[0].length; + } + var wordPrefix = 0; + var max = opt_shortest || Blockly.shortestStringLength(array); + for (var len = 0; len < max; len++) { + var letter = array[0][len]; + for (var i = 1; i < array.length; i++) { + if (letter != array[i][len]) { + return wordPrefix; + } + } + if (letter == ' ') { + wordPrefix = len + 1; + } + } + for (var i = 1; i < array.length; i++) { + var letter = array[i][len]; + if (letter && letter != ' ') { + return wordPrefix; + } + } + return max; +}; + +/** + * Given an array of strings, return the length of the common suffix. + * Words may not be split. Any space after a word is included in the length. + * @param {!Array} array Array of strings. + * @param {?number} opt_shortest Length of shortest string. + * @return {number} Length of common suffix. + */ +Blockly.commonWordSuffix = function(array, opt_shortest) { + if (!array.length) { + return 0; + } else if (array.length == 1) { + return array[0].length; + } + var wordPrefix = 0; + var max = opt_shortest || Blockly.shortestStringLength(array); + for (var len = 0; len < max; len++) { + var letter = array[0].substr(-len - 1, 1); + for (var i = 1; i < array.length; i++) { + if (letter != array[i].substr(-len - 1, 1)) { + return wordPrefix; + } + } + if (letter == ' ') { + wordPrefix = len + 1; + } + } + for (var i = 1; i < array.length; i++) { + var letter = array[i].charAt(array[i].length - len - 1); + if (letter && letter != ' ') { + return wordPrefix; + } + } + return max; +}; + +/** + * Is the given string a number (includes negative and decimals). + * @param {string} str Input string. + * @return {boolean} True if number, false otherwise. + */ +Blockly.isNumber = function(str) { + return !!str.match(/^\s*-?\d+(\.\d+)?\s*$/); +}; diff --git a/core/variables.js b/core/variables.js new file mode 100644 index 000000000..704b6bfed --- /dev/null +++ b/core/variables.js @@ -0,0 +1,181 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Utility functions for handling variables and procedure names. + * Note that variables and procedures share the same name space, meaning that + * one can't have a variable and a procedure of the same name. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Variables'); + +// TODO(scr): Fix circular dependencies +// goog.require('Blockly.Block'); +goog.require('Blockly.Toolbox'); +goog.require('Blockly.Workspace'); + + +/** + * Category to separate variable names from procedures and generated functions. + */ +Blockly.Variables.NAME_TYPE = 'VARIABLE'; + +/** + * Find all user-created variables. + * @param {Blockly.Block=} opt_block Optional root block. + * @return {!Array.} Array of variable names. + */ +Blockly.Variables.allVariables = function(opt_block) { + var blocks; + if (opt_block) { + blocks = opt_block.getDescendants(); + } else { + blocks = Blockly.mainWorkspace.getAllBlocks(); + } + var variableHash = Object.create(null); + // Iterate through every block and add each variable to the hash. + for (var x = 0; x < blocks.length; x++) { + var func = blocks[x].getVars; + if (func) { + var blockVariables = func.call(blocks[x]); + for (var y = 0; y < blockVariables.length; y++) { + var varName = blockVariables[y]; + // Variable name may be null if the block is only half-built. + if (varName) { + variableHash[varName.toLowerCase()] = varName; + } + } + } + } + // Flatten the hash into a list. + var variableList = []; + for (var name in variableHash) { + variableList.push(variableHash[name]); + } + return variableList; +}; + +/** + * Find all instances of the specified variable and rename them. + * @param {string} oldName Variable to rename. + * @param {string} newName New variable name. + */ +Blockly.Variables.renameVariable = function(oldName, newName) { + var blocks = Blockly.mainWorkspace.getAllBlocks(); + // Iterate through every block. + for (var x = 0; x < blocks.length; x++) { + var func = blocks[x].renameVar; + if (func) { + func.call(blocks[x], oldName, newName); + } + } +}; + +/** + * Construct the blocks required by the flyout for the variable category. + * @param {!Array.} blocks List of blocks to show. + * @param {!Array.} gaps List of widths between blocks. + * @param {number} margin Standard margin width for calculating gaps. + * @param {!Blockly.Workspace} workspace The flyout's workspace. + */ +Blockly.Variables.flyoutCategory = function(blocks, gaps, margin, workspace) { + var variableList = Blockly.Variables.allVariables(); + variableList.sort(goog.string.caseInsensitiveCompare); + // In addition to the user's variables, we also want to display the default + // variable name at the top. We also don't want this duplicated if the + // user has created a variable of the same name. + variableList.unshift(null); + var defaultVariable = undefined; + for (var i = 0; i < variableList.length; i++) { + if (variableList[i] === defaultVariable) { + continue; + } + var getBlock = Blockly.Blocks['variables_get'] ? + new Blockly.Block(workspace, 'variables_get') : null; + getBlock && getBlock.initSvg(); + var setBlock = Blockly.Blocks['variables_set'] ? + new Blockly.Block(workspace, 'variables_set') : null; + setBlock && setBlock.initSvg(); + if (variableList[i] === null) { + defaultVariable = (getBlock || setBlock).getVars()[0]; + } else { + getBlock && getBlock.setTitleValue(variableList[i], 'VAR'); + setBlock && setBlock.setTitleValue(variableList[i], 'VAR'); + } + setBlock && blocks.push(setBlock); + getBlock && blocks.push(getBlock); + if (getBlock && setBlock) { + gaps.push(margin, margin * 3); + } else { + gaps.push(margin * 2); + } + } +}; + +/** +* Return a new variable name that is not yet being used. This will try to +* generate single letter variable names in the range 'i' to 'z' to start with. +* If no unique name is located it will try 'i1' to 'z1', then 'i2' to 'z2' etc. +* @return {string} New variable name. +*/ +Blockly.Variables.generateUniqueName = function() { + var variableList = Blockly.Variables.allVariables(); + var newName = ''; + if (variableList.length) { + variableList.sort(goog.string.caseInsensitiveCompare); + var nameSuffix = 0, potName = 'i', i = 0, inUse = false; + while (!newName) { + i = 0; + inUse = false; + while (i < variableList.length && !inUse) { + if (variableList[i].toLowerCase() == potName) { + // This potential name is already used. + inUse = true; + } + i++; + } + if (inUse) { + // Try the next potential name. + if (potName[0] === 'z') { + // Reached the end of the character sequence so back to 'a' but with + // a new suffix. + nameSuffix++; + potName = 'a'; + } else { + potName = String.fromCharCode(potName.charCodeAt(0) + 1); + if (potName[0] == 'l') { + // Avoid using variable 'l' because of ambiguity with '1'. + potName = String.fromCharCode(potName.charCodeAt(0) + 1); + } + } + if (nameSuffix > 0) { + potName += nameSuffix; + } + } else { + // We can use the current potential name. + newName = potName; + } + } + } else { + newName = 'i'; + } + return newName; +}; diff --git a/core/warning.js b/core/warning.js new file mode 100644 index 000000000..5793e4c54 --- /dev/null +++ b/core/warning.js @@ -0,0 +1,158 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Object representing a warning. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Warning'); + +goog.require('Blockly.Bubble'); +goog.require('Blockly.Icon'); + + +/** + * Class for a warning. + * @param {!Blockly.Block} block The block associated with this warning. + * @extends {Blockly.Icon} + * @constructor + */ +Blockly.Warning = function(block) { + Blockly.Warning.superClass_.constructor.call(this, block); + this.createIcon_(); +}; +goog.inherits(Blockly.Warning, Blockly.Icon); + +/** + * Warning text (if bubble is not visible). + * @private + */ +Blockly.Warning.prototype.text_ = ''; + +/** + * Create the icon on the block. + * @private + */ +Blockly.Warning.prototype.createIcon_ = function() { + Blockly.Icon.prototype.createIcon_.call(this); + /* Here's the markup that will be generated: + + ! + */ + var iconShield = Blockly.createSvgElement('path', + {'class': 'blocklyIconShield', + 'd': 'M 2,15 Q -1,15 0.5,12 L 6.5,1.7 Q 8,-1 9.5,1.7 L 15.5,12 ' + + 'Q 17,15 14,15 z'}, + this.iconGroup_); + this.iconMark_ = Blockly.createSvgElement('text', + {'class': 'blocklyIconMark', + 'x': Blockly.Icon.RADIUS, + 'y': 2 * Blockly.Icon.RADIUS - 3}, this.iconGroup_); + this.iconMark_.appendChild(document.createTextNode('!')); +}; + +/** + * Create the text for the warning's bubble. + * @param {string} text The text to display. + * @return {!SVGTextElement} The top-level node of the text. + * @private + */ +Blockly.Warning.prototype.textToDom_ = function(text) { + var paragraph = /** @type {!SVGTextElement} */ ( + Blockly.createSvgElement( + 'text', {'class': 'blocklyText', 'y': Blockly.Bubble.BORDER_WIDTH}, + null)); + var lines = text.split('\n'); + for (var i = 0; i < lines.length; i++) { + var tspanElement = Blockly.createSvgElement('tspan', + {'dy': '1em', 'x': Blockly.Bubble.BORDER_WIDTH}, paragraph); + var textNode = document.createTextNode(lines[i]); + tspanElement.appendChild(textNode); + } + return paragraph; +}; + +/** + * Show or hide the warning bubble. + * @param {boolean} visible True if the bubble should be visible. + */ +Blockly.Warning.prototype.setVisible = function(visible) { + if (visible == this.isVisible()) { + // No change. + return; + } + if (visible) { + // Create the bubble. + var paragraph = this.textToDom_(this.text_); + this.bubble_ = new Blockly.Bubble( + /** @type {!Blockly.Workspace} */ (this.block_.workspace), + paragraph, this.block_.svg_.svgGroup_, + this.iconX_, this.iconY_, null, null); + if (Blockly.RTL) { + // Right-align the paragraph. + // This cannot be done until the bubble is rendered on screen. + var maxWidth = paragraph.getBBox().width; + for (var x = 0, textElement; textElement = paragraph.childNodes[x]; x++) { + textElement.setAttribute('text-anchor', 'end'); + textElement.setAttribute('x', maxWidth + Blockly.Bubble.BORDER_WIDTH); + } + } + this.updateColour(); + // Bump the warning into the right location. + var size = this.bubble_.getBubbleSize(); + this.bubble_.setBubbleSize(size.width, size.height); + } else { + // Dispose of the bubble. + this.bubble_.dispose(); + this.bubble_ = null; + this.body_ = null; + this.foreignObject_ = null; + } +}; + +/** + * Bring the warning to the top of the stack when clicked on. + * @param {!Event} e Mouse up event. + * @private + */ +Blockly.Warning.prototype.bodyFocus_ = function(e) { + this.bubble_.promote_(); +}; + +/** + * Set this warning's text. + * @param {string} text Warning text. + */ +Blockly.Warning.prototype.setText = function(text) { + this.text_ = text; + if (this.isVisible()) { + this.setVisible(false); + this.setVisible(true); + } +}; + +/** + * Dispose of this warning. + */ +Blockly.Warning.prototype.dispose = function() { + this.block_.warning = null; + Blockly.Icon.prototype.dispose.call(this); +}; diff --git a/core/widgetdiv.js b/core/widgetdiv.js new file mode 100644 index 000000000..54bbb52da --- /dev/null +++ b/core/widgetdiv.js @@ -0,0 +1,89 @@ +/** + * Visual Blocks Editor + * + * Copyright 2013 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview A div that floats on top of Blockly. This singleton contains + * temporary HTML UI widgets that the user is currently interacting with. + * E.g. text input areas, colour pickers. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.WidgetDiv'); + +goog.require('Blockly.Css'); +goog.require('goog.dom'); + + +/** + * The HTML container. Set once by inject.js's Blockly.createDom_. + * @type Element + */ +Blockly.WidgetDiv.DIV = null; + +/** + * The field currently using this container. + * @private + * @type Blockly.Field + */ +Blockly.WidgetDiv.field_ = null; + +/** + * Optional cleanup function set by whichever field uses the widget. + * @private + * @type Function + */ +Blockly.WidgetDiv.dispose_ = null; + +/** + * Initialize and display the widget div. Close the old one if needed. + * @param {!Blockly.Field} newField The field that will be using this container. + * @param {Function} dispose Optional cleanup function to be run when the widget + * is closed. + */ +Blockly.WidgetDiv.show = function(newField, dispose) { + Blockly.WidgetDiv.hide(); + Blockly.WidgetDiv.field_ = newField; + Blockly.WidgetDiv.dispose_ = dispose; + Blockly.WidgetDiv.DIV.style.display = 'block'; +}; + +/** + * Destroy the widget and hide the div. + */ +Blockly.WidgetDiv.hide = function() { + if (Blockly.WidgetDiv.field_) { + Blockly.WidgetDiv.DIV.style.display = 'none'; + Blockly.WidgetDiv.dispose_ && Blockly.WidgetDiv.dispose_(); + Blockly.WidgetDiv.field_ = null; + Blockly.WidgetDiv.dispose_ = null; + goog.dom.removeChildren(Blockly.WidgetDiv.DIV); + } +}; + +/** + * Destroy the widget and hide the div if it is being used by the specified + * field. + * @param {!Blockly.Field} oldField The field that was using this container. + */ +Blockly.WidgetDiv.hideIfField = function(oldField) { + if (Blockly.WidgetDiv.field_ == oldField) { + Blockly.WidgetDiv.hide(); + } +}; diff --git a/core/workspace.js b/core/workspace.js new file mode 100644 index 000000000..4857fe84e --- /dev/null +++ b/core/workspace.js @@ -0,0 +1,386 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Object representing a workspace. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Workspace'); + +// TODO(scr): Fix circular dependencies +// goog.require('Blockly.Block'); +goog.require('Blockly.ScrollbarPair'); +goog.require('Blockly.Trashcan'); +goog.require('Blockly.Xml'); + + +/** + * Class for a workspace. + * @param {Function} getMetrics A function that returns size/scrolling metrics. + * @param {Function} setMetrics A function that sets size/scrolling metrics. + * @constructor + */ +Blockly.Workspace = function(getMetrics, setMetrics) { + this.getMetrics = getMetrics; + this.setMetrics = setMetrics; + + /** @type {boolean} */ + this.isFlyout = false; + /** + * @type {!Array.} + * @private + */ + this.topBlocks_ = []; + + /** @type {number} */ + this.maxBlocks = Infinity; + + Blockly.ConnectionDB.init(this); +}; + +/** + * Angle away from the horizontal to sweep for blocks. Order of execution is + * generally top to bottom, but a small angle changes the scan to give a bit of + * a left to right bias (reversed in RTL). Units are in degrees. + * See: http://tvtropes.org/pmwiki/pmwiki.php/Main/DiagonalBilling. + */ +Blockly.Workspace.SCAN_ANGLE = 3; + +/** + * Can this workspace be dragged around (true) or is it fixed (false)? + * @type {boolean} + */ +Blockly.Workspace.prototype.dragMode = false; + +/** + * Current horizontal scrolling offset. + * @type {number} + */ +Blockly.Workspace.prototype.scrollX = 0; + +/** + * Current vertical scrolling offset. + * @type {number} + */ +Blockly.Workspace.prototype.scrollY = 0; + +/** + * The workspace's trashcan (if any). + * @type {Blockly.Trashcan} + */ +Blockly.Workspace.prototype.trashcan = null; + +/** + * PID of upcoming firing of a change event. Used to fire only one event + * after multiple changes. + * @type {?number} + * @private + */ +Blockly.Workspace.prototype.fireChangeEventPid_ = null; + +/** + * This workspace's scrollbars, if they exist. + * @type {Blockly.ScrollbarPair} + */ +Blockly.Workspace.prototype.scrollbar = null; + +/** + * Create the trash can elements. + * @return {!Element} The workspace's SVG group. + */ +Blockly.Workspace.prototype.createDom = function() { + /* + + [Trashcan may go here] + + + + */ + this.svgGroup_ = Blockly.createSvgElement('g', {}, null); + this.svgBlockCanvas_ = Blockly.createSvgElement('g', {}, this.svgGroup_); + this.svgBubbleCanvas_ = Blockly.createSvgElement('g', {}, this.svgGroup_); + this.fireChangeEvent(); + return this.svgGroup_; +}; + +/** + * Dispose of this workspace. + * Unlink from all DOM elements to prevent memory leaks. + */ +Blockly.Workspace.prototype.dispose = function() { + if (this.svgGroup_) { + goog.dom.removeNode(this.svgGroup_); + this.svgGroup_ = null; + } + this.svgBlockCanvas_ = null; + this.svgBubbleCanvas_ = null; + if (this.trashcan) { + this.trashcan.dispose(); + this.trashcan = null; + } +}; + +/** + * Add a trashcan. + */ +Blockly.Workspace.prototype.addTrashcan = function() { + if (Blockly.hasTrashcan && !Blockly.readOnly) { + this.trashcan = new Blockly.Trashcan(this); + var svgTrashcan = this.trashcan.createDom(); + this.svgGroup_.insertBefore(svgTrashcan, this.svgBlockCanvas_); + this.trashcan.init(); + } +}; + +/** + * Get the SVG element that forms the drawing surface. + * @return {!Element} SVG element. + */ +Blockly.Workspace.prototype.getCanvas = function() { + return this.svgBlockCanvas_; +}; + +/** + * Get the SVG element that forms the bubble surface. + * @return {!SVGGElement} SVG element. + */ +Blockly.Workspace.prototype.getBubbleCanvas = function() { + return this.svgBubbleCanvas_; +}; + +/** + * Add a block to the list of top blocks. + * @param {!Blockly.Block} block Block to remove. + */ +Blockly.Workspace.prototype.addTopBlock = function(block) { + this.topBlocks_.push(block); + this.fireChangeEvent(); +}; + +/** + * Remove a block from the list of top blocks. + * @param {!Blockly.Block} block Block to remove. + */ +Blockly.Workspace.prototype.removeTopBlock = function(block) { + var found = false; + for (var child, x = 0; child = this.topBlocks_[x]; x++) { + if (child == block) { + this.topBlocks_.splice(x, 1); + found = true; + break; + } + } + if (!found) { + throw 'Block not present in workspace\'s list of top-most blocks.'; + } + this.fireChangeEvent(); +}; + +/** + * Finds the top-level blocks and returns them. Blocks are optionally sorted + * by position; top to bottom (with slight LTR or RTL bias). + * @param {boolean} ordered Sort the list if true. + * @return {!Array.} The top-level block objects. + */ +Blockly.Workspace.prototype.getTopBlocks = function(ordered) { + // Copy the topBlocks_ list. + var blocks = [].concat(this.topBlocks_); + if (ordered && blocks.length > 1) { + var offset = Math.sin(Blockly.Workspace.SCAN_ANGLE / 180 * Math.PI); + if (Blockly.RTL) { + offset *= -1; + } + blocks.sort(function(a, b) { + var aXY = a.getRelativeToSurfaceXY(); + var bXY = b.getRelativeToSurfaceXY(); + return (aXY.y + offset * aXY.x) - (bXY.y + offset * bXY.x); + }); + } + return blocks; +}; + +/** + * Find all blocks in workspace. No particular order. + * @return {!Array.} Array of blocks. + */ +Blockly.Workspace.prototype.getAllBlocks = function() { + var blocks = this.getTopBlocks(false); + for (var x = 0; x < blocks.length; x++) { + blocks = blocks.concat(blocks[x].getChildren()); + } + return blocks; +}; + +/** + * Dispose of all blocks in workspace. + */ +Blockly.Workspace.prototype.clear = function() { + Blockly.hideChaff(); + while (this.topBlocks_.length) { + this.topBlocks_[0].dispose(); + } +}; + +/** + * Render all blocks in workspace. + */ +Blockly.Workspace.prototype.render = function() { + var renderList = this.getAllBlocks(); + for (var x = 0, block; block = renderList[x]; x++) { + if (!block.getChildren().length) { + block.render(); + } + } +}; + +/** + * Finds the block with the specified ID in this workspace. + * @param {string} id ID of block to find. + * @return {Blockly.Block} The matching block, or null if not found. + */ +Blockly.Workspace.prototype.getBlockById = function(id) { + // If this O(n) function fails to scale well, maintain a hash table of IDs. + var blocks = this.getAllBlocks(); + for (var x = 0, block; block = blocks[x]; x++) { + if (block.id == id) { + return block; + } + } + return null; +}; + +/** + * Turn the visual trace functionality on or off. + * @param {boolean} armed True if the trace should be on. + */ +Blockly.Workspace.prototype.traceOn = function(armed) { + this.traceOn_ = armed; + if (this.traceWrapper_) { + Blockly.unbindEvent_(this.traceWrapper_); + this.traceWrapper_ = null; + } + if (armed) { + this.traceWrapper_ = Blockly.bindEvent_(this.svgBlockCanvas_, + 'blocklySelectChange', this, function() {this.traceOn_ = false}); + } +}; + +/** + * Highlight a block in the workspace. + * @param {?string} id ID of block to find. + */ +Blockly.Workspace.prototype.highlightBlock = function(id) { + if (!this.traceOn_) { + return; + } + var block = null; + if (id) { + block = this.getBlockById(id); + if (!block) { + return; + } + } + // Temporary turn off the listener for selection changes, so that we don't + // trip the monitor for detecting user activity. + this.traceOn(false); + // Select the current block. + if (block) { + block.select(); + } else if (Blockly.selected) { + Blockly.selected.unselect(); + } + // Restore the monitor for user activity. + this.traceOn(true); +}; + +/** + * Fire a change event for this workspace. Changes include new block, dropdown + * edits, mutations, connections, etc. Groups of simultaneous changes (e.g. + * a tree of blocks being deleted) are merged into one event. + * Applications may hook workspace changes by listening for + * 'blocklyWorkspaceChange' on Blockly.mainWorkspace.getCanvas(). + */ +Blockly.Workspace.prototype.fireChangeEvent = function() { + if (this.fireChangeEventPid_) { + window.clearTimeout(this.fireChangeEventPid_); + } + var canvas = this.svgBlockCanvas_; + if (canvas) { + this.fireChangeEventPid_ = window.setTimeout(function() { + Blockly.fireUiEvent(canvas, 'blocklyWorkspaceChange'); + }, 0); + } +}; + +/** + * Paste the provided block onto the workspace. + * @param {!Element} xmlBlock XML block element. + */ +Blockly.Workspace.prototype.paste = function(xmlBlock) { + if (xmlBlock.getElementsByTagName('block').length >= + this.remainingCapacity()) { + return; + } + var block = Blockly.Xml.domToBlock_(this, xmlBlock); + // Move the duplicate to original position. + var blockX = parseInt(xmlBlock.getAttribute('x'), 10); + var blockY = parseInt(xmlBlock.getAttribute('y'), 10); + if (!isNaN(blockX) && !isNaN(blockY)) { + if (Blockly.RTL) { + blockX = -blockX; + } + // Offset block until not clobbering another block. + do { + var collide = false; + var allBlocks = this.getAllBlocks(); + for (var x = 0, otherBlock; otherBlock = allBlocks[x]; x++) { + var otherXY = otherBlock.getRelativeToSurfaceXY(); + if (Math.abs(blockX - otherXY.x) <= 1 && + Math.abs(blockY - otherXY.y) <= 1) { + if (Blockly.RTL) { + blockX -= Blockly.SNAP_RADIUS; + } else { + blockX += Blockly.SNAP_RADIUS; + } + blockY += Blockly.SNAP_RADIUS * 2; + collide = true; + } + } + } while (collide); + block.moveBy(blockX, blockY); + } + block.select(); +}; + +/** + * The number of blocks that may be added to the workspace before reaching + * the maxBlocks. + * @return {number} Number of blocks left. + */ +Blockly.Workspace.prototype.remainingCapacity = function() { + if (this.maxBlocks == Infinity) { + return Infinity; + } + return this.maxBlocks - this.getAllBlocks().length; +}; + +// Export symbols that would otherwise be renamed by Closure compiler. +Blockly.Workspace.prototype['clear'] = Blockly.Workspace.prototype.clear; diff --git a/core/xml.js b/core/xml.js new file mode 100644 index 000000000..a2f558f5d --- /dev/null +++ b/core/xml.js @@ -0,0 +1,371 @@ +/** + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview XML reader and writer. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Xml'); + +// TODO(scr): Fix circular dependencies +// goog.require('Blockly.Block'); + + +/** + * Encode a block tree as XML. + * @param {!Object} workspace The SVG workspace. + * @return {!Element} XML document. + */ +Blockly.Xml.workspaceToDom = function(workspace) { + var width = Blockly.svgSize().width; + var xml = goog.dom.createDom('xml'); + var blocks = workspace.getTopBlocks(true); + for (var i = 0, block; block = blocks[i]; i++) { + var element = Blockly.Xml.blockToDom_(block); + var xy = block.getRelativeToSurfaceXY(); + element.setAttribute('x', Blockly.RTL ? width - xy.x : xy.x); + element.setAttribute('y', xy.y); + xml.appendChild(element); + } + return xml; +}; + +/** + * Encode a block subtree as XML. + * @param {!Blockly.Block} block The root block to encode. + * @return {!Element} Tree of XML elements. + * @private + */ +Blockly.Xml.blockToDom_ = function(block) { + var element = goog.dom.createDom('block'); + element.setAttribute('type', block.type); + if (block.mutationToDom) { + // Custom data for an advanced block. + var mutation = block.mutationToDom(); + if (mutation) { + element.appendChild(mutation); + } + } + function titleToDom(title) { + if (title.name && title.EDITABLE) { + var container = goog.dom.createDom('title', null, title.getValue()); + container.setAttribute('name', title.name); + element.appendChild(container); + } + } + for (var x = 0, input; input = block.inputList[x]; x++) { + for (var y = 0, title; title = input.titleRow[y]; y++) { + titleToDom(title); + } + } + + if (block.comment) { + var commentElement = goog.dom.createDom('comment', null, + block.comment.getText()); + commentElement.setAttribute('pinned', block.comment.isVisible()); + var hw = block.comment.getBubbleSize(); + commentElement.setAttribute('h', hw.height); + commentElement.setAttribute('w', hw.width); + element.appendChild(commentElement); + } + + var hasValues = false; + for (var i = 0, input; input = block.inputList[i]; i++) { + var container; + var empty = true; + if (input.type == Blockly.DUMMY_INPUT) { + continue; + } else { + var childBlock = input.connection.targetBlock(); + if (input.type == Blockly.INPUT_VALUE) { + container = goog.dom.createDom('value'); + hasValues = true; + } else if (input.type == Blockly.NEXT_STATEMENT) { + container = goog.dom.createDom('statement'); + } + if (childBlock) { + container.appendChild(Blockly.Xml.blockToDom_(childBlock)); + empty = false; + } + } + container.setAttribute('name', input.name); + if (!empty) { + element.appendChild(container); + } + } + if (hasValues) { + element.setAttribute('inline', block.inputsInline); + } + if (block.isCollapsed()) { + element.setAttribute('collapsed', true); + } + if (block.disabled) { + element.setAttribute('disabled', true); + } + if (!block.isDeletable()) { + element.setAttribute('deletable', false); + } + if (!block.isMovable()) { + element.setAttribute('movable', false); + } + if (!block.isEditable()) { + element.setAttribute('editable', false); + } + + if (block.nextConnection) { + var nextBlock = block.nextConnection.targetBlock(); + if (nextBlock) { + var container = goog.dom.createDom('next', null, + Blockly.Xml.blockToDom_(nextBlock)); + element.appendChild(container); + } + } + + return element; +}; + +/** + * Converts a DOM structure into plain text. + * Currently the text format is fairly ugly: all one line with no whitespace. + * @param {!Element} dom A tree of XML elements. + * @return {string} Text representation. + */ +Blockly.Xml.domToText = function(dom) { + var oSerializer = new XMLSerializer(); + return oSerializer.serializeToString(dom); +}; + +/** + * Converts a DOM structure into properly indented text. + * @param {!Element} dom A tree of XML elements. + * @return {string} Text representation. + */ +Blockly.Xml.domToPrettyText = function(dom) { + // This function is not guaranteed to be correct for all XML. + // But it handles the XML that Blockly generates. + var blob = Blockly.Xml.domToText(dom); + // Place every open and close tag on its own line. + var lines = blob.split('<'); + // Indent every line. + var indent = ''; + for (var x = 1; x < lines.length; x++) { + var line = lines[x]; + if (line[0] == '/') { + indent = indent.substring(2); + } + lines[x] = indent + '<' + line; + if (line[0] != '/' && line.slice(-2) != '/>') { + indent += ' '; + } + } + // Pull simple tags back together. + // E.g. + var text = lines.join('\n'); + text = text.replace(/(<(\w+)\b[^>]*>[^\n]*)\n *<\/\2>/g, '$1'); + // Trim leading blank line. + return text.replace(/^\n/, ''); +}; + +/** + * Converts plain text into a DOM structure. + * Throws an error if XML doesn't parse. + * @param {string} text Text representation. + * @return {!Element} A tree of XML elements. + */ +Blockly.Xml.textToDom = function(text) { + var oParser = new DOMParser(); + var dom = oParser.parseFromString(text, 'text/xml'); + // The DOM should have one and only one top-level node, an XML tag. + if (!dom || !dom.firstChild || + dom.firstChild.nodeName.toLowerCase() != 'xml' || + dom.firstChild !== dom.lastChild) { + // Whatever we got back from the parser is not XML. + throw 'Blockly.Xml.textToDom did not obtain a valid XML tree.'; + } + return dom.firstChild; +}; + +/** + * Decode an XML DOM and create blocks on the workspace. + * @param {!Blockly.Workspace} workspace The SVG workspace. + * @param {!Element} xml XML DOM. + */ +Blockly.Xml.domToWorkspace = function(workspace, xml) { + var width = Blockly.svgSize().width; + for (var x = 0, xmlChild; xmlChild = xml.childNodes[x]; x++) { + if (xmlChild.nodeName.toLowerCase() == 'block') { + var block = Blockly.Xml.domToBlock_(workspace, xmlChild); + var blockX = parseInt(xmlChild.getAttribute('x'), 10); + var blockY = parseInt(xmlChild.getAttribute('y'), 10); + if (!isNaN(blockX) && !isNaN(blockY)) { + block.moveBy(Blockly.RTL ? width - blockX : blockX, blockY); + } + } + } +}; + +/** + * Decode an XML block tag and create a block (and possibly sub blocks) on the + * workspace. + * @param {!Blockly.Workspace} workspace The workspace. + * @param {!Element} xmlBlock XML block element. + * @return {!Blockly.Block} The root block created. + * @private + */ +Blockly.Xml.domToBlock_ = function(workspace, xmlBlock) { + var prototypeName = xmlBlock.getAttribute('type'); + var block = new Blockly.Block(workspace, prototypeName); + block.initSvg(); + + var inline = xmlBlock.getAttribute('inline'); + if (inline) { + block.setInputsInline(inline == 'true'); + } + var collapsed = xmlBlock.getAttribute('collapsed'); + if (collapsed) { + block.setCollapsed(collapsed == 'true'); + } + var disabled = xmlBlock.getAttribute('disabled'); + if (disabled) { + block.setDisabled(disabled == 'true'); + } + var deletable = xmlBlock.getAttribute('deletable'); + if (deletable) { + block.setDeletable(deletable == 'true'); + } + var movable = xmlBlock.getAttribute('movable'); + if (movable) { + block.setMovable(movable == 'true'); + } + var editable = xmlBlock.getAttribute('editable'); + if (editable) { + block.setEditable(editable == 'true'); + } + + var blockChild = null; + for (var x = 0, xmlChild; xmlChild = xmlBlock.childNodes[x]; x++) { + if (xmlChild.nodeType == 3 && xmlChild.data.match(/^\s*$/)) { + // Extra whitespace between tags does not concern us. + continue; + } + var input; + + // Find the first 'real' grandchild node (that isn't whitespace). + var firstRealGrandchild = null; + for (var y = 0, grandchildNode; grandchildNode = xmlChild.childNodes[y]; + y++) { + if (grandchildNode.nodeType != 3 || !grandchildNode.data.match(/^\s*$/)) { + firstRealGrandchild = grandchildNode; + } + } + + var name = xmlChild.getAttribute('name'); + switch (xmlChild.nodeName.toLowerCase()) { + case 'mutation': + // Custom data for an advanced block. + if (block.domToMutation) { + block.domToMutation(xmlChild); + } + break; + case 'comment': + block.setCommentText(xmlChild.textContent); + var visible = xmlChild.getAttribute('pinned'); + if (visible) { + block.comment.setVisible(visible == 'true'); + } + var bubbleW = parseInt(xmlChild.getAttribute('w'), 10); + var bubbleH = parseInt(xmlChild.getAttribute('h'), 10); + if (!isNaN(bubbleW) && !isNaN(bubbleH)) { + block.comment.setBubbleSize(bubbleW, bubbleH); + } + break; + case 'title': + block.setTitleValue(xmlChild.textContent, name); + break; + case 'value': + case 'statement': + input = block.getInput(name); + if (!input) { + throw 'Input does not exist: ' + name; + } + if (firstRealGrandchild && + firstRealGrandchild.nodeName.toLowerCase() == 'block') { + blockChild = Blockly.Xml.domToBlock_(workspace, firstRealGrandchild); + if (blockChild.outputConnection) { + input.connection.connect(blockChild.outputConnection); + } else if (blockChild.previousConnection) { + input.connection.connect(blockChild.previousConnection); + } else { + throw 'Child block does not have output or previous statement.'; + } + } + break; + case 'next': + if (firstRealGrandchild && + firstRealGrandchild.nodeName.toLowerCase() == 'block') { + if (!block.nextConnection) { + throw 'Next statement does not exist.'; + } else if (block.nextConnection.targetConnection) { + // This could happen if there is more than one XML 'next' tag. + throw 'Next statement is already connected.'; + } + blockChild = Blockly.Xml.domToBlock_(workspace, firstRealGrandchild); + if (!blockChild.previousConnection) { + throw 'Next block does not have previous statement.'; + } + block.nextConnection.connect(blockChild.previousConnection); + } + break; + default: + // Unknown tag; ignore. Same principle as HTML parsers. + } + } + + var next = block.nextConnection && block.nextConnection.targetBlock(); + if (next) { + // Next block in a stack needs to square off its corners. + // Rendering a child will render its parent. + next.render(); + } else { + block.render(); + } + return block; +}; + +/** + * Remove any 'next' block (statements in a stack). + * @param {!Element} xmlBlock XML block element. + */ +Blockly.Xml.deleteNext = function(xmlBlock) { + for (var x = 0, child; child = xmlBlock.childNodes[x]; x++) { + if (child.nodeName.toLowerCase() == 'next') { + xmlBlock.removeChild(child); + break; + } + } +}; + +// Export symbols that would otherwise be renamed by Closure compiler. +Blockly['Xml'] = Blockly.Xml; +Blockly.Xml['domToText'] = Blockly.Xml.domToText; +Blockly.Xml['domToWorkspace'] = Blockly.Xml.domToWorkspace; +Blockly.Xml['textToDom'] = Blockly.Xml.textToDom; +Blockly.Xml['workspaceToDom'] = Blockly.Xml.workspaceToDom; diff --git a/demos/fixed/index.html b/demos/fixed/index.html new file mode 100644 index 000000000..8f182456d --- /dev/null +++ b/demos/fixed/index.html @@ -0,0 +1,46 @@ + + + + + Blockly Demo: Fixed Blockly + + + + + + +

    Blockly > + Demos > Fixed Blockly

    + +

    This is a simple demo of injecting Blockly into a fixed-sized 'div' element.

    + +

    → More info on injecting fixed-sized Blockly...

    + +
    + + + + + + + diff --git a/demos/generator/index.html b/demos/generator/index.html new file mode 100644 index 000000000..410f56684 --- /dev/null +++ b/demos/generator/index.html @@ -0,0 +1,93 @@ + + + + + Blockly Demo: Generating JavaScript + + + + + + + +

    Blockly > + Demos > Generating JavaScript

    + +

    This is a simple demo of generating code from blocks.

    + +

    → More info on Language Generators...

    + +

    + + +

    + +
    + + + + + + + diff --git a/demos/iframe/frame.html b/demos/iframe/frame.html new file mode 100644 index 000000000..81f37428c --- /dev/null +++ b/demos/iframe/frame.html @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + diff --git a/demos/iframe/index.html b/demos/iframe/index.html new file mode 100644 index 000000000..d86fcd7f3 --- /dev/null +++ b/demos/iframe/index.html @@ -0,0 +1,55 @@ + + + + + Blockly Demo: Iframe Blockly + + + + + + + + + + +
    +

    Blockly > + Demos > Iframe Blockly

    + +

    This is a simple demo of injecting Blockly into a resizable 'iframe' element.

    + +

    → More info on injecting resizable Blockly...

    +
    + + +
    + + + diff --git a/demos/index.html b/demos/index.html new file mode 100644 index 000000000..49623a4bb --- /dev/null +++ b/demos/index.html @@ -0,0 +1,49 @@ + + + + + Blockly Demos + + + +

    Blockly > Demos

    + +

    These demos are intended for developers who want to integrate Blockly with + their own applications.

    + +
    +
    Fixed Blockly
    +
    Inject Blockly into a page as a fixed element.
    + +
    Resizable Blockly
    +
    Inject Blockly into a page as a resizable element.
    + +
    Defining the Toolbox
    +
    Organize blocks into categories for the user.
    + +
    RTL
    +
    See what Blockly looks like in right-to-left mode (for Arabic and Hebrew).
    + +
    Maximum Block Limit
    +
    Limit the total number of blocks allowed (for academic exercises).
    + +
    Generate JavaScript
    +
    Turn blocks into code and execute it.
    + +
    Cloud Storage
    +
    Save and load blocks with App Engine.
    +
    + + diff --git a/demos/maxBlocks/index.html b/demos/maxBlocks/index.html new file mode 100644 index 000000000..d80d94080 --- /dev/null +++ b/demos/maxBlocks/index.html @@ -0,0 +1,94 @@ + + + + + Blockly Demo: Maximum Block Limit + + + + + + +

    Blockly > + Demos > Maximum Block Limit

    + +

    This is a demo of Blockly which has been restricted to a maximum of five blocks.

    + +

    You have block(s) left.

    + +
    + + + + + + + diff --git a/demos/rtl/index.html b/demos/rtl/index.html new file mode 100644 index 000000000..4f283ec25 --- /dev/null +++ b/demos/rtl/index.html @@ -0,0 +1,205 @@ + + + + + Blockly Demo: RTL + + + + + + + +

    Blockly > + Demos > Right-to-Left

    + +
    + + + + + + diff --git a/demos/storage/index.html b/demos/storage/index.html new file mode 100644 index 000000000..158c0cbc1 --- /dev/null +++ b/demos/storage/index.html @@ -0,0 +1,93 @@ + + + + + Blockly Demo: Cloud Storage + + + + + + + +

    Blockly > + Demos > Cloud Storage

    + +

    This is a simple demo of cloud storage using App Engine.

    + + + +

    → More info on Cloud Storage...

    + +

    + +

    + +
    + + + + + + + diff --git a/demos/toolbox/index.html b/demos/toolbox/index.html new file mode 100644 index 000000000..36d0c45e2 --- /dev/null +++ b/demos/toolbox/index.html @@ -0,0 +1,348 @@ + + + + + Blockly Demo: Toolbox + + + + + + +

    Blockly > + Demos > Toolbox

    + +

    This is a demo of a complex category structure for the toolbox.

    + +

    → More info on Defining the Toolbox...

    + +
    + + + + + + + diff --git a/generators/javascript.js b/generators/javascript.js new file mode 100644 index 000000000..9d5e63b71 --- /dev/null +++ b/generators/javascript.js @@ -0,0 +1,214 @@ +/** + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Helper functions for generating JavaScript for blocks. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.JavaScript'); + +goog.require('Blockly.Generator'); + + +Blockly.JavaScript = new Blockly.Generator('JavaScript'); + +/** + * List of illegal variable names. + * This is not intended to be a security feature. Blockly is 100% client-side, + * so bypassing this list is trivial. This is intended to prevent users from + * accidentally clobbering a built-in object or function. + * @private + */ +Blockly.JavaScript.addReservedWords( + 'Blockly,' + // In case JS is evaled in the current window. + // https://developer.mozilla.org/en/JavaScript/Reference/Reserved_Words + 'break,case,catch,continue,debugger,default,delete,do,else,finally,for,function,if,in,instanceof,new,return,switch,this,throw,try,typeof,var,void,while,with,' + + 'class,enum,export,extends,import,super,implements,interface,let,package,private,protected,public,static,yield,' + + 'const,null,true,false,' + + // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects + 'Array,ArrayBuffer,Boolean,Date,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Error,eval,EvalError,Float32Array,Float64Array,Function,Infinity,Int16Array,Int32Array,Int8Array,isFinite,isNaN,Iterator,JSON,Math,NaN,Number,Object,parseFloat,parseInt,RangeError,ReferenceError,RegExp,StopIteration,String,SyntaxError,TypeError,Uint16Array,Uint32Array,Uint8Array,Uint8ClampedArray,undefined,uneval,URIError,' + + // https://developer.mozilla.org/en/DOM/window + 'applicationCache,closed,Components,content,_content,controllers,crypto,defaultStatus,dialogArguments,directories,document,frameElement,frames,fullScreen,globalStorage,history,innerHeight,innerWidth,length,location,locationbar,localStorage,menubar,messageManager,mozAnimationStartTime,mozInnerScreenX,mozInnerScreenY,mozPaintCount,name,navigator,opener,outerHeight,outerWidth,pageXOffset,pageYOffset,parent,performance,personalbar,pkcs11,returnValue,screen,screenX,screenY,scrollbars,scrollMaxX,scrollMaxY,scrollX,scrollY,self,sessionStorage,sidebar,status,statusbar,toolbar,top,URL,window,' + + 'addEventListener,alert,atob,back,blur,btoa,captureEvents,clearImmediate,clearInterval,clearTimeout,close,confirm,disableExternalCapture,dispatchEvent,dump,enableExternalCapture,escape,find,focus,forward,GeckoActiveXObject,getAttention,getAttentionWithCycleCount,getComputedStyle,getSelection,home,matchMedia,maximize,minimize,moveBy,moveTo,mozRequestAnimationFrame,open,openDialog,postMessage,print,prompt,QueryInterface,releaseEvents,removeEventListener,resizeBy,resizeTo,restore,routeEvent,scroll,scrollBy,scrollByLines,scrollByPages,scrollTo,setCursor,setImmediate,setInterval,setResizable,setTimeout,showModalDialog,sizeToContent,stop,unescape,updateCommands,XPCNativeWrapper,XPCSafeJSObjectWrapper,' + + 'onabort,onbeforeunload,onblur,onchange,onclick,onclose,oncontextmenu,ondevicemotion,ondeviceorientation,ondragdrop,onerror,onfocus,onhashchange,onkeydown,onkeypress,onkeyup,onload,onmousedown,onmousemove,onmouseout,onmouseover,onmouseup,onmozbeforepaint,onpaint,onpopstate,onreset,onresize,onscroll,onselect,onsubmit,onunload,onpageshow,onpagehide,' + + 'Image,Option,Worker,' + + // https://developer.mozilla.org/en/Gecko_DOM_Reference + 'Event,Range,File,FileReader,Blob,BlobBuilder,' + + 'Attr,CDATASection,CharacterData,Comment,console,DocumentFragment,DocumentType,DomConfiguration,DOMError,DOMErrorHandler,DOMException,DOMImplementation,DOMImplementationList,DOMImplementationRegistry,DOMImplementationSource,DOMLocator,DOMObject,DOMString,DOMStringList,DOMTimeStamp,DOMUserData,Entity,EntityReference,MediaQueryList,MediaQueryListListener,NameList,NamedNodeMap,Node,NodeFilter,NodeIterator,NodeList,Notation,Plugin,PluginArray,ProcessingInstruction,SharedWorker,Text,TimeRanges,Treewalker,TypeInfo,UserDataHandler,Worker,WorkerGlobalScope,' + + 'HTMLDocument,HTMLElement,HTMLAnchorElement,HTMLAppletElement,HTMLAudioElement,HTMLAreaElement,HTMLBaseElement,HTMLBaseFontElement,HTMLBodyElement,HTMLBRElement,HTMLButtonElement,HTMLCanvasElement,HTMLDirectoryElement,HTMLDivElement,HTMLDListElement,HTMLEmbedElement,HTMLFieldSetElement,HTMLFontElement,HTMLFormElement,HTMLFrameElement,HTMLFrameSetElement,HTMLHeadElement,HTMLHeadingElement,HTMLHtmlElement,HTMLHRElement,HTMLIFrameElement,HTMLImageElement,HTMLInputElement,HTMLKeygenElement,HTMLLabelElement,HTMLLIElement,HTMLLinkElement,HTMLMapElement,HTMLMenuElement,HTMLMetaElement,HTMLModElement,HTMLObjectElement,HTMLOListElement,HTMLOptGroupElement,HTMLOptionElement,HTMLOutputElement,HTMLParagraphElement,HTMLParamElement,HTMLPreElement,HTMLQuoteElement,HTMLScriptElement,HTMLSelectElement,HTMLSourceElement,HTMLSpanElement,HTMLStyleElement,HTMLTableElement,HTMLTableCaptionElement,HTMLTableCellElement,HTMLTableDataCellElement,HTMLTableHeaderCellElement,HTMLTableColElement,HTMLTableRowElement,HTMLTableSectionElement,HTMLTextAreaElement,HTMLTimeElement,HTMLTitleElement,HTMLTrackElement,HTMLUListElement,HTMLUnknownElement,HTMLVideoElement,' + + 'HTMLCanvasElement,CanvasRenderingContext2D,CanvasGradient,CanvasPattern,TextMetrics,ImageData,CanvasPixelArray,HTMLAudioElement,HTMLVideoElement,NotifyAudioAvailableEvent,HTMLCollection,HTMLAllCollection,HTMLFormControlsCollection,HTMLOptionsCollection,HTMLPropertiesCollection,DOMTokenList,DOMSettableTokenList,DOMStringMap,RadioNodeList,' + + 'SVGDocument,SVGElement,SVGAElement,SVGAltGlyphElement,SVGAltGlyphDefElement,SVGAltGlyphItemElement,SVGAnimationElement,SVGAnimateElement,SVGAnimateColorElement,SVGAnimateMotionElement,SVGAnimateTransformElement,SVGSetElement,SVGCircleElement,SVGClipPathElement,SVGColorProfileElement,SVGCursorElement,SVGDefsElement,SVGDescElement,SVGEllipseElement,SVGFilterElement,SVGFilterPrimitiveStandardAttributes,SVGFEBlendElement,SVGFEColorMatrixElement,SVGFEComponentTransferElement,SVGFECompositeElement,SVGFEConvolveMatrixElement,SVGFEDiffuseLightingElement,SVGFEDisplacementMapElement,SVGFEDistantLightElement,SVGFEFloodElement,SVGFEGaussianBlurElement,SVGFEImageElement,SVGFEMergeElement,SVGFEMergeNodeElement,SVGFEMorphologyElement,SVGFEOffsetElement,SVGFEPointLightElement,SVGFESpecularLightingElement,SVGFESpotLightElement,SVGFETileElement,SVGFETurbulenceElement,SVGComponentTransferFunctionElement,SVGFEFuncRElement,SVGFEFuncGElement,SVGFEFuncBElement,SVGFEFuncAElement,SVGFontElement,SVGFontFaceElement,SVGFontFaceFormatElement,SVGFontFaceNameElement,SVGFontFaceSrcElement,SVGFontFaceUriElement,SVGForeignObjectElement,SVGGElement,SVGGlyphElement,SVGGlyphRefElement,SVGGradientElement,SVGLinearGradientElement,SVGRadialGradientElement,SVGHKernElement,SVGImageElement,SVGLineElement,SVGMarkerElement,SVGMaskElement,SVGMetadataElement,SVGMissingGlyphElement,SVGMPathElement,SVGPathElement,SVGPatternElement,SVGPolylineElement,SVGPolygonElement,SVGRectElement,SVGScriptElement,SVGStopElement,SVGStyleElement,SVGSVGElement,SVGSwitchElement,SVGSymbolElement,SVGTextElement,SVGTextPathElement,SVGTitleElement,SVGTRefElement,SVGTSpanElement,SVGUseElement,SVGViewElement,SVGVKernElement,' + + 'SVGAngle,SVGColor,SVGICCColor,SVGElementInstance,SVGElementInstanceList,SVGLength,SVGLengthList,SVGMatrix,SVGNumber,SVGNumberList,SVGPaint,SVGPoint,SVGPointList,SVGPreserveAspectRatio,SVGRect,SVGStringList,SVGTransform,SVGTransformList,' + + 'SVGAnimatedAngle,SVGAnimatedBoolean,SVGAnimatedEnumeration,SVGAnimatedInteger,SVGAnimatedLength,SVGAnimatedLengthList,SVGAnimatedNumber,SVGAnimatedNumberList,SVGAnimatedPreserveAspectRatio,SVGAnimatedRect,SVGAnimatedString,SVGAnimatedTransformList,' + + 'SVGPathSegList,SVGPathSeg,SVGPathSegArcAbs,SVGPathSegArcRel,SVGPathSegClosePath,SVGPathSegCurvetoCubicAbs,SVGPathSegCurvetoCubicRel,SVGPathSegCurvetoCubicSmoothAbs,SVGPathSegCurvetoCubicSmoothRel,SVGPathSegCurvetoQuadraticAbs,SVGPathSegCurvetoQuadraticRel,SVGPathSegCurvetoQuadraticSmoothAbs,SVGPathSegCurvetoQuadraticSmoothRel,SVGPathSegLinetoAbs,SVGPathSegLinetoHorizontalAbs,SVGPathSegLinetoHorizontalRel,SVGPathSegLinetoRel,SVGPathSegLinetoVerticalAbs,SVGPathSegLinetoVerticalRel,SVGPathSegMovetoAbs,SVGPathSegMovetoRel,ElementTimeControl,TimeEvent,SVGAnimatedPathData,' + + 'SVGAnimatedPoints,SVGColorProfileRule,SVGCSSRule,SVGExternalResourcesRequired,SVGFitToViewBox,SVGLangSpace,SVGLocatable,SVGRenderingIntent,SVGStylable,SVGTests,SVGTextContentElement,SVGTextPositioningElement,SVGTransformable,SVGUnitTypes,SVGURIReference,SVGViewSpec,SVGZoomAndPan'); + +/** + * Order of operation ENUMs. + * https://developer.mozilla.org/en/JavaScript/Reference/Operators/Operator_Precedence + */ +Blockly.JavaScript.ORDER_ATOMIC = 0; // 0 "" ... +Blockly.JavaScript.ORDER_MEMBER = 1; // . [] +Blockly.JavaScript.ORDER_NEW = 1; // new +Blockly.JavaScript.ORDER_FUNCTION_CALL = 2; // () +Blockly.JavaScript.ORDER_INCREMENT = 3; // ++ +Blockly.JavaScript.ORDER_DECREMENT = 3; // -- +Blockly.JavaScript.ORDER_LOGICAL_NOT = 4; // ! +Blockly.JavaScript.ORDER_BITWISE_NOT = 4; // ~ +Blockly.JavaScript.ORDER_UNARY_PLUS = 4; // + +Blockly.JavaScript.ORDER_UNARY_NEGATION = 4; // - +Blockly.JavaScript.ORDER_TYPEOF = 4; // typeof +Blockly.JavaScript.ORDER_VOID = 4; // void +Blockly.JavaScript.ORDER_DELETE = 4; // delete +Blockly.JavaScript.ORDER_MULTIPLICATION = 5; // * +Blockly.JavaScript.ORDER_DIVISION = 5; // / +Blockly.JavaScript.ORDER_MODULUS = 5; // % +Blockly.JavaScript.ORDER_ADDITION = 6; // + +Blockly.JavaScript.ORDER_SUBTRACTION = 6; // - +Blockly.JavaScript.ORDER_BITWISE_SHIFT = 7; // << >> >>> +Blockly.JavaScript.ORDER_RELATIONAL = 8; // < <= > >= +Blockly.JavaScript.ORDER_IN = 8; // in +Blockly.JavaScript.ORDER_INSTANCEOF = 8; // instanceof +Blockly.JavaScript.ORDER_EQUALITY = 9; // == != === !== +Blockly.JavaScript.ORDER_BITWISE_AND = 10; // & +Blockly.JavaScript.ORDER_BITWISE_XOR = 11; // ^ +Blockly.JavaScript.ORDER_BITWISE_OR = 12; // | +Blockly.JavaScript.ORDER_LOGICAL_AND = 13; // && +Blockly.JavaScript.ORDER_LOGICAL_OR = 14; // || +Blockly.JavaScript.ORDER_CONDITIONAL = 15; // ?: +Blockly.JavaScript.ORDER_ASSIGNMENT = 16; // = += -= *= /= %= <<= >>= ... +Blockly.JavaScript.ORDER_COMMA = 17; // , +Blockly.JavaScript.ORDER_NONE = 99; // (...) + +/** + * Arbitrary code to inject into locations that risk causing infinite loops. + * Any instances of '%1' will be replaced by the block ID that failed. + * E.g. ' checkTimeout(%1);\n' + * @type ?string + */ +Blockly.JavaScript.INFINITE_LOOP_TRAP = null; + +/** + * Initialise the database of variable names. + */ +Blockly.JavaScript.init = function() { + // Create a dictionary of definitions to be printed before the code. + Blockly.JavaScript.definitions_ = Object.create(null); + + if (Blockly.Variables) { + if (!Blockly.JavaScript.variableDB_) { + Blockly.JavaScript.variableDB_ = + new Blockly.Names(Blockly.JavaScript.RESERVED_WORDS_); + } else { + Blockly.JavaScript.variableDB_.reset(); + } + + var defvars = []; + var variables = Blockly.Variables.allVariables(); + for (var x = 0; x < variables.length; x++) { + defvars[x] = 'var ' + + Blockly.JavaScript.variableDB_.getName(variables[x], + Blockly.Variables.NAME_TYPE) + ';'; + } + Blockly.JavaScript.definitions_['variables'] = defvars.join('\n'); + } +}; + +/** + * Prepend the generated code with the variable definitions. + * @param {string} code Generated code. + * @return {string} Completed code. + */ +Blockly.JavaScript.finish = function(code) { + // Convert the definitions dictionary into a list. + var definitions = []; + for (var name in Blockly.JavaScript.definitions_) { + definitions.push(Blockly.JavaScript.definitions_[name]); + } + return definitions.join('\n\n') + '\n\n\n' + code; +}; + +/** + * Naked values are top-level blocks with outputs that aren't plugged into + * anything. A trailing semicolon is needed to make this legal. + * @param {string} line Line of generated code. + * @return {string} Legal line of code. + */ +Blockly.JavaScript.scrubNakedValue = function(line) { + return line + ';\n'; +}; + +/** + * Encode a string as a properly escaped JavaScript string, complete with + * quotes. + * @param {string} string Text to encode. + * @return {string} JavaScript string. + * @private + */ +Blockly.JavaScript.quote_ = function(string) { + // TODO: This is a quick hack. Replace with goog.string.quote + string = string.replace(/\\/g, '\\\\') + .replace(/\n/g, '\\\n') + .replace(/'/g, '\\\''); + return '\'' + string + '\''; +}; + +/** + * Common tasks for generating JavaScript from blocks. + * Handles comments for the specified block and any connected value blocks. + * Calls any statements following this block. + * @param {!Blockly.Block} block The current block. + * @param {string} code The JavaScript code created for this block. + * @return {string} JavaScript code with comments and subsequent blocks added. + * @this {Blockly.CodeGenerator} + * @private + */ +Blockly.JavaScript.scrub_ = function(block, code) { + if (code === null) { + // Block has handled code generation itself. + return ''; + } + var commentCode = ''; + // Only collect comments for blocks that aren't inline. + if (!block.outputConnection || !block.outputConnection.targetConnection) { + // Collect comment for this block. + var comment = block.getCommentText(); + if (comment) { + commentCode += this.prefixLines(comment, '// ') + '\n'; + } + // Collect comments for all value arguments. + // Don't collect comments for nested statements. + for (var x = 0; x < block.inputList.length; x++) { + if (block.inputList[x].type == Blockly.INPUT_VALUE) { + var childBlock = block.inputList[x].connection.targetBlock(); + if (childBlock) { + var comment = this.allNestedComments(childBlock); + if (comment) { + commentCode += this.prefixLines(comment, '// '); + } + } + } + } + } + var nextBlock = block.nextConnection && block.nextConnection.targetBlock(); + var nextCode = this.blockToCode(nextBlock); + return commentCode + code + nextCode; +}; diff --git a/generators/javascript/colour.js b/generators/javascript/colour.js new file mode 100644 index 000000000..ef05717fa --- /dev/null +++ b/generators/javascript/colour.js @@ -0,0 +1,119 @@ +/** + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Generating JavaScript for colour blocks. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.JavaScript.colour'); + +goog.require('Blockly.JavaScript'); + + +Blockly.JavaScript['colour_picker'] = function(block) { + // Colour picker. + var code = '\'' + block.getTitleValue('COLOUR') + '\''; + return [code, Blockly.JavaScript.ORDER_ATOMIC]; +}; + +Blockly.JavaScript['colour_random'] = function(block) { + // Generate a random colour. + if (!Blockly.JavaScript.definitions_['colour_random']) { + var functionName = Blockly.JavaScript.variableDB_.getDistinctName( + 'colour_random', Blockly.Generator.NAME_TYPE); + Blockly.JavaScript.colour_random.functionName = functionName; + var func = []; + func.push('function ' + functionName + '() {'); + func.push(' var num = Math.floor(Math.random() * Math.pow(2, 24));'); + func.push(' return \'#\' + (\'00000\' + num.toString(16)).substr(-6);'); + func.push('}'); + Blockly.JavaScript.definitions_['colour_random'] = func.join('\n'); + } + var code = Blockly.JavaScript.colour_random.functionName + '()'; + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; +}; + +Blockly.JavaScript['colour_rgb'] = function(block) { + // Compose a colour from RGB components expressed as percentages. + var red = Blockly.JavaScript.valueToCode(block, 'RED', + Blockly.JavaScript.ORDER_COMMA) || 0; + var green = Blockly.JavaScript.valueToCode(block, 'GREEN', + Blockly.JavaScript.ORDER_COMMA) || 0; + var blue = Blockly.JavaScript.valueToCode(block, 'BLUE', + Blockly.JavaScript.ORDER_COMMA) || 0; + + if (!Blockly.JavaScript.definitions_['colour_rgb']) { + var functionName = Blockly.JavaScript.variableDB_.getDistinctName( + 'colour_rgb', Blockly.Generator.NAME_TYPE); + Blockly.JavaScript.colour_rgb.functionName = functionName; + var func = []; + func.push('function ' + functionName + '(r, g, b) {'); + func.push(' r = Math.max(Math.min(Number(r), 100), 0) * 2.55;'); + func.push(' g = Math.max(Math.min(Number(g), 100), 0) * 2.55;'); + func.push(' b = Math.max(Math.min(Number(b), 100), 0) * 2.55;'); + func.push(' r = (\'0\' + (Math.round(r) || 0).toString(16)).slice(-2);'); + func.push(' g = (\'0\' + (Math.round(g) || 0).toString(16)).slice(-2);'); + func.push(' b = (\'0\' + (Math.round(b) || 0).toString(16)).slice(-2);'); + func.push(' return \'#\' + r + g + b;'); + func.push('}'); + Blockly.JavaScript.definitions_['colour_rgb'] = func.join('\n'); + } + var code = Blockly.JavaScript.colour_rgb.functionName + + '(' + red + ', ' + green + ', ' + blue + ')'; + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; +}; + +Blockly.JavaScript['colour_blend'] = function(block) { + // Blend two colours together. + var c1 = Blockly.JavaScript.valueToCode(block, 'COLOUR1', + Blockly.JavaScript.ORDER_COMMA) || '\'#000000\''; + var c2 = Blockly.JavaScript.valueToCode(block, 'COLOUR2', + Blockly.JavaScript.ORDER_COMMA) || '\'#000000\''; + var ratio = Blockly.JavaScript.valueToCode(block, 'RATIO', + Blockly.JavaScript.ORDER_COMMA) || 0.5; + + if (!Blockly.JavaScript.definitions_['colour_blend']) { + var functionName = Blockly.JavaScript.variableDB_.getDistinctName( + 'colour_blend', Blockly.Generator.NAME_TYPE); + Blockly.JavaScript.colour_blend.functionName = functionName; + var func = []; + func.push('function ' + functionName + '(c1, c2, ratio) {'); + func.push(' ratio = Math.max(Math.min(Number(ratio), 1), 0);'); + func.push(' var r1 = parseInt(c1.substring(1, 3), 16);'); + func.push(' var g1 = parseInt(c1.substring(3, 5), 16);'); + func.push(' var b1 = parseInt(c1.substring(5, 7), 16);'); + func.push(' var r2 = parseInt(c2.substring(1, 3), 16);'); + func.push(' var g2 = parseInt(c2.substring(3, 5), 16);'); + func.push(' var b2 = parseInt(c2.substring(5, 7), 16);'); + func.push(' var r = Math.round(r1 * (1 - ratio) + r2 * ratio);'); + func.push(' var g = Math.round(g1 * (1 - ratio) + g2 * ratio);'); + func.push(' var b = Math.round(b1 * (1 - ratio) + b2 * ratio);'); + func.push(' r = (\'0\' + (r || 0).toString(16)).slice(-2);'); + func.push(' g = (\'0\' + (g || 0).toString(16)).slice(-2);'); + func.push(' b = (\'0\' + (b || 0).toString(16)).slice(-2);'); + func.push(' return \'#\' + r + g + b;'); + func.push('}'); + Blockly.JavaScript.definitions_['colour_blend'] = func.join('\n'); + } + var code = Blockly.JavaScript.colour_blend.functionName + + '(' + c1 + ', ' + c2 + ', ' + ratio + ')'; + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; +}; diff --git a/generators/javascript/lists.js b/generators/javascript/lists.js new file mode 100644 index 000000000..f446e2e82 --- /dev/null +++ b/generators/javascript/lists.js @@ -0,0 +1,323 @@ +/** + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Generating JavaScript for list blocks. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.JavaScript.lists'); + +goog.require('Blockly.JavaScript'); + + +Blockly.JavaScript['lists_create_empty'] = function(block) { + // Create an empty list. + return ['[]', Blockly.JavaScript.ORDER_ATOMIC]; +}; + +Blockly.JavaScript['lists_create_with'] = function(block) { + // Create a list with any number of elements of any type. + var code = new Array(block.itemCount_); + for (var n = 0; n < block.itemCount_; n++) { + code[n] = Blockly.JavaScript.valueToCode(block, 'ADD' + n, + Blockly.JavaScript.ORDER_COMMA) || 'null'; + } + code = '[' + code.join(', ') + ']'; + return [code, Blockly.JavaScript.ORDER_ATOMIC]; +}; + +Blockly.JavaScript['lists_repeat'] = function(block) { + // Create a list with one element repeated. + if (!Blockly.JavaScript.definitions_['lists_repeat']) { + // Function copied from Closure's goog.array.repeat. + var functionName = Blockly.JavaScript.variableDB_.getDistinctName( + 'lists_repeat', Blockly.Generator.NAME_TYPE); + Blockly.JavaScript.lists_repeat.repeat = functionName; + var func = []; + func.push('function ' + functionName + '(value, n) {'); + func.push(' var array = [];'); + func.push(' for (var i = 0; i < n; i++) {'); + func.push(' array[i] = value;'); + func.push(' }'); + func.push(' return array;'); + func.push('}'); + Blockly.JavaScript.definitions_['lists_repeat'] = func.join('\n'); + } + var argument0 = Blockly.JavaScript.valueToCode(block, 'ITEM', + Blockly.JavaScript.ORDER_COMMA) || 'null'; + var argument1 = Blockly.JavaScript.valueToCode(block, 'NUM', + Blockly.JavaScript.ORDER_COMMA) || '0'; + var code = Blockly.JavaScript.lists_repeat.repeat + + '(' + argument0 + ', ' + argument1 + ')'; + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; +}; + +Blockly.JavaScript['lists_length'] = function(block) { + // List length. + var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE', + Blockly.JavaScript.ORDER_FUNCTION_CALL) || '\'\''; + return [argument0 + '.length', Blockly.JavaScript.ORDER_MEMBER]; +}; + +Blockly.JavaScript['lists_isEmpty'] = function(block) { + // Is the list empty? + var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE', + Blockly.JavaScript.ORDER_MEMBER) || '[]'; + return ['!' + argument0 + '.length', Blockly.JavaScript.ORDER_LOGICAL_NOT]; +}; + +Blockly.JavaScript['lists_indexOf'] = function(block) { + // Find an item in the list. + var operator = block.getTitleValue('END') == 'FIRST' ? + 'indexOf' : 'lastIndexOf'; + var argument0 = Blockly.JavaScript.valueToCode(block, 'FIND', + Blockly.JavaScript.ORDER_NONE) || '\'\''; + var argument1 = Blockly.JavaScript.valueToCode(block, 'VALUE', + Blockly.JavaScript.ORDER_MEMBER) || '[]'; + var code = argument1 + '.' + operator + '(' + argument0 + ') + 1'; + return [code, Blockly.JavaScript.ORDER_MEMBER]; +}; + +Blockly.JavaScript['lists_getIndex'] = function(block) { + // Get element at index. + // Note: Until January 2013 this block did not have MODE or WHERE inputs. + var mode = block.getTitleValue('MODE') || 'GET'; + var where = block.getTitleValue('WHERE') || 'FROM_START'; + var at = Blockly.JavaScript.valueToCode(block, 'AT', + Blockly.JavaScript.ORDER_UNARY_NEGATION) || '1'; + var list = Blockly.JavaScript.valueToCode(block, 'VALUE', + Blockly.JavaScript.ORDER_MEMBER) || '[]'; + + if (where == 'FIRST') { + if (mode == 'GET') { + var code = list + '[0]'; + return [code, Blockly.JavaScript.ORDER_MEMBER]; + } else if (mode == 'GET_REMOVE') { + var code = list + '.shift()'; + return [code, Blockly.JavaScript.ORDER_MEMBER]; + } else if (mode == 'REMOVE') { + return list + '.shift();\n'; + } + } else if (where == 'LAST') { + if (mode == 'GET') { + var code = list + '.slice(-1)[0]'; + return [code, Blockly.JavaScript.ORDER_MEMBER]; + } else if (mode == 'GET_REMOVE') { + var code = list + '.pop()'; + return [code, Blockly.JavaScript.ORDER_MEMBER]; + } else if (mode == 'REMOVE') { + return list + '.pop();\n'; + } + } else if (where == 'FROM_START') { + // Blockly uses one-based indicies. + if (Blockly.isNumber(at)) { + // If the index is a naked number, decrement it right now. + at = parseFloat(at) - 1; + } else { + // If the index is dynamic, decrement it in code. + at += ' - 1'; + } + if (mode == 'GET') { + var code = list + '[' + at + ']'; + return [code, Blockly.JavaScript.ORDER_MEMBER]; + } else if (mode == 'GET_REMOVE') { + var code = list + '.splice(' + at + ', 1)[0]'; + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; + } else if (mode == 'REMOVE') { + return list + '.splice(' + at + ', 1);\n'; + } + } else if (where == 'FROM_END') { + if (mode == 'GET') { + var code = list + '.slice(-' + at + ')[0]'; + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; + } else if (mode == 'GET_REMOVE' || mode == 'REMOVE') { + if (!Blockly.JavaScript.definitions_['lists_remove_from_end']) { + var functionName = Blockly.JavaScript.variableDB_.getDistinctName( + 'lists_remove_from_end', Blockly.Generator.NAME_TYPE); + Blockly.JavaScript.lists_getIndex.lists_remove_from_end = functionName; + var func = []; + func.push('function ' + functionName + '(list, x) {'); + func.push(' x = list.length - x;'); + func.push(' return list.splice(x, 1)[0];'); + func.push('}'); + Blockly.JavaScript.definitions_['lists_remove_from_end'] = + func.join('\n'); + } + code = Blockly.JavaScript.lists_getIndex.lists_remove_from_end + + '(' + list + ', ' + at + ')'; + if (mode == 'GET_REMOVE') { + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; + } else if (mode == 'REMOVE') { + return code + ';\n'; + } + } + } else if (where == 'RANDOM') { + if (!Blockly.JavaScript.definitions_['lists_get_random_item']) { + var functionName = Blockly.JavaScript.variableDB_.getDistinctName( + 'lists_get_random_item', Blockly.Generator.NAME_TYPE); + Blockly.JavaScript.lists_getIndex.random = functionName; + var func = []; + func.push('function ' + functionName + '(list, remove) {'); + func.push(' var x = Math.floor(Math.random() * list.length);'); + func.push(' if (remove) {'); + func.push(' return list.splice(x, 1)[0];'); + func.push(' } else {'); + func.push(' return list[x];'); + func.push(' }'); + func.push('}'); + Blockly.JavaScript.definitions_['lists_get_random_item'] = + func.join('\n'); + } + code = Blockly.JavaScript.lists_getIndex.random + + '(' + list + ', ' + (mode != 'GET') + ')'; + if (mode == 'GET' || mode == 'GET_REMOVE') { + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; + } else if (mode == 'REMOVE') { + return code + ';\n'; + } + } + throw 'Unhandled combination (lists_getIndex).'; +}; + +Blockly.JavaScript['lists_setIndex'] = function(block) { + // Set element at index. + // Note: Until February 2013 this block did not have MODE or WHERE inputs. + var list = Blockly.JavaScript.valueToCode(block, 'LIST', + Blockly.JavaScript.ORDER_MEMBER) || '[]'; + var mode = block.getTitleValue('MODE') || 'GET'; + var where = block.getTitleValue('WHERE') || 'FROM_START'; + var at = Blockly.JavaScript.valueToCode(block, 'AT', + Blockly.JavaScript.ORDER_NONE) || '1'; + var value = Blockly.JavaScript.valueToCode(block, 'TO', + Blockly.JavaScript.ORDER_ASSIGNMENT) || 'null'; + // Cache non-trivial values to variables to prevent repeated look-ups. + // Closure, which accesses and modifies 'list'. + function cacheList() { + if (list.match(/^\w+$/)) { + return ''; + } + var listVar = Blockly.JavaScript.variableDB_.getDistinctName( + 'tmp_list', Blockly.Variables.NAME_TYPE); + var code = 'var ' + listVar + ' = ' + list + ';\n'; + list = listVar; + return code; + } + if (where == 'FIRST') { + if (mode == 'SET') { + return list + '[0] = ' + value + ';\n'; + } else if (mode == 'INSERT') { + return list + '.unshift(' + value + ');\n'; + } + } else if (where == 'LAST') { + if (mode == 'SET') { + var code = cacheList(); + code += list + '[' + list + '.length - 1] = ' + value + ';\n'; + return code; + } else if (mode == 'INSERT') { + return list + '.push(' + value + ');\n'; + } + } else if (where == 'FROM_START') { + // Blockly uses one-based indicies. + if (Blockly.isNumber(at)) { + // If the index is a naked number, decrement it right now. + at = parseFloat(at) - 1; + } else { + // If the index is dynamic, decrement it in code. + at += ' - 1'; + } + if (mode == 'SET') { + return list + '[' + at + '] = ' + value + ';\n'; + } else if (mode == 'INSERT') { + return list + '.splice(' + at + ', 0, ' + value + ');\n'; + } + } else if (where == 'FROM_END') { + var code = cacheList(); + if (mode == 'SET') { + code += list + '[' + list + '.length - ' + at + '] = ' + value + ';\n'; + return code; + } else if (mode == 'INSERT') { + code += list + '.splice(' + list + '.length - ' + at + ', 0, ' + value + + ');\n'; + return code; + } + } else if (where == 'RANDOM') { + var code = cacheList(); + var xVar = Blockly.JavaScript.variableDB_.getDistinctName( + 'tmp_x', Blockly.Variables.NAME_TYPE); + code += 'var ' + xVar + ' = Math.floor(Math.random() * ' + list + + '.length);\n'; + if (mode == 'SET') { + code += list + '[' + xVar + '] = ' + value + ';\n'; + return code; + } else if (mode == 'INSERT') { + code += list + '.splice(' + xVar + ', 0, ' + value + ');\n'; + return code; + } + } + throw 'Unhandled combination (lists_setIndex).'; +}; + +Blockly.JavaScript['lists_getSublist'] = function(block) { + // Get sublist. + var list = Blockly.JavaScript.valueToCode(block, 'LIST', + Blockly.JavaScript.ORDER_MEMBER) || '[]'; + var where1 = block.getTitleValue('WHERE1'); + var where2 = block.getTitleValue('WHERE2'); + var at1 = Blockly.JavaScript.valueToCode(block, 'AT1', + Blockly.JavaScript.ORDER_NONE) || '1'; + var at2 = Blockly.JavaScript.valueToCode(block, 'AT2', + Blockly.JavaScript.ORDER_NONE) || '1'; + if (where1 == 'FIRST' && where2 == 'LAST') { + var code = list + '.concat()'; + } else { + if (!Blockly.JavaScript.definitions_['lists_get_sublist']) { + var functionName = Blockly.JavaScript.variableDB_.getDistinctName( + 'lists_get_sublist', Blockly.Generator.NAME_TYPE); + Blockly.JavaScript.lists_getSublist.func = functionName; + var func = []; + func.push('function ' + functionName + + '(list, where1, at1, where2, at2) {'); + func.push(' function getAt(where, at) {'); + func.push(' if (where == \'FROM_START\') {'); + func.push(' at--;'); + func.push(' } else if (where == \'FROM_END\') {'); + func.push(' at = list.length - at;'); + func.push(' } else if (where == \'FIRST\') {'); + func.push(' at = 0;'); + func.push(' } else if (where == \'LAST\') {'); + func.push(' at = list.length - 1;'); + func.push(' } else {'); + func.push(' throw \'Unhandled option (lists_getSublist).\';'); + func.push(' }'); + func.push(' return at;'); + func.push(' }'); + func.push(' at1 = getAt(where1, at1);'); + func.push(' at2 = getAt(where2, at2) + 1;'); + func.push(' return list.slice(at1, at2);'); + func.push('}'); + Blockly.JavaScript.definitions_['lists_get_sublist'] = + func.join('\n'); + } + var code = Blockly.JavaScript.lists_getSublist.func + '(' + list + ', \'' + + where1 + '\', ' + at1 + ', \'' + where2 + '\', ' + at2 + ')'; + } + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; +}; diff --git a/generators/javascript/logic.js b/generators/javascript/logic.js new file mode 100644 index 000000000..b8880dd81 --- /dev/null +++ b/generators/javascript/logic.js @@ -0,0 +1,125 @@ +/** + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Generating JavaScript for logic blocks. + * @author q.neutron@gmail.com (Quynh Neutron) + */ +'use strict'; + +goog.provide('Blockly.JavaScript.logic'); + +goog.require('Blockly.JavaScript'); + + +Blockly.JavaScript['controls_if'] = function(block) { + // If/elseif/else condition. + var n = 0; + var argument = Blockly.JavaScript.valueToCode(block, 'IF' + n, + Blockly.JavaScript.ORDER_NONE) || 'false'; + var branch = Blockly.JavaScript.statementToCode(block, 'DO' + n); + var code = 'if (' + argument + ') {\n' + branch + '}'; + for (n = 1; n <= block.elseifCount_; n++) { + argument = Blockly.JavaScript.valueToCode(block, 'IF' + n, + Blockly.JavaScript.ORDER_NONE) || 'false'; + branch = Blockly.JavaScript.statementToCode(block, 'DO' + n); + code += ' else if (' + argument + ') {\n' + branch + '}'; + } + if (block.elseCount_) { + branch = Blockly.JavaScript.statementToCode(block, 'ELSE'); + code += ' else {\n' + branch + '}\n'; + } + return code + '\n'; +}; + +Blockly.JavaScript['logic_compare'] = function(block) { + // Comparison operator. + var OPERATORS = { + EQ: '==', + NEQ: '!=', + LT: '<', + LTE: '<=', + GT: '>', + GTE: '>=' + }; + var operator = OPERATORS[block.getTitleValue('OP')]; + var order = (operator == '==' || operator == '!=') ? + Blockly.JavaScript.ORDER_EQUALITY : Blockly.JavaScript.ORDER_RELATIONAL; + var argument0 = Blockly.JavaScript.valueToCode(block, 'A', order) || '0'; + var argument1 = Blockly.JavaScript.valueToCode(block, 'B', order) || '0'; + var code = argument0 + ' ' + operator + ' ' + argument1; + return [code, order]; +}; + +Blockly.JavaScript['logic_operation'] = function(block) { + // Operations 'and', 'or'. + var operator = (block.getTitleValue('OP') == 'AND') ? '&&' : '||'; + var order = (operator == '&&') ? Blockly.JavaScript.ORDER_LOGICAL_AND : + Blockly.JavaScript.ORDER_LOGICAL_OR; + var argument0 = Blockly.JavaScript.valueToCode(block, 'A', order); + var argument1 = Blockly.JavaScript.valueToCode(block, 'B', order); + if (!argument0 && !argument1) { + // If there are no arguments, then the return value is false. + argument0 = 'false'; + argument1 = 'false'; + } else { + // Single missing arguments have no effect on the return value. + var defaultArgument = (operator == '&&') ? 'true' : 'false'; + if (!argument0) { + argument0 = defaultArgument; + } + if (!argument1) { + argument1 = defaultArgument; + } + } + var code = argument0 + ' ' + operator + ' ' + argument1; + return [code, order]; +}; + +Blockly.JavaScript['logic_negate'] = function(block) { + // Negation. + var order = Blockly.JavaScript.ORDER_LOGICAL_NOT; + var argument0 = Blockly.JavaScript.valueToCode(block, 'BOOL', order) || + 'true'; + var code = '!' + argument0; + return [code, order]; +}; + +Blockly.JavaScript['logic_boolean'] = function(block) { + // Boolean values true and false. + var code = (block.getTitleValue('BOOL') == 'TRUE') ? 'true' : 'false'; + return [code, Blockly.JavaScript.ORDER_ATOMIC]; +}; + +Blockly.JavaScript['logic_null'] = function(block) { + // Null data type. + return ['null', Blockly.JavaScript.ORDER_ATOMIC]; +}; + +Blockly.JavaScript['logic_ternary'] = function(block) { + // Ternary operator. + var value_if = Blockly.JavaScript.valueToCode(block, 'IF', + Blockly.JavaScript.ORDER_CONDITIONAL) || 'false'; + var value_then = Blockly.JavaScript.valueToCode(block, 'THEN', + Blockly.JavaScript.ORDER_CONDITIONAL) || 'null'; + var value_else = Blockly.JavaScript.valueToCode(block, 'ELSE', + Blockly.JavaScript.ORDER_CONDITIONAL) || 'null'; + var code = value_if + ' ? ' + value_then + ' : ' + value_else + return [code, Blockly.JavaScript.ORDER_CONDITIONAL]; +}; diff --git a/generators/javascript/loops.js b/generators/javascript/loops.js new file mode 100644 index 000000000..7496753c7 --- /dev/null +++ b/generators/javascript/loops.js @@ -0,0 +1,200 @@ +/** + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Generating JavaScript for loop blocks. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.JavaScript.loops'); + +goog.require('Blockly.JavaScript'); + + +Blockly.JavaScript['controls_repeat'] = function(block) { + // Repeat n times (internal number). + var repeats = Number(block.getTitleValue('TIMES')); + var branch = Blockly.JavaScript.statementToCode(block, 'DO'); + if (Blockly.JavaScript.INFINITE_LOOP_TRAP) { + branch = Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g, + '\'' + block.id + '\'') + branch; + } + var loopVar = Blockly.JavaScript.variableDB_.getDistinctName( + 'count', Blockly.Variables.NAME_TYPE); + var code = 'for (var ' + loopVar + ' = 0; ' + + loopVar + ' < ' + repeats + '; ' + + loopVar + '++) {\n' + + branch + '}\n'; + return code; +}; + +Blockly.JavaScript['controls_repeat_ext'] = function(block) { + // Repeat n times (external number). + var repeats = Blockly.JavaScript.valueToCode(block, 'TIMES', + Blockly.JavaScript.ORDER_ASSIGNMENT) || '0'; + var branch = Blockly.JavaScript.statementToCode(block, 'DO'); + if (Blockly.JavaScript.INFINITE_LOOP_TRAP) { + branch = Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g, + '\'' + block.id + '\'') + branch; + } + var code = ''; + var loopVar = Blockly.JavaScript.variableDB_.getDistinctName( + 'count', Blockly.Variables.NAME_TYPE); + var endVar = repeats; + if (!repeats.match(/^\w+$/) && !Blockly.isNumber(repeats)) { + var endVar = Blockly.JavaScript.variableDB_.getDistinctName( + 'repeat_end', Blockly.Variables.NAME_TYPE); + code += 'var ' + endVar + ' = ' + repeats + ';\n'; + } + code += 'for (var ' + loopVar + ' = 0; ' + + loopVar + ' < ' + endVar + '; ' + + loopVar + '++) {\n' + + branch + '}\n'; + return code; +}; + +Blockly.JavaScript['controls_whileUntil'] = function(block) { + // Do while/until loop. + var until = block.getTitleValue('MODE') == 'UNTIL'; + var argument0 = Blockly.JavaScript.valueToCode(block, 'BOOL', + until ? Blockly.JavaScript.ORDER_LOGICAL_NOT : + Blockly.JavaScript.ORDER_NONE) || 'false'; + var branch = Blockly.JavaScript.statementToCode(block, 'DO'); + if (Blockly.JavaScript.INFINITE_LOOP_TRAP) { + branch = Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g, + '\'' + block.id + '\'') + branch; + } + if (until) { + argument0 = '!' + argument0; + } + return 'while (' + argument0 + ') {\n' + branch + '}\n'; +}; + +Blockly.JavaScript['controls_for'] = function(block) { + // For loop. + var variable0 = Blockly.JavaScript.variableDB_.getName( + block.getTitleValue('VAR'), Blockly.Variables.NAME_TYPE); + var argument0 = Blockly.JavaScript.valueToCode(block, 'FROM', + Blockly.JavaScript.ORDER_ASSIGNMENT) || '0'; + var argument1 = Blockly.JavaScript.valueToCode(block, 'TO', + Blockly.JavaScript.ORDER_ASSIGNMENT) || '0'; + var increment = Blockly.JavaScript.valueToCode(block, 'BY', + Blockly.JavaScript.ORDER_ASSIGNMENT) || '1'; + var branch = Blockly.JavaScript.statementToCode(block, 'DO'); + if (Blockly.JavaScript.INFINITE_LOOP_TRAP) { + branch = Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g, + '\'' + block.id + '\'') + branch; + } + var code; + if (Blockly.isNumber(argument0) && Blockly.isNumber(argument1) && + Blockly.isNumber(increment)) { + // All arguments are simple numbers. + var up = parseFloat(argument0) <= parseFloat(argument1); + code = 'for (' + variable0 + ' = ' + argument0 + '; ' + + variable0 + (up ? ' <= ' : ' >= ') + argument1 + '; ' + + variable0; + var step = Math.abs(parseFloat(increment)); + if (step == 1) { + code += up ? '++' : '--'; + } else { + code += (up ? ' += ' : ' -= ') + step; + } + code += ') {\n' + branch + '}\n'; + } else { + code = ''; + // Cache non-trivial values to variables to prevent repeated look-ups. + var startVar = argument0; + if (!argument0.match(/^\w+$/) && !Blockly.isNumber(argument0)) { + var startVar = Blockly.JavaScript.variableDB_.getDistinctName( + variable0 + '_start', Blockly.Variables.NAME_TYPE); + code += 'var ' + startVar + ' = ' + argument0 + ';\n'; + } + var endVar = argument1; + if (!argument1.match(/^\w+$/) && !Blockly.isNumber(argument1)) { + var endVar = Blockly.JavaScript.variableDB_.getDistinctName( + variable0 + '_end', Blockly.Variables.NAME_TYPE); + code += 'var ' + endVar + ' = ' + argument1 + ';\n'; + } + // Determine loop direction at start, in case one of the bounds + // changes during loop execution. + var incVar = Blockly.JavaScript.variableDB_.getDistinctName( + variable0 + '_inc', Blockly.Variables.NAME_TYPE); + code += 'var ' + incVar + ' = '; + if (Blockly.isNumber(increment)) { + code += Math.abs(increment) + ';\n'; + } else { + code += 'Math.abs(' + increment + ');\n'; + } + code += 'if (' + startVar + ' > ' + endVar + ') {\n'; + code += ' ' + incVar + ' = -' + incVar +';\n'; + code += '}\n'; + code += 'for (' + variable0 + ' = ' + startVar + ';\n' + + ' ' + incVar + ' >= 0 ? ' + + variable0 + ' <= ' + endVar + ' : ' + + variable0 + ' >= ' + endVar + ';\n' + + ' ' + variable0 + ' += ' + incVar + ') {\n' + + branch + '}\n'; + } + return code; +}; + +Blockly.JavaScript['controls_forEach'] = function(block) { + // For each loop. + var variable0 = Blockly.JavaScript.variableDB_.getName( + block.getTitleValue('VAR'), Blockly.Variables.NAME_TYPE); + var argument0 = Blockly.JavaScript.valueToCode(block, 'LIST', + Blockly.JavaScript.ORDER_ASSIGNMENT) || '[]'; + var branch = Blockly.JavaScript.statementToCode(block, 'DO'); + if (Blockly.JavaScript.INFINITE_LOOP_TRAP) { + branch = Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g, + '\'' + block.id + '\'') + branch; + } + var code; + var indexVar = Blockly.JavaScript.variableDB_.getDistinctName( + variable0 + '_index', Blockly.Variables.NAME_TYPE); + if (argument0.match(/^\w+$/)) { + branch = ' ' + variable0 + ' = ' + argument0 + '[' + indexVar + '];\n' + + branch; + code = 'for (var ' + indexVar + ' in ' + argument0 + ') {\n' + + branch + '}\n'; + } else { + // The list appears to be more complicated than a simple variable. + // Cache it to a variable to prevent repeated look-ups. + var listVar = Blockly.JavaScript.variableDB_.getDistinctName( + variable0 + '_list', Blockly.Variables.NAME_TYPE); + branch = ' ' + variable0 + ' = ' + listVar + '[' + indexVar + '];\n' + + branch; + code = 'var ' + listVar + ' = ' + argument0 + ';\n' + + 'for (var ' + indexVar + ' in ' + listVar + ') {\n' + + branch + '}\n'; + } + return code; +}; + +Blockly.JavaScript['controls_flow_statements'] = function(block) { + // Flow statements: continue, break. + switch (block.getTitleValue('FLOW')) { + case 'BREAK': + return 'break;\n'; + case 'CONTINUE': + return 'continue;\n'; + } + throw 'Unknown flow statement.'; +}; diff --git a/generators/javascript/math.js b/generators/javascript/math.js new file mode 100644 index 000000000..5e16b5b8a --- /dev/null +++ b/generators/javascript/math.js @@ -0,0 +1,443 @@ +/** + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Generating JavaScript for math blocks. + * @author q.neutron@gmail.com (Quynh Neutron) + */ +'use strict'; + +goog.provide('Blockly.JavaScript.math'); + +goog.require('Blockly.JavaScript'); + + +Blockly.JavaScript['math_number'] = function(block) { + // Numeric value. + var code = parseFloat(block.getTitleValue('NUM')); + return [code, Blockly.JavaScript.ORDER_ATOMIC]; +}; + +Blockly.JavaScript['math_arithmetic'] = function(block) { + // Basic arithmetic operators, and power. + var OPERATORS = { + ADD: [' + ', Blockly.JavaScript.ORDER_ADDITION], + MINUS: [' - ', Blockly.JavaScript.ORDER_SUBTRACTION], + MULTIPLY: [' * ', Blockly.JavaScript.ORDER_MULTIPLICATION], + DIVIDE: [' / ', Blockly.JavaScript.ORDER_DIVISION], + POWER: [null, Blockly.JavaScript.ORDER_COMMA] // Handle power separately. + }; + var tuple = OPERATORS[block.getTitleValue('OP')]; + var operator = tuple[0]; + var order = tuple[1]; + var argument0 = Blockly.JavaScript.valueToCode(block, 'A', order) || '0'; + var argument1 = Blockly.JavaScript.valueToCode(block, 'B', order) || '0'; + var code; + // Power in JavaScript requires a special case since it has no operator. + if (!operator) { + code = 'Math.pow(' + argument0 + ', ' + argument1 + ')'; + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; + } + code = argument0 + operator + argument1; + return [code, order]; +}; + +Blockly.JavaScript['math_single'] = function(block) { + // Math operators with single operand. + var operator = block.getTitleValue('OP'); + var code; + var arg; + if (operator == 'NEG') { + // Negation is a special case given its different operator precedence. + arg = Blockly.JavaScript.valueToCode(block, 'NUM', + Blockly.JavaScript.ORDER_UNARY_NEGATION) || '0'; + if (arg[0] == '-') { + // --3 is not legal in JS. + arg = ' ' + arg; + } + code = '-' + arg; + return [code, Blockly.JavaScript.ORDER_UNARY_NEGATION]; + } + if (operator == 'SIN' || operator == 'COS' || operator == 'TAN') { + arg = Blockly.JavaScript.valueToCode(block, 'NUM', + Blockly.JavaScript.ORDER_DIVISION) || '0'; + } else { + arg = Blockly.JavaScript.valueToCode(block, 'NUM', + Blockly.JavaScript.ORDER_NONE) || '0'; + } + // First, handle cases which generate values that don't need parentheses + // wrapping the code. + switch (operator) { + case 'ABS': + code = 'Math.abs(' + arg + ')'; + break; + case 'ROOT': + code = 'Math.sqrt(' + arg + ')'; + break; + case 'LN': + code = 'Math.log(' + arg + ')'; + break; + case 'EXP': + code = 'Math.exp(' + arg + ')'; + break; + case 'POW10': + code = 'Math.pow(10,' + arg + ')'; + break; + case 'ROUND': + code = 'Math.round(' + arg + ')'; + break; + case 'ROUNDUP': + code = 'Math.ceil(' + arg + ')'; + break; + case 'ROUNDDOWN': + code = 'Math.floor(' + arg + ')'; + break; + case 'SIN': + code = 'Math.sin(' + arg + ' / 180 * Math.PI)'; + break; + case 'COS': + code = 'Math.cos(' + arg + ' / 180 * Math.PI)'; + break; + case 'TAN': + code = 'Math.tan(' + arg + ' / 180 * Math.PI)'; + break; + } + if (code) { + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; + } + // Second, handle cases which generate values that may need parentheses + // wrapping the code. + switch (operator) { + case 'LOG10': + code = 'Math.log(' + arg + ') / Math.log(10)'; + break; + case 'ASIN': + code = 'Math.asin(' + arg + ') / Math.PI * 180'; + break; + case 'ACOS': + code = 'Math.acos(' + arg + ') / Math.PI * 180'; + break; + case 'ATAN': + code = 'Math.atan(' + arg + ') / Math.PI * 180'; + break; + default: + throw 'Unknown math operator: ' + operator; + } + return [code, Blockly.JavaScript.ORDER_DIVISION]; +}; + +Blockly.JavaScript['math_constant'] = function(block) { + // Constants: PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), INFINITY. + var CONSTANTS = { + PI: ['Math.PI', Blockly.JavaScript.ORDER_MEMBER], + E: ['Math.E', Blockly.JavaScript.ORDER_MEMBER], + GOLDEN_RATIO: ['(1 + Math.sqrt(5)) / 2', Blockly.JavaScript.ORDER_DIVISION], + SQRT2: ['Math.SQRT2', Blockly.JavaScript.ORDER_MEMBER], + SQRT1_2: ['Math.SQRT1_2', Blockly.JavaScript.ORDER_MEMBER], + INFINITY: ['Infinity', Blockly.JavaScript.ORDER_ATOMIC] + }; + return CONSTANTS[block.getTitleValue('CONSTANT')]; +}; + +Blockly.JavaScript['math_number_property'] = function(block) { + // Check if a number is even, odd, prime, whole, positive, or negative + // or if it is divisible by certain number. Returns true or false. + var number_to_check = Blockly.JavaScript.valueToCode(block, 'NUMBER_TO_CHECK', + Blockly.JavaScript.ORDER_MODULUS) || '0'; + var dropdown_property = block.getTitleValue('PROPERTY'); + var code; + if (dropdown_property == 'PRIME') { + // Prime is a special case as it is not a one-liner test. + if (!Blockly.JavaScript.definitions_['isPrime']) { + var functionName = Blockly.JavaScript.variableDB_.getDistinctName( + 'isPrime', Blockly.Generator.NAME_TYPE); + Blockly.JavaScript.logic_prime= functionName; + var func = []; + func.push('function ' + functionName + '(n) {'); + func.push(' // http://en.wikipedia.org/wiki/Primality_test#Naive_methods'); + func.push(' if (n == 2 || n == 3) {'); + func.push(' return true;'); + func.push(' }'); + func.push(' // False if n is NaN, negative, is 1, or not whole.'); + func.push(' // And false if n is divisible by 2 or 3.'); + func.push(' if (isNaN(n) || n <= 1 || n % 1 != 0 || n % 2 == 0 ||' + + ' n % 3 == 0) {'); + func.push(' return false;'); + func.push(' }'); + func.push(' // Check all the numbers of form 6k +/- 1, up to sqrt(n).'); + func.push(' for (var x = 6; x <= Math.sqrt(n) + 1; x += 6) {'); + func.push(' if (n % (x - 1) == 0 || n % (x + 1) == 0) {'); + func.push(' return false;'); + func.push(' }'); + func.push(' }'); + func.push(' return true;'); + func.push('}'); + Blockly.JavaScript.definitions_['isPrime'] = func.join('\n'); + } + code = Blockly.JavaScript.logic_prime + '(' + number_to_check + ')'; + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; + } + switch (dropdown_property) { + case 'EVEN': + code = number_to_check + ' % 2 == 0'; + break; + case 'ODD': + code = number_to_check + ' % 2 == 1'; + break; + case 'WHOLE': + code = number_to_check + ' % 1 == 0'; + break; + case 'POSITIVE': + code = number_to_check + ' > 0'; + break; + case 'NEGATIVE': + code = number_to_check + ' < 0'; + break; + case 'DIVISIBLE_BY': + var divisor = Blockly.JavaScript.valueToCode(block, 'DIVISOR', + Blockly.JavaScript.ORDER_MODULUS) || '0'; + code = number_to_check + ' % ' + divisor + ' == 0'; + break; + } + return [code, Blockly.JavaScript.ORDER_EQUALITY]; +}; + +Blockly.JavaScript['math_change'] = function(block) { + // Add to a variable in place. + var argument0 = Blockly.JavaScript.valueToCode(block, 'DELTA', + Blockly.JavaScript.ORDER_ADDITION) || '0'; + var varName = Blockly.JavaScript.variableDB_.getName( + block.getTitleValue('VAR'), Blockly.Variables.NAME_TYPE); + return varName + ' = (typeof ' + varName + ' == \'number\' ? ' + varName + + ' : 0) + ' + argument0 + ';\n'; +}; + +// Rounding functions have a single operand. +Blockly.JavaScript['math_round'] = Blockly.JavaScript['math_single']; +// Trigonometry functions have a single operand. +Blockly.JavaScript['math_trig'] = Blockly.JavaScript['math_single']; + +Blockly.JavaScript['math_on_list'] = function(block) { + // Math functions for lists. + var func = block.getTitleValue('OP'); + var list, code; + switch (func) { + case 'SUM': + list = Blockly.JavaScript.valueToCode(block, 'LIST', + Blockly.JavaScript.ORDER_MEMBER) || '[]'; + code = list + '.reduce(function(x, y) {return x + y;})'; + break; + case 'MIN': + list = Blockly.JavaScript.valueToCode(block, 'LIST', + Blockly.JavaScript.ORDER_COMMA) || '[]'; + code = 'Math.min.apply(null, ' + list + ')'; + break; + case 'MAX': + list = Blockly.JavaScript.valueToCode(block, 'LIST', + Blockly.JavaScript.ORDER_COMMA) || '[]'; + code = 'Math.max.apply(null, ' + list + ')'; + break; + case 'AVERAGE': + // math_median([null,null,1,3]) == 2.0. + if (!Blockly.JavaScript.definitions_['math_mean']) { + var functionName = Blockly.JavaScript.variableDB_.getDistinctName( + 'math_mean', Blockly.Generator.NAME_TYPE); + Blockly.JavaScript.math_on_list.math_mean = functionName; + var func = []; + func.push('function ' + functionName + '(myList) {'); + func.push(' return myList.reduce(function(x, y) {return x + y;}) / ' + + 'myList.length;'); + func.push('}'); + Blockly.JavaScript.definitions_['math_mean'] = func.join('\n'); + } + list = Blockly.JavaScript.valueToCode(block, 'LIST', + Blockly.JavaScript.ORDER_NONE) || '[]'; + code = Blockly.JavaScript.math_on_list.math_mean + '(' + list + ')'; + break; + case 'MEDIAN': + // math_median([null,null,1,3]) == 2.0. + if (!Blockly.JavaScript.definitions_['math_median']) { + var functionName = Blockly.JavaScript.variableDB_.getDistinctName( + 'math_median', Blockly.Generator.NAME_TYPE); + Blockly.JavaScript.math_on_list.math_median = functionName; + var func = []; + func.push('function ' + functionName + '(myList) {'); + func.push(' var localList = myList.filter(function (x) ' + + '{return typeof x == \'number\';});'); + func.push(' if (!localList.length) return null;'); + func.push(' localList.sort(function(a, b) {return b - a;});'); + func.push(' if (localList.length % 2 == 0) {'); + func.push(' return (localList[localList.length / 2 - 1] + ' + + 'localList[localList.length / 2]) / 2;'); + func.push(' } else {'); + func.push(' return localList[(localList.length - 1) / 2];'); + func.push(' }'); + func.push('}'); + Blockly.JavaScript.definitions_['math_median'] = func.join('\n'); + } + list = Blockly.JavaScript.valueToCode(block, 'LIST', + Blockly.JavaScript.ORDER_NONE) || '[]'; + code = Blockly.JavaScript.math_on_list.math_median + '(' + list + ')'; + break; + case 'MODE': + if (!Blockly.JavaScript.definitions_['math_modes']) { + var functionName = Blockly.JavaScript.variableDB_.getDistinctName( + 'math_modes', Blockly.Generator.NAME_TYPE); + Blockly.JavaScript.math_on_list.math_modes = functionName; + // As a list of numbers can contain more than one mode, + // the returned result is provided as an array. + // Mode of [3, 'x', 'x', 1, 1, 2, '3'] -> ['x', 1]. + var func = []; + func.push('function ' + functionName + '(values) {'); + func.push(' var modes = [];'); + func.push(' var counts = [];'); + func.push(' var maxCount = 0;'); + func.push(' for (var i = 0; i < values.length; i++) {'); + func.push(' var value = values[i];'); + func.push(' var found = false;'); + func.push(' var thisCount;'); + func.push(' for (var j = 0; j < counts.length; j++) {'); + func.push(' if (counts[j][0] === value) {'); + func.push(' thisCount = ++counts[j][1];'); + func.push(' found = true;'); + func.push(' break;'); + func.push(' }'); + func.push(' }'); + func.push(' if (!found) {'); + func.push(' counts.push([value, 1]);'); + func.push(' thisCount = 1;'); + func.push(' }'); + func.push(' maxCount = Math.max(thisCount, maxCount);'); + func.push(' }'); + func.push(' for (var j = 0; j < counts.length; j++) {'); + func.push(' if (counts[j][1] == maxCount) {'); + func.push(' modes.push(counts[j][0]);'); + func.push(' }'); + func.push(' }'); + func.push(' return modes;'); + func.push('}'); + Blockly.JavaScript.definitions_['math_modes'] = func.join('\n'); + } + list = Blockly.JavaScript.valueToCode(block, 'LIST', + Blockly.JavaScript.ORDER_NONE) || '[]'; + code = Blockly.JavaScript.math_on_list.math_modes + '(' + list + ')'; + break; + case 'STD_DEV': + if (!Blockly.JavaScript.definitions_['math_standard_deviation']) { + var functionName = Blockly.JavaScript.variableDB_.getDistinctName( + 'math_standard_deviation', Blockly.Generator.NAME_TYPE); + Blockly.JavaScript.math_on_list.math_standard_deviation = functionName; + var func = []; + func.push('function ' + functionName + '(numbers) {'); + func.push(' var n = numbers.length;'); + func.push(' if (!n) return null;'); + func.push(' var mean = numbers.reduce(function(x, y) ' + + '{return x + y;}) / n;'); + func.push(' var variance = 0;'); + func.push(' for (var j = 0; j < n; j++) {'); + func.push(' variance += Math.pow(numbers[j] - mean, 2);'); + func.push(' }'); + func.push(' variance = variance / n;'); + func.push(' return Math.sqrt(variance);'); + func.push('}'); + Blockly.JavaScript.definitions_['math_standard_deviation'] = + func.join('\n'); + } + list = Blockly.JavaScript.valueToCode(block, 'LIST', + Blockly.JavaScript.ORDER_NONE) || '[]'; + code = Blockly.JavaScript.math_on_list.math_standard_deviation + + '(' + list + ')'; + break; + case 'RANDOM': + if (!Blockly.JavaScript.definitions_['math_random_item']) { + var functionName = Blockly.JavaScript.variableDB_.getDistinctName( + 'math_random_item', Blockly.Generator.NAME_TYPE); + Blockly.JavaScript.math_on_list.math_random_item = functionName; + var func = []; + func.push('function ' + functionName + '(list) {'); + func.push(' var x = Math.floor(Math.random() * list.length);'); + func.push(' return list[x];'); + func.push('}'); + Blockly.JavaScript.definitions_['math_random_item'] = func.join('\n'); + } + list = Blockly.JavaScript.valueToCode(block, 'LIST', + Blockly.JavaScript.ORDER_NONE) || '[]'; + code = Blockly.JavaScript.math_on_list.math_random_item + + '(' + list + ')'; + break; + default: + throw 'Unknown operator: ' + func; + } + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; +}; + +Blockly.JavaScript['math_modulo'] = function(block) { + // Remainder computation. + var argument0 = Blockly.JavaScript.valueToCode(block, 'DIVIDEND', + Blockly.JavaScript.ORDER_MODULUS) || '0'; + var argument1 = Blockly.JavaScript.valueToCode(block, 'DIVISOR', + Blockly.JavaScript.ORDER_MODULUS) || '0'; + var code = argument0 + ' % ' + argument1; + return [code, Blockly.JavaScript.ORDER_MODULUS]; +}; + +Blockly.JavaScript['math_constrain'] = function(block) { + // Constrain a number between two limits. + var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE', + Blockly.JavaScript.ORDER_COMMA) || '0'; + var argument1 = Blockly.JavaScript.valueToCode(block, 'LOW', + Blockly.JavaScript.ORDER_COMMA) || '0'; + var argument2 = Blockly.JavaScript.valueToCode(block, 'HIGH', + Blockly.JavaScript.ORDER_COMMA) || 'Infinity'; + var code = 'Math.min(Math.max(' + argument0 + ', ' + argument1 + '), ' + + argument2 + ')'; + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; +}; + +Blockly.JavaScript['math_random_int'] = function(block) { + // Random integer between [X] and [Y]. + var argument0 = Blockly.JavaScript.valueToCode(block, 'FROM', + Blockly.JavaScript.ORDER_COMMA) || '0'; + var argument1 = Blockly.JavaScript.valueToCode(block, 'TO', + Blockly.JavaScript.ORDER_COMMA) || '0'; + if (!Blockly.JavaScript.definitions_['math_random_int']) { + var functionName = Blockly.JavaScript.variableDB_.getDistinctName( + 'math_random_int', Blockly.Generator.NAME_TYPE); + Blockly.JavaScript.math_random_int.random_function = functionName; + var func = []; + func.push('function ' + functionName + '(a, b) {'); + func.push(' if (a > b) {'); + func.push(' // Swap a and b to ensure a is smaller.'); + func.push(' var c = a;'); + func.push(' a = b;'); + func.push(' b = c;'); + func.push(' }'); + func.push(' return Math.floor(Math.random() * (b - a + 1) + a);'); + func.push('}'); + Blockly.JavaScript.definitions_['math_random_int'] = func.join('\n'); + } + var code = Blockly.JavaScript.math_random_int.random_function + + '(' + argument0 + ', ' + argument1 + ')'; + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; +}; + +Blockly.JavaScript['math_random_float'] = function(block) { + // Random fraction between 0 and 1. + return ['Math.random()', Blockly.JavaScript.ORDER_FUNCTION_CALL]; +}; diff --git a/generators/javascript/procedures.js b/generators/javascript/procedures.js new file mode 100644 index 000000000..ded5a53b9 --- /dev/null +++ b/generators/javascript/procedures.js @@ -0,0 +1,102 @@ +/** + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Generating JavaScript for procedure blocks. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.JavaScript.procedures'); + +goog.require('Blockly.JavaScript'); + + +Blockly.JavaScript['procedures_defreturn'] = function(block) { + // Define a procedure with a return value. + var funcName = Blockly.JavaScript.variableDB_.getName( + block.getTitleValue('NAME'), Blockly.Procedures.NAME_TYPE); + var branch = Blockly.JavaScript.statementToCode(block, 'STACK'); + if (Blockly.JavaScript.INFINITE_LOOP_TRAP) { + branch = Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g, + '\'' + block.id + '\'') + branch; + } + var returnValue = Blockly.JavaScript.valueToCode(block, 'RETURN', + Blockly.JavaScript.ORDER_NONE) || ''; + if (returnValue) { + returnValue = ' return ' + returnValue + ';\n'; + } + var args = []; + for (var x = 0; x < block.arguments_.length; x++) { + args[x] = Blockly.JavaScript.variableDB_.getName(block.arguments_[x], + Blockly.Variables.NAME_TYPE); + } + var code = 'function ' + funcName + '(' + args.join(', ') + ') {\n' + + branch + returnValue + '}'; + code = Blockly.JavaScript.scrub_(block, code); + Blockly.JavaScript.definitions_[funcName] = code; + return null; +}; + +// Defining a procedure without a return value uses the same generator as +// a procedure with a return value. +Blockly.JavaScript['procedures_defnoreturn'] = + Blockly.JavaScript['procedures_defreturn']; + +Blockly.JavaScript['procedures_callreturn'] = function(block) { + // Call a procedure with a return value. + var funcName = Blockly.JavaScript.variableDB_.getName( + block.getTitleValue('NAME'), Blockly.Procedures.NAME_TYPE); + var args = []; + for (var x = 0; x < block.arguments_.length; x++) { + args[x] = Blockly.JavaScript.valueToCode(block, 'ARG' + x, + Blockly.JavaScript.ORDER_COMMA) || 'null'; + } + var code = funcName + '(' + args.join(', ') + ')'; + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; +}; + +Blockly.JavaScript['procedures_callnoreturn'] = function(block) { + // Call a procedure with no return value. + var funcName = Blockly.JavaScript.variableDB_.getName( + block.getTitleValue('NAME'), Blockly.Procedures.NAME_TYPE); + var args = []; + for (var x = 0; x < block.arguments_.length; x++) { + args[x] = Blockly.JavaScript.valueToCode(block, 'ARG' + x, + Blockly.JavaScript.ORDER_COMMA) || 'null'; + } + var code = funcName + '(' + args.join(', ') + ');\n'; + return code; +}; + +Blockly.JavaScript['procedures_ifreturn'] = function(block) { + // Conditionally return value from a procedure. + var condition = Blockly.JavaScript.valueToCode(block, 'CONDITION', + Blockly.JavaScript.ORDER_NONE) || 'false'; + var code = 'if (' + condition + ') {\n'; + if (block.hasReturnValue_) { + var value = Blockly.JavaScript.valueToCode(block, 'VALUE', + Blockly.JavaScript.ORDER_NONE) || 'null'; + code += ' return ' + value + ';\n'; + } else { + code += ' return;\n'; + } + code += '}\n'; + return code; +}; diff --git a/generators/javascript/text.js b/generators/javascript/text.js new file mode 100644 index 000000000..a609c1eed --- /dev/null +++ b/generators/javascript/text.js @@ -0,0 +1,260 @@ +/** + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Generating JavaScript for text blocks. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.JavaScript.text'); + +goog.require('Blockly.JavaScript'); + + +Blockly.JavaScript['text'] = function(block) { + // Text value. + var code = Blockly.JavaScript.quote_(block.getTitleValue('TEXT')); + return [code, Blockly.JavaScript.ORDER_ATOMIC]; +}; + +Blockly.JavaScript['text_join'] = function(block) { + // Create a string made up of any number of elements of any type. + var code; + if (block.itemCount_ == 0) { + return ['\'\'', Blockly.JavaScript.ORDER_ATOMIC]; + } else if (block.itemCount_ == 1) { + var argument0 = Blockly.JavaScript.valueToCode(block, 'ADD0', + Blockly.JavaScript.ORDER_NONE) || '\'\''; + code = 'String(' + argument0 + ')'; + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; + } else if (block.itemCount_ == 2) { + var argument0 = Blockly.JavaScript.valueToCode(block, 'ADD0', + Blockly.JavaScript.ORDER_NONE) || '\'\''; + var argument1 = Blockly.JavaScript.valueToCode(block, 'ADD1', + Blockly.JavaScript.ORDER_NONE) || '\'\''; + code = 'String(' + argument0 + ') + String(' + argument1 + ')'; + return [code, Blockly.JavaScript.ORDER_ADDITION]; + } else { + code = new Array(block.itemCount_); + for (var n = 0; n < block.itemCount_; n++) { + code[n] = Blockly.JavaScript.valueToCode(block, 'ADD' + n, + Blockly.JavaScript.ORDER_COMMA) || '\'\''; + } + code = '[' + code.join(',') + '].join(\'\')'; + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; + } +}; + +Blockly.JavaScript['text_append'] = function(block) { + // Append to a variable in place. + var varName = Blockly.JavaScript.variableDB_.getName( + block.getTitleValue('VAR'), Blockly.Variables.NAME_TYPE); + var argument0 = Blockly.JavaScript.valueToCode(block, 'TEXT', + Blockly.JavaScript.ORDER_NONE) || '\'\''; + return varName + ' = String(' + varName + ') + String(' + argument0 + ');\n'; +}; + +Blockly.JavaScript['text_length'] = function(block) { + // String length. + var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE', + Blockly.JavaScript.ORDER_FUNCTION_CALL) || '\'\''; + return [argument0 + '.length', Blockly.JavaScript.ORDER_MEMBER]; +}; + +Blockly.JavaScript['text_isEmpty'] = function(block) { + // Is the string null? + var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE', + Blockly.JavaScript.ORDER_MEMBER) || '\'\''; + return ['!' + argument0, Blockly.JavaScript.ORDER_LOGICAL_NOT]; +}; + +Blockly.JavaScript['text_indexOf'] = function(block) { + // Search the text for a substring. + var operator = block.getTitleValue('END') == 'FIRST' ? + 'indexOf' : 'lastIndexOf'; + var argument0 = Blockly.JavaScript.valueToCode(block, 'FIND', + Blockly.JavaScript.ORDER_NONE) || '\'\''; + var argument1 = Blockly.JavaScript.valueToCode(block, 'VALUE', + Blockly.JavaScript.ORDER_MEMBER) || '\'\''; + var code = argument1 + '.' + operator + '(' + argument0 + ') + 1'; + return [code, Blockly.JavaScript.ORDER_MEMBER]; +}; + +Blockly.JavaScript['text_charAt'] = function(block) { + // Get letter at index. + // Note: Until January 2013 this block did not have the WHERE input. + var where = block.getTitleValue('WHERE') || 'FROM_START'; + var at = Blockly.JavaScript.valueToCode(block, 'AT', + Blockly.JavaScript.ORDER_UNARY_NEGATION) || '1'; + var text = Blockly.JavaScript.valueToCode(block, 'VALUE', + Blockly.JavaScript.ORDER_MEMBER) || '\'\''; + switch (where) { + case 'FIRST': + var code = text + '.charAt(0)'; + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; + case 'LAST': + var code = text + '.slice(-1)'; + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; + case 'FROM_START': + // Blockly uses one-based indicies. + if (Blockly.isNumber(at)) { + // If the index is a naked number, decrement it right now. + at = parseFloat(at) - 1; + } else { + // If the index is dynamic, decrement it in code. + at += ' - 1'; + } + var code = text + '.charAt(' + at + ')'; + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; + case 'FROM_END': + var code = text + '.slice(-' + at + ').charAt(0)'; + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; + case 'RANDOM': + if (!Blockly.JavaScript.definitions_['text_random_letter']) { + var functionName = Blockly.JavaScript.variableDB_.getDistinctName( + 'text_random_letter', Blockly.Generator.NAME_TYPE); + Blockly.JavaScript.text_charAt.text_random_letter = functionName; + var func = []; + func.push('function ' + functionName + '(text) {'); + func.push(' var x = Math.floor(Math.random() * text.length);'); + func.push(' return text[x];'); + func.push('}'); + Blockly.JavaScript.definitions_['text_random_letter'] = func.join('\n'); + } + code = Blockly.JavaScript.text_charAt.text_random_letter + + '(' + text + ')'; + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; + } + throw 'Unhandled option (text_charAt).'; +}; + +Blockly.JavaScript['text_getSubstring'] = function(block) { + // Get substring. + var text = Blockly.JavaScript.valueToCode(block, 'STRING', + Blockly.JavaScript.ORDER_MEMBER) || '[]'; + var where1 = block.getTitleValue('WHERE1'); + var where2 = block.getTitleValue('WHERE2'); + var at1 = Blockly.JavaScript.valueToCode(block, 'AT1', + Blockly.JavaScript.ORDER_NONE) || '1'; + var at2 = Blockly.JavaScript.valueToCode(block, 'AT2', + Blockly.JavaScript.ORDER_NONE) || '1'; + if (where1 == 'FIRST' && where2 == 'LAST') { + var code = text; + } else { + if (!Blockly.JavaScript.definitions_['text_get_substring']) { + var functionName = Blockly.JavaScript.variableDB_.getDistinctName( + 'text_get_substring', Blockly.Generator.NAME_TYPE); + Blockly.JavaScript.text_getSubstring.func = functionName; + var func = []; + func.push('function ' + functionName + + '(text, where1, at1, where2, at2) {'); + func.push(' function getAt(where, at) {'); + func.push(' if (where == \'FROM_START\') {'); + func.push(' at--;'); + func.push(' } else if (where == \'FROM_END\') {'); + func.push(' at = text.length - at;'); + func.push(' } else if (where == \'FIRST\') {'); + func.push(' at = 0;'); + func.push(' } else if (where == \'LAST\') {'); + func.push(' at = text.length - 1;'); + func.push(' } else {'); + func.push(' throw \'Unhandled option (text_getSubstring).\';'); + func.push(' }'); + func.push(' return at;'); + func.push(' }'); + func.push(' at1 = getAt(where1, at1);'); + func.push(' at2 = getAt(where2, at2) + 1;'); + func.push(' return text.slice(at1, at2);'); + func.push('}'); + Blockly.JavaScript.definitions_['text_get_substring'] = + func.join('\n'); + } + var code = Blockly.JavaScript.text_getSubstring.func + '(' + text + ', \'' + + where1 + '\', ' + at1 + ', \'' + where2 + '\', ' + at2 + ')'; + } + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; +}; + +Blockly.JavaScript['text_changeCase'] = function(block) { + // Change capitalization. + var OPERATORS = { + UPPERCASE: '.toUpperCase()', + LOWERCASE: '.toLowerCase()', + TITLECASE: null + }; + var operator = OPERATORS[block.getTitleValue('CASE')]; + var code; + if (operator) { + // Upper and lower case are functions built into JavaScript. + var argument0 = Blockly.JavaScript.valueToCode(block, 'TEXT', + Blockly.JavaScript.ORDER_MEMBER) || '\'\''; + code = argument0 + operator; + } else { + if (!Blockly.JavaScript.definitions_['text_toTitleCase']) { + // Title case is not a native JavaScript function. Define one. + var functionName = Blockly.JavaScript.variableDB_.getDistinctName( + 'text_toTitleCase', Blockly.Generator.NAME_TYPE); + Blockly.JavaScript.text_changeCase.toTitleCase = functionName; + var func = []; + func.push('function ' + functionName + '(str) {'); + func.push(' return str.replace(/\\S+/g,'); + func.push(' function(txt) {return txt[0].toUpperCase() + ' + + 'txt.substring(1).toLowerCase();});'); + func.push('}'); + Blockly.JavaScript.definitions_['text_toTitleCase'] = func.join('\n'); + } + var argument0 = Blockly.JavaScript.valueToCode(block, 'TEXT', + Blockly.JavaScript.ORDER_NONE) || '\'\''; + code = Blockly.JavaScript.text_changeCase.toTitleCase + + '(' + argument0 + ')'; + } + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; +}; + +Blockly.JavaScript['text_trim'] = function(block) { + // Trim spaces. + var OPERATORS = { + LEFT: '.trimLeft()', + RIGHT: '.trimRight()', + BOTH: '.trim()' + }; + var operator = OPERATORS[block.getTitleValue('MODE')]; + var argument0 = Blockly.JavaScript.valueToCode(block, 'TEXT', + Blockly.JavaScript.ORDER_MEMBER) || '\'\''; + return [argument0 + operator, Blockly.JavaScript.ORDER_FUNCTION_CALL]; +}; + +Blockly.JavaScript['text_print'] = function(block) { + // Print statement. + var argument0 = Blockly.JavaScript.valueToCode(block, 'TEXT', + Blockly.JavaScript.ORDER_NONE) || '\'\''; + return 'window.alert(' + argument0 + ');\n'; +}; + +Blockly.JavaScript['text_prompt'] = function(block) { + // Prompt function. + var msg = Blockly.JavaScript.quote_(block.getTitleValue('TEXT')); + var code = 'window.prompt(' + msg + ')'; + var toNumber = block.getTitleValue('TYPE') == 'NUMBER'; + if (toNumber) { + code = 'parseFloat(' + code + ')'; + } + return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; +}; diff --git a/generators/javascript/variables.js b/generators/javascript/variables.js new file mode 100644 index 000000000..f5c707730 --- /dev/null +++ b/generators/javascript/variables.js @@ -0,0 +1,45 @@ +/** + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Generating JavaScript for variable blocks. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.JavaScript.variables'); + +goog.require('Blockly.JavaScript'); + + +Blockly.JavaScript['variables_get'] = function(block) { + // Variable getter. + var code = Blockly.JavaScript.variableDB_.getName(block.getTitleValue('VAR'), + Blockly.Variables.NAME_TYPE); + return [code, Blockly.JavaScript.ORDER_ATOMIC]; +}; + +Blockly.JavaScript['variables_set'] = function(block) { + // Variable setter. + var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE', + Blockly.JavaScript.ORDER_ASSIGNMENT) || '0'; + var varName = Blockly.JavaScript.variableDB_.getName( + block.getTitleValue('VAR'), Blockly.Variables.NAME_TYPE); + return varName + ' = ' + argument0 + ';\n'; +}; diff --git a/generators/python.js b/generators/python.js new file mode 100644 index 000000000..2a2bd283a --- /dev/null +++ b/generators/python.js @@ -0,0 +1,237 @@ +/** + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Helper functions for generating Python for blocks. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Python'); + +goog.require('Blockly.Generator'); + + +Blockly.Python = new Blockly.Generator('Python'); + +/** + * List of illegal variable names. + * This is not intended to be a security feature. Blockly is 100% client-side, + * so bypassing this list is trivial. This is intended to prevent users from + * accidentally clobbering a built-in object or function. + * @private + */ +Blockly.Python.addReservedWords( + // import keyword + // print ','.join(keyword.kwlist) + // http://docs.python.org/reference/lexical_analysis.html#keywords + 'and,as,assert,break,class,continue,def,del,elif,else,except,exec,finally,for,from,global,if,import,in,is,lambda,not,or,pass,print,raise,return,try,while,with,yield,' + + //http://docs.python.org/library/constants.html + 'True,False,None,NotImplemented,Ellipsis,__debug__,quit,exit,copyright,license,credits,' + + // http://docs.python.org/library/functions.html + 'abs,divmod,input,open,staticmethod,all,enumerate,int,ord,str,any,eval,isinstance,pow,sum,basestring,execfile,issubclass,print,super,bin,file,iter,property,tuple,bool,filter,len,range,type,bytearray,float,list,raw_input,unichr,callable,format,locals,reduce,unicode,chr,frozenset,long,reload,vars,classmethod,getattr,map,repr,xrange,cmp,globals,max,reversed,zip,compile,hasattr,memoryview,round,__import__,complex,hash,min,set,apply,delattr,help,next,setattr,buffer,dict,hex,object,slice,coerce,dir,id,oct,sorted,intern'); + +/** + * Order of operation ENUMs. + * http://docs.python.org/reference/expressions.html#summary + */ +Blockly.Python.ORDER_ATOMIC = 0; // 0 "" ... +Blockly.Python.ORDER_COLLECTION = 1; // tuples, lists, dictionaries +Blockly.Python.ORDER_STRING_CONVERSION = 1; // `expression...` +Blockly.Python.ORDER_MEMBER = 2; // . [] +Blockly.Python.ORDER_FUNCTION_CALL = 2; // () +Blockly.Python.ORDER_EXPONENTIATION = 3; // ** +Blockly.Python.ORDER_UNARY_SIGN = 4; // + - +Blockly.Python.ORDER_BITWISE_NOT = 4; // ~ +Blockly.Python.ORDER_MULTIPLICATIVE = 5; // * / // % +Blockly.Python.ORDER_ADDITIVE = 6; // + - +Blockly.Python.ORDER_BITWISE_SHIFT = 7; // << >> +Blockly.Python.ORDER_BITWISE_AND = 8; // & +Blockly.Python.ORDER_BITWISE_XOR = 9; // ^ +Blockly.Python.ORDER_BITWISE_OR = 10; // | +Blockly.Python.ORDER_RELATIONAL = 11; // in, not in, is, is not, + // <, <=, >, >=, <>, !=, == +Blockly.Python.ORDER_LOGICAL_NOT = 12; // not +Blockly.Python.ORDER_LOGICAL_AND = 13; // and +Blockly.Python.ORDER_LOGICAL_OR = 14; // or +Blockly.Python.ORDER_CONDITIONAL = 15; // if else +Blockly.Python.ORDER_LAMBDA = 16; // lambda +Blockly.Python.ORDER_NONE = 99; // (...) + +/** + * Arbitrary code to inject into locations that risk causing infinite loops. + * Any instances of '%1' will be replaced by the block ID that failed. + * E.g. ' checkTimeout(%1)\n' + * @type ?string + */ +Blockly.Python.INFINITE_LOOP_TRAP = null; + +/** + * This is used as a placeholder in functions defined using + * Blockly.Python.provideFunction_. It must not be legal code that could + * legitimately appear in a function definition (or comment), and it must + * not confuse the regular expression parser. + */ +Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ = '{{{}}}'; +Blockly.Python.FUNCTION_NAME_PLACEHOLDER_REGEXP_ = + new RegExp(Blockly.Python.FUNCTION_NAME_PLACEHOLDER_, 'g'); + +/** + * Initialise the database of variable names. + */ +Blockly.Python.init = function() { + // Create a dictionary of definitions to be printed before the code. + Blockly.Python.definitions_ = Object.create(null); + // Create a dictionary mapping desired function names in definitions_ + // to actual function names (to avoid collisions with user functions). + Blockly.Python.functionNames_ = Object.create(null); + + if (Blockly.Variables) { + if (!Blockly.Python.variableDB_) { + Blockly.Python.variableDB_ = + new Blockly.Names(Blockly.Python.RESERVED_WORDS_); + } else { + Blockly.Python.variableDB_.reset(); + } + + var defvars = []; + var variables = Blockly.Variables.allVariables(); + for (var x = 0; x < variables.length; x++) { + defvars[x] = Blockly.Python.variableDB_.getName(variables[x], + Blockly.Variables.NAME_TYPE) + ' = None'; + } + Blockly.Python.definitions_['variables'] = defvars.join('\n'); + } +}; + +/** + * Prepend the generated code with the variable definitions. + * @param {string} code Generated code. + * @return {string} Completed code. + */ +Blockly.Python.finish = function(code) { + // Convert the definitions dictionary into a list. + var imports = []; + var definitions = []; + for (var name in Blockly.Python.definitions_) { + var def = Blockly.Python.definitions_[name]; + if (def.match(/^(from\s+\S+\s+)?import\s+\S+/)) { + imports.push(def); + } else { + definitions.push(def); + } + } + var allDefs = imports.join('\n') + '\n\n' + definitions.join('\n\n'); + return allDefs.replace(/\n\n+/g, '\n\n').replace(/\n*$/, '\n\n\n') + code; +}; + +/** + * Naked values are top-level blocks with outputs that aren't plugged into + * anything. + * @param {string} line Line of generated code. + * @return {string} Legal line of code. + */ +Blockly.Python.scrubNakedValue = function(line) { + return line + '\n'; +}; + +/** + * Encode a string as a properly escaped Python string, complete with quotes. + * @param {string} string Text to encode. + * @return {string} Python string. + * @private + */ +Blockly.Python.quote_ = function(string) { + // TODO: This is a quick hack. Replace with goog.string.quote + string = string.replace(/\\/g, '\\\\') + .replace(/\n/g, '\\\n') + .replace(/\%/g, '\\%') + .replace(/'/g, '\\\''); + return '\'' + string + '\''; +}; + +/** + * Common tasks for generating Python from blocks. + * Handles comments for the specified block and any connected value blocks. + * Calls any statements following this block. + * @param {!Blockly.Block} block The current block. + * @param {string} code The Python code created for this block. + * @return {string} Python code with comments and subsequent blocks added. + * @this {Blockly.CodeGenerator} + * @private + */ +Blockly.Python.scrub_ = function(block, code) { + if (code === null) { + // Block has handled code generation itself. + return ''; + } + var commentCode = ''; + // Only collect comments for blocks that aren't inline. + if (!block.outputConnection || !block.outputConnection.targetConnection) { + // Collect comment for this block. + var comment = block.getCommentText(); + if (comment) { + commentCode += this.prefixLines(comment, '# ') + '\n'; + } + // Collect comments for all value arguments. + // Don't collect comments for nested statements. + for (var x = 0; x < block.inputList.length; x++) { + if (block.inputList[x].type == Blockly.INPUT_VALUE) { + var childBlock = block.inputList[x].connection.targetBlock(); + if (childBlock) { + var comment = this.allNestedComments(childBlock); + if (comment) { + commentCode += this.prefixLines(comment, '# '); + } + } + } + } + } + var nextBlock = block.nextConnection && block.nextConnection.targetBlock(); + var nextCode = this.blockToCode(nextBlock); + return commentCode + code + nextCode; +}; + +/** + * Define a function to be included in the generated code. + * The first time this is called with a given desiredName, the code is + * saved and an actual name is generated. Subsequent calls with the + * same desiredName have no effect but have the same return value. + * + * It is up to the caller to make sure the same desiredName is not + * used for different code values. + * + * The code gets output when Blockly.Python.finish() is called. + * + * @param {string} desiredName The desired name of the function (e.g., isPrime). + * @param {code} A list of Python statements. + * @return {string} The actual name of the new function. This may differ + * from desiredName if the former has already been taken by the user. + * @private + */ +Blockly.Python.provideFunction_ = function(desiredName, code) { + if (!Blockly.Python.definitions_[desiredName]) { + var functionName = Blockly.Python.variableDB_.getDistinctName( + desiredName, Blockly.Generator.NAME_TYPE); + Blockly.Python.functionNames_[desiredName] = functionName; + Blockly.Python.definitions_[desiredName] = code.join('\n').replace( + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_REGEXP_, functionName); + } + return Blockly.Python.functionNames_[desiredName]; +}; diff --git a/generators/python/colour.js b/generators/python/colour.js new file mode 100644 index 000000000..d1c02fa06 --- /dev/null +++ b/generators/python/colour.js @@ -0,0 +1,85 @@ +/** + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Generating Python for colour blocks. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Python.colour'); + +goog.require('Blockly.Python'); + + +Blockly.Python['colour_picker'] = function(block) { + // Colour picker. + var code = '\'' + block.getTitleValue('COLOUR') + '\''; + return [code, Blockly.Python.ORDER_ATOMIC]; +}; + +Blockly.Python['colour_random'] = function(block) { + // Generate a random colour. + Blockly.Python.definitions_['import_random'] = 'import random'; + var code = '\'#%06x\' % random.randint(0, 2**24 - 1)'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; +}; + +Blockly.Python['colour_rgb'] = function(block) { + // Compose a colour from RGB components. + var functionName = Blockly.Python.provideFunction_( + 'colour_rgb', + [ 'def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(r, g, b):', + ' r = round(min(100, max(0, r)) * 2.55)', + ' g = round(min(100, max(0, g)) * 2.55)', + ' b = round(min(100, max(0, b)) * 2.55)', + ' return \'#%02x%02x%02x\' % (r, g, b)']); + var r = Blockly.Python.valueToCode(block, 'RED', + Blockly.Python.ORDER_NONE) || 0; + var g = Blockly.Python.valueToCode(block, 'GREEN', + Blockly.Python.ORDER_NONE) || 0; + var b = Blockly.Python.valueToCode(block, 'BLUE', + Blockly.Python.ORDER_NONE) || 0; + var code = functionName + '(' + r + ', ' + g + ', ' + b + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; +}; + +Blockly.Python['colour_blend'] = function(block) { + // Blend two colours together. + var functionName = Blockly.Python.provideFunction_( + 'colour_blend', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + + '(colour1, colour2, ratio):', + ' r1, r2 = int(colour1[1:3], 16), int(colour2[1:3], 16)', + ' g1, g2 = int(colour1[3:5], 16), int(colour2[3:5], 16)', + ' b1, b2 = int(colour1[5:7], 16), int(colour2[5:7], 16)', + ' ratio = min(1, max(0, ratio))', + ' r = round(r1 * (1 - ratio) + r2 * ratio)', + ' g = round(g1 * (1 - ratio) + g2 * ratio)', + ' b = round(b1 * (1 - ratio) + b2 * ratio)', + ' return \'#%02x%02x%02x\' % (r, g, b)']); + var colour1 = Blockly.Python.valueToCode(block, 'COLOUR1', + Blockly.Python.ORDER_NONE) || '\'#000000\''; + var colour2 = Blockly.Python.valueToCode(block, 'COLOUR2', + Blockly.Python.ORDER_NONE) || '\'#000000\''; + var ratio = Blockly.Python.valueToCode(block, 'RATIO', + Blockly.Python.ORDER_NONE) || 0; + var code = functionName + '(' + colour1 + ', ' + colour2 + ', ' + ratio + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; +}; diff --git a/generators/python/lists.js b/generators/python/lists.js new file mode 100644 index 000000000..1897f992d --- /dev/null +++ b/generators/python/lists.js @@ -0,0 +1,312 @@ +/** + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Generating Python for list blocks. + * @author q.neutron@gmail.com (Quynh Neutron) + */ +'use strict'; + +goog.provide('Blockly.Python.lists'); + +goog.require('Blockly.Python'); + + +Blockly.Python['lists_create_empty'] = function(block) { + // Create an empty list. + return ['[]', Blockly.Python.ORDER_ATOMIC]; +}; + +Blockly.Python['lists_create_with'] = function(block) { + // Create a list with any number of elements of any type. + var code = new Array(block.itemCount_); + for (var n = 0; n < block.itemCount_; n++) { + code[n] = Blockly.Python.valueToCode(block, 'ADD' + n, + Blockly.Python.ORDER_NONE) || 'None'; + } + code = '[' + code.join(', ') + ']'; + return [code, Blockly.Python.ORDER_ATOMIC]; +}; + +Blockly.Python['lists_repeat'] = function(block) { + // Create a list with one element repeated. + var argument0 = Blockly.Python.valueToCode(block, 'ITEM', + Blockly.Python.ORDER_NONE) || 'None'; + var argument1 = Blockly.Python.valueToCode(block, 'NUM', + Blockly.Python.ORDER_MULTIPLICATIVE) || '0'; + var code = '[' + argument0 + '] * ' + argument1; + return [code, Blockly.Python.ORDER_MULTIPLICATIVE]; +}; + +Blockly.Python['lists_length'] = function(block) { + // List length. + var argument0 = Blockly.Python.valueToCode(block, 'VALUE', + Blockly.Python.ORDER_NONE) || '[]'; + return ['len(' + argument0 + ')', Blockly.Python.ORDER_FUNCTION_CALL]; +}; + +Blockly.Python['lists_isEmpty'] = function(block) { + // Is the list empty? + var argument0 = Blockly.Python.valueToCode(block, 'VALUE', + Blockly.Python.ORDER_NONE) || '[]'; + var code = 'not len(' + argument0 + ')'; + return [code, Blockly.Python.ORDER_LOGICAL_NOT]; +}; + +Blockly.Python['lists_indexOf'] = function(block) { + // Find an item in the list. + var argument0 = Blockly.Python.valueToCode(block, 'FIND', + Blockly.Python.ORDER_NONE) || '[]'; + var argument1 = Blockly.Python.valueToCode(block, 'VALUE', + Blockly.Python.ORDER_MEMBER) || '\'\''; + var code; + if (block.getTitleValue('END') == 'FIRST') { + var functionName = Blockly.Python.provideFunction_( + 'first_index', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(myList, elem):', + ' try: theIndex = myList.index(elem) + 1', + ' except: theIndex = 0', + ' return theIndex']); + code = functionName + '(' + argument1 + ', ' + argument0 + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } else { + var functionName = Blockly.Python.provideFunction_( + 'last_index', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(myList, elem):', + ' try: theIndex = len(myList) - myList[::-1].index(elem)', + ' except: theIndex = 0', + ' return theIndex']); + code = functionName + '(' + argument1 + ', ' + argument0 + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } +}; + +Blockly.Python['lists_getIndex'] = function(block) { + // Get element at index. + // Note: Until January 2013 this block did not have MODE or WHERE inputs. + var mode = block.getTitleValue('MODE') || 'GET'; + var where = block.getTitleValue('WHERE') || 'FROM_START'; + var at = Blockly.Python.valueToCode(block, 'AT', + Blockly.Python.ORDER_UNARY_SIGN) || '1'; + var list = Blockly.Python.valueToCode(block, 'VALUE', + Blockly.Python.ORDER_MEMBER) || '[]'; + + if (where == 'FIRST') { + if (mode == 'GET') { + var code = list + '[0]'; + return [code, Blockly.Python.ORDER_MEMBER]; + } else { + var code = list + '.pop(0)'; + if (mode == 'GET_REMOVE') { + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } else if (mode == 'REMOVE') { + return code + '\n'; + } + } + } else if (where == 'LAST') { + if (mode == 'GET') { + var code = list + '[-1]'; + return [code, Blockly.Python.ORDER_MEMBER]; + } else { + var code = list + '.pop()'; + if (mode == 'GET_REMOVE') { + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } else if (mode == 'REMOVE') { + return code + '\n'; + } + } + } else if (where == 'FROM_START') { + // Blockly uses one-based indicies. + if (Blockly.isNumber(at)) { + // If the index is a naked number, decrement it right now. + at = parseInt(at, 10) - 1; + } else { + // If the index is dynamic, decrement it in code. + at = 'int(' + at + ' - 1)'; + } + if (mode == 'GET') { + var code = list + '[' + at + ']'; + return [code, Blockly.Python.ORDER_MEMBER]; + } else { + var code = list + '.pop(' + at + ')'; + if (mode == 'GET_REMOVE') { + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } else if (mode == 'REMOVE') { + return code + '\n'; + } + } + } else if (where == 'FROM_END') { + if (mode == 'GET') { + var code = list + '[-' + at + ']'; + return [code, Blockly.Python.ORDER_MEMBER]; + } else { + var code = list + '.pop(-' + at + ')'; + if (mode == 'GET_REMOVE') { + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } else if (mode == 'REMOVE') { + return code + '\n'; + } + } + } else if (where == 'RANDOM') { + Blockly.Python.definitions_['import_random'] = 'import random'; + if (mode == 'GET') { + code = 'random.choice(' + list + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } else { + var functionName = Blockly.Python.provideFunction_( + 'lists_remove_random_item', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(myList):', + ' x = int(random.random() * len(myList))', + ' return myList.pop(x)']); + code = functionName + '(' + list + ')'; + if (mode == 'GET_REMOVE') { + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } else if (mode == 'REMOVE') { + return code + '\n'; + } + } + } + throw 'Unhandled combination (lists_getIndex).'; +}; + +Blockly.Python['lists_setIndex'] = function(block) { + // Set element at index. + // Note: Until February 2013 this block did not have MODE or WHERE inputs. + var list = Blockly.Python.valueToCode(block, 'LIST', + Blockly.Python.ORDER_MEMBER) || '[]'; + var mode = block.getTitleValue('MODE') || 'GET'; + var where = block.getTitleValue('WHERE') || 'FROM_START'; + var at = Blockly.Python.valueToCode(block, 'AT', + Blockly.Python.ORDER_NONE) || '1'; + var value = Blockly.Python.valueToCode(block, 'TO', + Blockly.Python.ORDER_NONE) || 'None'; + // Cache non-trivial values to variables to prevent repeated look-ups. + // Closure, which accesses and modifies 'list'. + function cacheList() { + if (list.match(/^\w+$/)) { + return ''; + } + var listVar = Blockly.Python.variableDB_.getDistinctName( + 'tmp_list', Blockly.Variables.NAME_TYPE); + var code = listVar + ' = ' + list + '\n'; + list = listVar; + return code; + } + if (where == 'FIRST') { + if (mode == 'SET') { + return list + '[0] = ' + value + '\n'; + } else if (mode == 'INSERT') { + return list + '.insert(0, ' + value + ')\n'; + } + } else if (where == 'LAST') { + if (mode == 'SET') { + return list + '[-1] = ' + value + '\n'; + } else if (mode == 'INSERT') { + return list + '.append(' + value + ')\n'; + } + } else if (where == 'FROM_START') { + // Blockly uses one-based indicies. + if (Blockly.isNumber(at)) { + // If the index is a naked number, decrement it right now. + at = parseInt(at, 10) - 1; + } else { + // If the index is dynamic, decrement it in code. + at = 'int(' + at + ' - 1)'; + } + if (mode == 'SET') { + return list + '[' + at + '] = ' + value + '\n'; + } else if (mode == 'INSERT') { + return list + '.insert(' + at + ', ' + value + ')\n'; + } + } else if (where == 'FROM_END') { + if (mode == 'SET') { + return list + '[-' + at + '] = ' + value + '\n'; + } else if (mode == 'INSERT') { + return list + '.insert(-' + at + ', ' + value + ')\n'; + } + } else if (where == 'RANDOM') { + Blockly.Python.definitions_['import_random'] = 'import random'; + var code = cacheList(); + var xVar = Blockly.Python.variableDB_.getDistinctName( + 'tmp_x', Blockly.Variables.NAME_TYPE); + code += xVar + ' = int(random.random() * len(' + list + '))\n'; + if (mode == 'SET') { + code += list + '[' + xVar + '] = ' + value + '\n'; + return code; + } else if (mode == 'INSERT') { + code += list + '.insert(' + xVar + ', ' + value + ')\n'; + return code; + } + } + throw 'Unhandled combination (lists_setIndex).'; +}; + +Blockly.Python['lists_getSublist'] = function(block) { + // Get sublist. + var list = Blockly.Python.valueToCode(block, 'LIST', + Blockly.Python.ORDER_MEMBER) || '[]'; + var where1 = block.getTitleValue('WHERE1'); + var where2 = block.getTitleValue('WHERE2'); + var at1 = Blockly.Python.valueToCode(block, 'AT1', + Blockly.Python.ORDER_ADDITIVE) || '1'; + var at2 = Blockly.Python.valueToCode(block, 'AT2', + Blockly.Python.ORDER_ADDITIVE) || '1'; + if (where1 == 'FIRST' || (where1 == 'FROM_START' && at1 == '1')) { + at1 = ''; + } else if (where1 == 'FROM_START') { + // Blockly uses one-based indicies. + if (Blockly.isNumber(at1)) { + // If the index is a naked number, decrement it right now. + at1 = parseInt(at1, 10) - 1; + } else { + // If the index is dynamic, decrement it in code. + at1 = 'int(' + at1 + ' - 1)'; + } + } else if (where1 == 'FROM_END') { + if (Blockly.isNumber(at1)) { + at1 = -parseInt(at1, 10); + } else { + at1 = '-int(' + at1 + ')'; + } + } + if (where2 == 'LAST' || (where2 == 'FROM_END' && at2 == '1')) { + at2 = ''; + } else if (where1 == 'FROM_START') { + if (Blockly.isNumber(at2)) { + at2 = parseInt(at2, 10); + } else { + at2 = 'int(' + at2 + ')'; + } + } else if (where1 == 'FROM_END') { + if (Blockly.isNumber(at2)) { + // If the index is a naked number, increment it right now. + // Add special case for -0. + at2 = 1 - parseInt(at2, 10); + if (at2 == 0) { + at2 = ''; + } + } else { + // If the index is dynamic, increment it in code. + Blockly.Python.definitions_['import_sys'] = 'import sys'; + at2 = 'int(1 - ' + at2 + ') or sys.maxsize'; + } + } + var code = list + '[' + at1 + ' : ' + at2 + ']'; + return [code, Blockly.Python.ORDER_MEMBER]; +}; diff --git a/generators/python/logic.js b/generators/python/logic.js new file mode 100644 index 000000000..e3590fc64 --- /dev/null +++ b/generators/python/logic.js @@ -0,0 +1,123 @@ +/** + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Generating Python for logic blocks. + * @author q.neutron@gmail.com (Quynh Neutron) + */ +'use strict'; + +goog.provide('Blockly.Python.logic'); + +goog.require('Blockly.Python'); + + +Blockly.Python['controls_if'] = function(block) { + // If/elseif/else condition. + var n = 0; + var argument = Blockly.Python.valueToCode(block, 'IF' + n, + Blockly.Python.ORDER_NONE) || 'False'; + var branch = Blockly.Python.statementToCode(block, 'DO' + n) || ' pass\n'; + var code = 'if ' + argument + ':\n' + branch; + for (n = 1; n <= block.elseifCount_; n++) { + argument = Blockly.Python.valueToCode(block, 'IF' + n, + Blockly.Python.ORDER_NONE) || 'False'; + branch = Blockly.Python.statementToCode(block, 'DO' + n) || ' pass\n'; + code += 'elif ' + argument + ':\n' + branch; + } + if (block.elseCount_) { + branch = Blockly.Python.statementToCode(block, 'ELSE') || ' pass\n'; + code += 'else:\n' + branch; + } + return code; +}; + +Blockly.Python['logic_compare'] = function(block) { + // Comparison operator. + var OPERATORS = { + EQ: '==', + NEQ: '!=', + LT: '<', + LTE: '<=', + GT: '>', + GTE: '>=' + }; + var operator = OPERATORS[block.getTitleValue('OP')]; + var order = Blockly.Python.ORDER_RELATIONAL; + var argument0 = Blockly.Python.valueToCode(block, 'A', order) || '0'; + var argument1 = Blockly.Python.valueToCode(block, 'B', order) || '0'; + var code = argument0 + ' ' + operator + ' ' + argument1; + return [code, order]; +}; + +Blockly.Python['logic_operation'] = function(block) { + // Operations 'and', 'or'. + var operator = (block.getTitleValue('OP') == 'AND') ? 'and' : 'or'; + var order = (operator == 'and') ? Blockly.Python.ORDER_LOGICAL_AND : + Blockly.Python.ORDER_LOGICAL_OR; + var argument0 = Blockly.Python.valueToCode(block, 'A', order); + var argument1 = Blockly.Python.valueToCode(block, 'B', order); + if (!argument0 && !argument1) { + // If there are no arguments, then the return value is false. + argument0 = 'False'; + argument1 = 'False'; + } else { + // Single missing arguments have no effect on the return value. + var defaultArgument = (operator == 'and') ? 'True' : 'False'; + if (!argument0) { + argument0 = defaultArgument; + } + if (!argument1) { + argument1 = defaultArgument; + } + } + var code = argument0 + ' ' + operator + ' ' + argument1; + return [code, order]; +}; + +Blockly.Python['logic_negate'] = function(block) { + // Negation. + var argument0 = Blockly.Python.valueToCode(block, 'BOOL', + Blockly.Python.ORDER_LOGICAL_NOT) || 'True'; + var code = 'not ' + argument0; + return [code, Blockly.Python.ORDER_LOGICAL_NOT]; +}; + +Blockly.Python['logic_boolean'] = function(block) { + // Boolean values true and false. + var code = (block.getTitleValue('BOOL') == 'TRUE') ? 'True' : 'False'; + return [code, Blockly.Python.ORDER_ATOMIC]; +}; + +Blockly.Python['logic_null'] = function(block) { + // Null data type. + return ['None', Blockly.Python.ORDER_ATOMIC]; +}; + +Blockly.Python['logic_ternary'] = function(block) { + // Ternary operator. + var value_if = Blockly.Python.valueToCode(block, 'IF', + Blockly.Python.ORDER_CONDITIONAL) || 'False'; + var value_then = Blockly.Python.valueToCode(block, 'THEN', + Blockly.Python.ORDER_CONDITIONAL) || 'None'; + var value_else = Blockly.Python.valueToCode(block, 'ELSE', + Blockly.Python.ORDER_CONDITIONAL) || 'None'; + var code = value_then + ' if ' + value_if + ' else ' + value_else + return [code, Blockly.Python.ORDER_CONDITIONAL]; +}; diff --git a/generators/python/loops.js b/generators/python/loops.js new file mode 100644 index 000000000..55e427cdd --- /dev/null +++ b/generators/python/loops.js @@ -0,0 +1,227 @@ +/** + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Generating Python for loop blocks. + * @author q.neutron@gmail.com (Quynh Neutron) + */ +'use strict'; + +goog.provide('Blockly.Python.loops'); + +goog.require('Blockly.Python'); + + +Blockly.Python['controls_repeat'] = function(block) { + // Repeat n times (internal number). + var repeats = parseInt(block.getTitleValue('TIMES'), 10); + var branch = Blockly.Python.statementToCode(block, 'DO') || ' pass\n'; + if (Blockly.Python.INFINITE_LOOP_TRAP) { + branch = Blockly.Python.INFINITE_LOOP_TRAP.replace(/%1/g, + '\'' + block.id + '\'') + branch; + } + var loopVar = Blockly.Python.variableDB_.getDistinctName( + 'count', Blockly.Variables.NAME_TYPE); + var code = 'for ' + loopVar + ' in range(' + repeats + '):\n' + branch; + return code; +}; + +Blockly.Python['controls_repeat_ext'] = function(block) { + // Repeat n times (external number). + var repeats = Blockly.Python.valueToCode(block, 'TIMES', + Blockly.Python.ORDER_NONE) || '0'; + if (Blockly.isNumber(repeats)) { + repeats = parseInt(repeats, 10); + } else { + repeats = 'int(' + repeats + ')'; + } + var branch = Blockly.Python.statementToCode(block, 'DO') || ' pass\n'; + if (Blockly.Python.INFINITE_LOOP_TRAP) { + branch = Blockly.Python.INFINITE_LOOP_TRAP.replace(/%1/g, + '\'' + block.id + '\'') + branch; + } + var loopVar = Blockly.Python.variableDB_.getDistinctName( + 'count', Blockly.Variables.NAME_TYPE); + var code = 'for ' + loopVar + ' in range(' + repeats + '):\n' + branch; + return code; +}; + +Blockly.Python['controls_whileUntil'] = function(block) { + // Do while/until loop. + var until = block.getTitleValue('MODE') == 'UNTIL'; + var argument0 = Blockly.Python.valueToCode(block, 'BOOL', + until ? Blockly.Python.ORDER_LOGICAL_NOT : + Blockly.Python.ORDER_NONE) || 'False'; + var branch = Blockly.Python.statementToCode(block, 'DO') || ' pass\n'; + if (Blockly.Python.INFINITE_LOOP_TRAP) { + branch = Blockly.Python.INFINITE_LOOP_TRAP.replace(/%1/g, + '"' + block.id + '"') + branch; + } + if (block.getTitleValue('MODE') == 'UNTIL') { + if (!argument0.match(/^\w+$/)) { + argument0 = '(' + argument0 + ')'; + } + argument0 = 'not ' + argument0; + } + return 'while ' + argument0 + ':\n' + branch; +}; + +Blockly.Python['controls_for'] = function(block) { + // For loop. + var variable0 = Blockly.Python.variableDB_.getName( + block.getTitleValue('VAR'), Blockly.Variables.NAME_TYPE); + var argument0 = Blockly.Python.valueToCode(block, 'FROM', + Blockly.Python.ORDER_NONE) || '0'; + var argument1 = Blockly.Python.valueToCode(block, 'TO', + Blockly.Python.ORDER_NONE) || '0'; + var increment = Blockly.Python.valueToCode(block, 'BY', + Blockly.Python.ORDER_NONE) || '1'; + var branch = Blockly.Python.statementToCode(block, 'DO') || ' pass\n'; + if (Blockly.Python.INFINITE_LOOP_TRAP) { + branch = Blockly.Python.INFINITE_LOOP_TRAP.replace(/%1/g, + '"' + block.id + '"') + branch; + } + + var code = ''; + var range; + + // Helper functions. + var defineUpRange = function() { + return Blockly.Python.provideFunction_( + 'upRange', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + + '(start, stop, step):', + ' while start <= stop:', + ' yield start', + ' start += abs(step)']); + }; + var defineDownRange = function() { + return Blockly.Python.provideFunction_( + 'downRange', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + + '(start, stop, step):', + ' while start >= stop:', + ' yield start', + ' start -= abs(step)']); + }; + // Arguments are legal Python code (numbers or strings returned by scrub()). + var generateUpDownRange = function(start, end, inc) { + return '(' + start + ' <= ' + end + ') and ' + + defineUpRange() + '(' + start + ', ' + end + ', ' + inc + ') or ' + + defineDownRange() + '(' + start + ', ' + end + ', ' + inc + ')'; + }; + + if (Blockly.isNumber(argument0) && Blockly.isNumber(argument1) && + Blockly.isNumber(increment)) { + // All parameters are simple numbers. + argument0 = parseFloat(argument0); + argument1 = parseFloat(argument1); + increment = Math.abs(parseFloat(increment)); + if (argument0 % 1 === 0 && argument1 % 1 === 0 && increment % 1 === 0) { + // All parameters are integers. + if (argument0 <= argument1) { + // Count up. + argument1++; + if (argument0 == 0 && increment == 1) { + // If starting index is 0, omit it. + range = argument1; + } else { + range = argument0 + ', ' + argument1; + } + // If increment isn't 1, it must be explicit. + if (increment != 1) { + range += ', ' + increment; + } + } else { + // Count down. + argument1--; + range = argument0 + ', ' + argument1 + ', -' + increment; + } + range = 'range(' + range + ')'; + } else { + // At least one of the parameters is not an integer. + if (argument0 < argument1) { + range = defineUpRange(); + } else { + range = defineDownRange(); + } + range += '(' + argument0 + ', ' + argument1 + ', ' + increment + ')'; + } + } else { + // Cache non-trivial values to variables to prevent repeated look-ups. + var scrub = function(arg, suffix) { + if (Blockly.isNumber(arg)) { + // Simple number. + arg = parseFloat(arg); + } else if (arg.match(/^\w+$/)) { + // Variable. + arg = 'float(' + arg + ')'; + } else { + // It's complicated. + var varName = Blockly.Python.variableDB_.getDistinctName( + variable0 + suffix, Blockly.Variables.NAME_TYPE); + code += varName + ' = float(' + arg + ')\n'; + arg = varName; + } + return arg; + }; + var startVar = scrub(argument0, '_start'); + var endVar = scrub(argument1, '_end'); + var incVar = scrub(increment, '_inc'); + + if (typeof startVar == 'number' && typeof endVar == 'number') { + if (startVar < endVar) { + range = defineUpRange(startVar, endVar, increment); + } else { + range = defineDownRange(startVar, endVar, increment); + } + } else { + // We cannot determine direction statically. + range = generateUpDownRange(startVar, endVar, increment); + } + } + code += 'for ' + variable0 + ' in ' + range + ':\n' + branch; + return code; +}; + +Blockly.Python['controls_forEach'] = function(block) { + // For each loop. + var variable0 = Blockly.Python.variableDB_.getName( + block.getTitleValue('VAR'), Blockly.Variables.NAME_TYPE); + var argument0 = Blockly.Python.valueToCode(block, 'LIST', + Blockly.Python.ORDER_RELATIONAL) || '[]'; + var branch = Blockly.Python.statementToCode(block, 'DO') || ' pass\n'; + if (Blockly.Python.INFINITE_LOOP_TRAP) { + branch = Blockly.Python.INFINITE_LOOP_TRAP.replace(/%1/g, + '"' + block.id + '"') + branch; + } + var code = 'for ' + variable0 + ' in ' + argument0 + ':\n' + branch; + return code; +}; + +Blockly.Python['controls_flow_statements'] = function(block) { + // Flow statements: continue, break. + switch (block.getTitleValue('FLOW')) { + case 'BREAK': + return 'break\n'; + case 'CONTINUE': + return 'continue\n'; + } + throw 'Unknown flow statement.'; +}; diff --git a/generators/python/math.js b/generators/python/math.js new file mode 100644 index 000000000..684c6035a --- /dev/null +++ b/generators/python/math.js @@ -0,0 +1,371 @@ +/** + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Generating Python for math blocks. + * @author q.neutron@gmail.com (Quynh Neutron) + */ +'use strict'; + +goog.provide('Blockly.Python.math'); + +goog.require('Blockly.Python'); + + +// If any new block imports any library, add that library name here. +Blockly.Python.addReservedWords('math,random'); + +Blockly.Python['math_number'] = function(block) { + // Numeric value. + var code = parseFloat(block.getTitleValue('NUM')); + var order = code < 0 ? Blockly.Python.ORDER_UNARY_SIGN : + Blockly.Python.ORDER_ATOMIC; + return [code, order]; +}; + +Blockly.Python['math_arithmetic'] = function(block) { + // Basic arithmetic operators, and power. + var OPERATORS = { + ADD: [' + ', Blockly.Python.ORDER_ADDITIVE], + MINUS: [' - ', Blockly.Python.ORDER_ADDITIVE], + MULTIPLY: [' * ', Blockly.Python.ORDER_MULTIPLICATIVE], + DIVIDE: [' / ', Blockly.Python.ORDER_MULTIPLICATIVE], + POWER: [' ** ', Blockly.Python.ORDER_EXPONENTIATION] + }; + var tuple = OPERATORS[block.getTitleValue('OP')]; + var operator = tuple[0]; + var order = tuple[1]; + var argument0 = Blockly.Python.valueToCode(block, 'A', order) || '0'; + var argument1 = Blockly.Python.valueToCode(block, 'B', order) || '0'; + var code = argument0 + operator + argument1; + return [code, order]; + // In case of 'DIVIDE', division between integers returns different results + // in Python 2 and 3. However, is not an issue since Blockly does not + // guarantee identical results in all languages. To do otherwise would + // require every operator to be wrapped in a function call. This would kill + // legibility of the generated code. See: + // http://code.google.com/p/blockly/wiki/Language +}; + +Blockly.Python['math_single'] = function(block) { + // Math operators with single operand. + var operator = block.getTitleValue('OP'); + var code; + var arg; + if (operator == 'NEG') { + // Negation is a special case given its different operator precedence. + var code = Blockly.Python.valueToCode(block, 'NUM', + Blockly.Python.ORDER_UNARY_SIGN) || '0'; + return ['-' + code, Blockly.Python.ORDER_UNARY_SIGN]; + } + Blockly.Python.definitions_['import_math'] = 'import math'; + if (operator == 'SIN' || operator == 'COS' || operator == 'TAN') { + arg = Blockly.Python.valueToCode(block, 'NUM', + Blockly.Python.ORDER_MULTIPLICATIVE) || '0'; + } else { + arg = Blockly.Python.valueToCode(block, 'NUM', + Blockly.Python.ORDER_NONE) || '0'; + } + // First, handle cases which generate values that don't need parentheses + // wrapping the code. + switch (operator) { + case 'ABS': + code = 'math.fabs(' + arg + ')'; + break; + case 'ROOT': + code = 'math.sqrt(' + arg + ')'; + break; + case 'LN': + code = 'math.log(' + arg + ')'; + break; + case 'LOG10': + code = 'math.log10(' + arg + ')'; + break; + case 'EXP': + code = 'math.exp(' + arg + ')'; + break; + case 'POW10': + code = 'math.pow(10,' + arg + ')'; + break; + case 'ROUND': + code = 'round(' + arg + ')'; + break; + case 'ROUNDUP': + code = 'math.ceil(' + arg + ')'; + break; + case 'ROUNDDOWN': + code = 'math.floor(' + arg + ')'; + break; + case 'SIN': + code = 'math.sin(' + arg + ' / 180.0 * math.pi)'; + break; + case 'COS': + code = 'math.cos(' + arg + ' / 180.0 * math.pi)'; + break; + case 'TAN': + code = 'math.tan(' + arg + ' / 180.0 * math.pi)'; + break; + } + if (code) { + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } + // Second, handle cases which generate values that may need parentheses + // wrapping the code. + switch (operator) { + case 'ASIN': + code = 'math.asin(' + arg + ') / math.pi * 180'; + break; + case 'ACOS': + code = 'math.acos(' + arg + ') / math.pi * 180'; + break; + case 'ATAN': + code = 'math.atan(' + arg + ') / math.pi * 180'; + break; + default: + throw 'Unknown math operator: ' + operator; + } + return [code, Blockly.Python.ORDER_MULTIPLICATIVE]; +}; + +Blockly.Python['math_constant'] = function(block) { + // Constants: PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), INFINITY. + var CONSTANTS = { + PI: ['math.pi', Blockly.Python.ORDER_MEMBER], + E: ['math.e', Blockly.Python.ORDER_MEMBER], + GOLDEN_RATIO: ['(1 + math.sqrt(5)) / 2', Blockly.Python.ORDER_MULTIPLICATIVE], + SQRT2: ['math.sqrt(2)', Blockly.Python.ORDER_MEMBER], + SQRT1_2: ['math.sqrt(1.0 / 2)', Blockly.Python.ORDER_MEMBER], + INFINITY: ['float(\'inf\')', Blockly.Python.ORDER_ATOMIC] + }; + var constant = block.getTitleValue('CONSTANT'); + if (constant != 'INFINITY') { + Blockly.Python.definitions_['import_math'] = 'import math'; + } + return CONSTANTS[constant]; +}; + +Blockly.Python['math_number_property'] = function(block) { + // Check if a number is even, odd, prime, whole, positive, or negative + // or if it is divisible by certain number. Returns true or false. + var number_to_check = Blockly.Python.valueToCode(block, 'NUMBER_TO_CHECK', + Blockly.Python.ORDER_MULTIPLICATIVE) || '0'; + var dropdown_property = block.getTitleValue('PROPERTY'); + var code; + if (dropdown_property == 'PRIME') { + Blockly.Python.definitions_['import_math'] = 'import math'; + var functionName = Blockly.Python.provideFunction_( + 'isPrime', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(n):', + ' # http://en.wikipedia.org/wiki/Primality_test#Naive_methods', + ' # If n is not a number but a string, try parsing it.', + ' if type(n) not in (int, float, long):', + ' try:', + ' n = float(n)', + ' except:', + ' return False', + ' if n == 2 or n == 3:', + ' return True', + ' # False if n is negative, is 1, or not whole,' + + ' or if n is divisible by 2 or 3.', + ' if n <= 1 or n % 1 != 0 or n % 2 == 0 or n % 3 == 0:', + ' return False', + ' # Check all the numbers of form 6k +/- 1, up to sqrt(n).', + ' for x in range(6, int(math.sqrt(n)) + 2, 6):', + ' if n % (x - 1) == 0 or n % (x + 1) == 0:', + ' return False', + ' return True']); + code = functionName + '(' + number_to_check + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } + switch (dropdown_property) { + case 'EVEN': + code = number_to_check + ' % 2 == 0'; + break; + case 'ODD': + code = number_to_check + ' % 2 == 1'; + break; + case 'WHOLE': + code = number_to_check + ' % 1 == 0'; + break; + case 'POSITIVE': + code = number_to_check + ' > 0'; + break; + case 'NEGATIVE': + code = number_to_check + ' < 0'; + break; + case 'DIVISIBLE_BY': + var divisor = Blockly.Python.valueToCode(block, 'DIVISOR', + Blockly.Python.ORDER_MULTIPLICATIVE); + // If 'divisor' is some code that evals to 0, Python will raise an error. + if (!divisor || divisor == '0') { + return ['False', Blockly.Python.ORDER_ATOMIC]; + } + code = number_to_check + ' % ' + divisor + ' == 0'; + break; + } + return [code, Blockly.Python.ORDER_RELATIONAL]; +}; + +Blockly.Python['math_change'] = function(block) { + // Add to a variable in place. + var argument0 = Blockly.Python.valueToCode(block, 'DELTA', + Blockly.Python.ORDER_ADDITIVE) || '0'; + var varName = Blockly.Python.variableDB_.getName(block.getTitleValue('VAR'), + Blockly.Variables.NAME_TYPE); + return varName + ' = (' + varName + ' if type(' + varName + + ') in (int, float, long) else 0) + ' + argument0 + '\n'; +}; + +// Rounding functions have a single operand. +Blockly.Python['math_round'] = Blockly.Python['math_single']; +// Trigonometry functions have a single operand. +Blockly.Python['math_trig'] = Blockly.Python['math_single']; + +Blockly.Python['math_on_list'] = function(block) { + // Math functions for lists. + var func = block.getTitleValue('OP'); + var list = Blockly.Python.valueToCode(block, 'LIST', + Blockly.Python.ORDER_NONE) || '[]'; + var code; + switch (func) { + case 'SUM': + code = 'sum(' + list + ')'; + break; + case 'MIN': + code = 'min(' + list + ')'; + break; + case 'MAX': + code = 'max(' + list + ')'; + break; + case 'AVERAGE': + var functionName = Blockly.Python.provideFunction_( + 'math_mean', + // This operation excludes null and values that are not int or float:', + // math_mean([null, null, "aString", 1, 9]) == 5.0.', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(myList):', + ' localList = [e for e in myList if type(e) in (int, float, long)]', + ' if not localList: return', + ' return float(sum(localList)) / len(localList)']); + code = functionName + '(' + list + ')'; + break; + case 'MEDIAN': + var functionName = Blockly.Python.provideFunction_( + 'math_median', + // This operation excludes null values: + // math_median([null, null, 1, 3]) == 2.0. + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(myList):', + ' localList = sorted([e for e in myList ' + + 'if type(e) in (int, float, long)])', + ' if not localList: return', + ' if len(localList) % 2 == 0:', + ' return (localList[len(localList) / 2 - 1] + ' + + 'localList[len(localList) / 2]) / 2.0', + ' else:', + ' return localList[(len(localList) - 1) / 2]']); + code = functionName + '(' + list + ')'; + break; + case 'MODE': + var functionName = Blockly.Python.provideFunction_( + 'math_modes', + // As a list of numbers can contain more than one mode, + // the returned result is provided as an array. + // Mode of [3, 'x', 'x', 1, 1, 2, '3'] -> ['x', 1]. + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(some_list):', + ' modes = []', + ' # Using a lists of [item, count] to keep count rather than dict', + ' # to avoid "unhashable" errors when the counted item is ' + + 'itself a list or dict.', + ' counts = []', + ' maxCount = 1', + ' for item in some_list:', + ' found = False', + ' for count in counts:', + ' if count[0] == item:', + ' count[1] += 1', + ' maxCount = max(maxCount, count[1])', + ' found = True', + ' if not found:', + ' counts.append([item, 1])', + ' for counted_item, item_count in counts:', + ' if item_count == maxCount:', + ' modes.append(counted_item)', + ' return modes']); + code = functionName + '(' + list + ')'; + break; + case 'STD_DEV': + Blockly.Python.definitions_['import_math'] = 'import math'; + var functionName = Blockly.Python.provideFunction_( + 'math_standard_deviation', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(numbers):', + ' n = len(numbers)', + ' if n == 0: return', + ' mean = float(sum(numbers)) / n', + ' variance = sum((x - mean) ** 2 for x in numbers) / n', + ' return math.sqrt(variance)']); + code = functionName + '(' + list + ')'; + break; + case 'RANDOM': + Blockly.Python.definitions_['import_random'] = 'import random'; + code = 'random.choice(' + list + ')'; + break; + default: + throw 'Unknown operator: ' + func; + } + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; +}; + +Blockly.Python['math_modulo'] = function(block) { + // Remainder computation. + var argument0 = Blockly.Python.valueToCode(block, 'DIVIDEND', + Blockly.Python.ORDER_MULTIPLICATIVE) || '0'; + var argument1 = Blockly.Python.valueToCode(block, 'DIVISOR', + Blockly.Python.ORDER_MULTIPLICATIVE) || '0'; + var code = argument0 + ' % ' + argument1; + return [code, Blockly.Python.ORDER_MULTIPLICATIVE]; +}; + +Blockly.Python['math_constrain'] = function(block) { + // Constrain a number between two limits. + var argument0 = Blockly.Python.valueToCode(block, 'VALUE', + Blockly.Python.ORDER_NONE) || '0'; + var argument1 = Blockly.Python.valueToCode(block, 'LOW', + Blockly.Python.ORDER_NONE) || '0'; + var argument2 = Blockly.Python.valueToCode(block, 'HIGH', + Blockly.Python.ORDER_NONE) || 'float(\'inf\')'; + var code = 'min(max(' + argument0 + ', ' + argument1 + '), ' + + argument2 + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; +}; + +Blockly.Python['math_random_int'] = function(block) { + // Random integer between [X] and [Y]. + Blockly.Python.definitions_['import_random'] = 'import random'; + var argument0 = Blockly.Python.valueToCode(block, 'FROM', + Blockly.Python.ORDER_NONE) || '0'; + var argument1 = Blockly.Python.valueToCode(block, 'TO', + Blockly.Python.ORDER_NONE) || '0'; + var code = 'random.randint(' + argument0 + ', ' + argument1 + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; +}; + +Blockly.Python['math_random_float'] = function(block) { + // Random fraction between 0 and 1. + Blockly.Python.definitions_['import_random'] = 'import random'; + return ['random.random()', Blockly.Python.ORDER_FUNCTION_CALL]; +}; diff --git a/generators/python/procedures.js b/generators/python/procedures.js new file mode 100644 index 000000000..2cf311760 --- /dev/null +++ b/generators/python/procedures.js @@ -0,0 +1,117 @@ +/** + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Generating Python for procedure blocks. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Python.procedures'); + +goog.require('Blockly.Python'); + + +Blockly.Python['procedures_defreturn'] = function(block) { + // Define a procedure with a return value. + // First, add a 'global' statement for every variable that is assigned. + var globals = Blockly.Variables.allVariables(block); + for (var i = globals.length - 1; i >= 0; i--) { + var varName = globals[i]; + if (block.arguments_.indexOf(varName) == -1) { + globals[i] = Blockly.Python.variableDB_.getName(varName, + Blockly.Variables.NAME_TYPE); + } else { + // This variable is actually a parameter name. Do not include it in + // the list of globals, thus allowing it be of local scope. + globals.splice(i, 1); + } + } + globals = globals.length ? ' global ' + globals.join(', ') + '\n' : ''; + var funcName = Blockly.Python.variableDB_.getName(block.getTitleValue('NAME'), + Blockly.Procedures.NAME_TYPE); + var branch = Blockly.Python.statementToCode(block, 'STACK'); + if (Blockly.Python.INFINITE_LOOP_TRAP) { + branch = Blockly.Python.INFINITE_LOOP_TRAP.replace(/%1/g, + '"' + block.id + '"') + branch; + } + var returnValue = Blockly.Python.valueToCode(block, 'RETURN', + Blockly.Python.ORDER_NONE) || ''; + if (returnValue) { + returnValue = ' return ' + returnValue + '\n'; + } else if (!branch) { + branch = ' pass'; + } + var args = []; + for (var x = 0; x < block.arguments_.length; x++) { + args[x] = Blockly.Python.variableDB_.getName(block.arguments_[x], + Blockly.Variables.NAME_TYPE); + } + var code = 'def ' + funcName + '(' + args.join(', ') + '):\n' + + globals + branch + returnValue; + code = Blockly.Python.scrub_(block, code); + Blockly.Python.definitions_[funcName] = code; + return null; +}; + +// Defining a procedure without a return value uses the same generator as +// a procedure with a return value. +Blockly.Python['procedures_defnoreturn'] = + Blockly.Python['procedures_defreturn']; + +Blockly.Python['procedures_callreturn'] = function(block) { + // Call a procedure with a return value. + var funcName = Blockly.Python.variableDB_.getName(block.getTitleValue('NAME'), + Blockly.Procedures.NAME_TYPE); + var args = []; + for (var x = 0; x < block.arguments_.length; x++) { + args[x] = Blockly.Python.valueToCode(block, 'ARG' + x, + Blockly.Python.ORDER_NONE) || 'None'; + } + var code = funcName + '(' + args.join(', ') + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; +}; + +Blockly.Python['procedures_callnoreturn'] = function(block) { + // Call a procedure with no return value. + var funcName = Blockly.Python.variableDB_.getName(block.getTitleValue('NAME'), + Blockly.Procedures.NAME_TYPE); + var args = []; + for (var x = 0; x < block.arguments_.length; x++) { + args[x] = Blockly.Python.valueToCode(block, 'ARG' + x, + Blockly.Python.ORDER_NONE) || 'None'; + } + var code = funcName + '(' + args.join(', ') + ')\n'; + return code; +}; + +Blockly.Python['procedures_ifreturn'] = function(block) { + // Conditionally return value from a procedure. + var condition = Blockly.Python.valueToCode(block, 'CONDITION', + Blockly.Python.ORDER_NONE) || 'False'; + var code = 'if ' + condition + ':\n'; + if (block.hasReturnValue_) { + var value = Blockly.Python.valueToCode(block, 'VALUE', + Blockly.Python.ORDER_NONE) || 'None'; + code += ' return ' + value + '\n'; + } else { + code += ' return\n'; + } + return code; +}; diff --git a/generators/python/text.js b/generators/python/text.js new file mode 100644 index 000000000..431bdf955 --- /dev/null +++ b/generators/python/text.js @@ -0,0 +1,252 @@ +/** + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Generating Python for text blocks. + * @author q.neutron@gmail.com (Quynh Neutron) + */ +'use strict'; + +goog.provide('Blockly.Python.text'); + +goog.require('Blockly.Python'); + + +Blockly.Python['text'] = function(block) { + // Text value. + var code = Blockly.Python.quote_(block.getTitleValue('TEXT')); + return [code, Blockly.Python.ORDER_ATOMIC]; +}; + +Blockly.Python['text_join'] = function(block) { + // Create a string made up of any number of elements of any type. + //Should we allow joining by '-' or ',' or any other characters? + var code; + if (block.itemCount_ == 0) { + return ['\'\'', Blockly.Python.ORDER_ATOMIC]; + } else if (block.itemCount_ == 1) { + var argument0 = Blockly.Python.valueToCode(block, 'ADD0', + Blockly.Python.ORDER_NONE) || '\'\''; + code = 'str(' + argument0 + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } else if (block.itemCount_ == 2) { + var argument0 = Blockly.Python.valueToCode(block, 'ADD0', + Blockly.Python.ORDER_NONE) || '\'\''; + var argument1 = Blockly.Python.valueToCode(block, 'ADD1', + Blockly.Python.ORDER_NONE) || '\'\''; + var code = 'str(' + argument0 + ') + str(' + argument1 + ')'; + return [code, Blockly.Python.ORDER_UNARY_SIGN]; + } else { + var code = []; + for (var n = 0; n < block.itemCount_; n++) { + code[n] = Blockly.Python.valueToCode(block, 'ADD' + n, + Blockly.Python.ORDER_NONE) || '\'\''; + } + var tempVar = Blockly.Python.variableDB_.getDistinctName('temp_value', + Blockly.Variables.NAME_TYPE); + code = '\'\'.join([str(' + tempVar + ') for ' + tempVar + ' in [' + + code.join(', ') + ']])'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } +}; + +Blockly.Python['text_append'] = function(block) { + // Append to a variable in place. + var varName = Blockly.Python.variableDB_.getName(block.getTitleValue('VAR'), + Blockly.Variables.NAME_TYPE); + var argument0 = Blockly.Python.valueToCode(block, 'TEXT', + Blockly.Python.ORDER_NONE) || '\'\''; + return varName + ' = str(' + varName + ') + str(' + argument0 + ')\n'; +}; + +Blockly.Python['text_length'] = function(block) { + // String length. + var argument0 = Blockly.Python.valueToCode(block, 'VALUE', + Blockly.Python.ORDER_NONE) || '\'\''; + return ['len(' + argument0 + ')', Blockly.Python.ORDER_FUNCTION_CALL]; +}; + +Blockly.Python['text_isEmpty'] = function(block) { + // Is the string null? + var argument0 = Blockly.Python.valueToCode(block, 'VALUE', + Blockly.Python.ORDER_NONE) || '\'\''; + var code = 'not len(' + argument0 + ')'; + return [code, Blockly.Python.ORDER_LOGICAL_NOT]; +}; + +Blockly.Python['text_indexOf'] = function(block) { + // Search the text for a substring. + // Should we allow for non-case sensitive??? + var operator = block.getTitleValue('END') == 'FIRST' ? 'find' : 'rfind'; + var argument0 = Blockly.Python.valueToCode(block, 'FIND', + Blockly.Python.ORDER_NONE) || '\'\''; + var argument1 = Blockly.Python.valueToCode(block, 'VALUE', + Blockly.Python.ORDER_MEMBER) || '\'\''; + var code = argument1 + '.' + operator + '(' + argument0 + ') + 1'; + return [code, Blockly.Python.ORDER_MEMBER]; +}; + +Blockly.Python['text_charAt'] = function(block) { + // Get letter at index. + // Note: Until January 2013 this block did not have the WHERE input. + var where = block.getTitleValue('WHERE') || 'FROM_START'; + var at = Blockly.Python.valueToCode(block, 'AT', + Blockly.Python.ORDER_UNARY_SIGN) || '1'; + var text = Blockly.Python.valueToCode(block, 'VALUE', + Blockly.Python.ORDER_MEMBER) || '\'\''; + switch (where) { + case 'FIRST': + var code = text + '[0]'; + return [code, Blockly.Python.ORDER_MEMBER]; + case 'LAST': + var code = text + '[-1]'; + return [code, Blockly.Python.ORDER_MEMBER]; + case 'FROM_START': + // Blockly uses one-based indicies. + if (Blockly.isNumber(at)) { + // If the index is a naked number, decrement it right now. + at = parseInt(at, 10) - 1; + } else { + // If the index is dynamic, decrement it in code. + at = 'int(' + at + ' - 1)'; + } + var code = text + '[' + at + ']'; + return [code, Blockly.Python.ORDER_MEMBER]; + case 'FROM_END': + var code = text + '[-' + at + ']'; + return [code, Blockly.Python.ORDER_MEMBER]; + case 'RANDOM': + Blockly.Python.definitions_['import_random'] = 'import random'; + var functionName = Blockly.Python.provideFunction_( + 'text_random_letter', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(text):', + ' x = int(random.random() * len(text))', + ' return text[x];']); + code = functionName + '(' + text + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } + throw 'Unhandled option (text_charAt).'; +}; + +Blockly.Python['text_getSubstring'] = function(block) { + // Get substring. + var text = Blockly.Python.valueToCode(block, 'STRING', + Blockly.Python.ORDER_MEMBER) || '\'\''; + var where1 = block.getTitleValue('WHERE1'); + var where2 = block.getTitleValue('WHERE2'); + var at1 = Blockly.Python.valueToCode(block, 'AT1', + Blockly.Python.ORDER_ADDITIVE) || '1'; + var at2 = Blockly.Python.valueToCode(block, 'AT2', + Blockly.Python.ORDER_ADDITIVE) || '1'; + if (where1 == 'FIRST' || (where1 == 'FROM_START' && at1 == '1')) { + at1 = ''; + } else if (where1 == 'FROM_START') { + // Blockly uses one-based indicies. + if (Blockly.isNumber(at1)) { + // If the index is a naked number, decrement it right now. + at1 = parseInt(at1, 10) - 1; + } else { + // If the index is dynamic, decrement it in code. + at1 = 'int(' + at1 + ' - 1)'; + } + } else if (where1 == 'FROM_END') { + if (Blockly.isNumber(at1)) { + at1 = -parseInt(at1, 10); + } else { + at1 = '-int(' + at1 + ')'; + } + } + if (where2 == 'LAST' || (where2 == 'FROM_END' && at2 == '1')) { + at2 = ''; + } else if (where1 == 'FROM_START') { + if (Blockly.isNumber(at2)) { + at2 = parseInt(at2, 10); + } else { + at2 = 'int(' + at2 + ')'; + } + } else if (where1 == 'FROM_END') { + if (Blockly.isNumber(at2)) { + // If the index is a naked number, increment it right now. + at2 = 1 - parseInt(at2, 10); + if (at2 == 0) { + at2 = ''; + } + } else { + // If the index is dynamic, increment it in code. + // Add special case for -0. + Blockly.Python.definitions_['import_sys'] = 'import sys'; + at2 = 'int(1 - ' + at2 + ') or sys.maxsize'; + } + } + var code = text + '[' + at1 + ' : ' + at2 + ']'; + return [code, Blockly.Python.ORDER_MEMBER]; +}; + +Blockly.Python['text_changeCase'] = function(block) { + // Change capitalization. + var OPERATORS = { + UPPERCASE: '.upper()', + LOWERCASE: '.lower()', + TITLECASE: '.title()' + }; + var operator = OPERATORS[block.getTitleValue('CASE')]; + var argument0 = Blockly.Python.valueToCode(block, 'TEXT', + Blockly.Python.ORDER_MEMBER) || '\'\''; + var code = argument0 + operator; + return [code, Blockly.Python.ORDER_MEMBER]; +}; + +Blockly.Python['text_trim'] = function(block) { + // Trim spaces. + var OPERATORS = { + LEFT: '.lstrip()', + RIGHT: '.rstrip()', + BOTH: '.strip()' + }; + var operator = OPERATORS[block.getTitleValue('MODE')]; + var argument0 = Blockly.Python.valueToCode(block, 'TEXT', + Blockly.Python.ORDER_MEMBER) || '\'\''; + var code = argument0 + operator; + return [code, Blockly.Python.ORDER_MEMBER]; +}; + +Blockly.Python['text_print'] = function(block) { + // Print statement. + var argument0 = Blockly.Python.valueToCode(block, 'TEXT', + Blockly.Python.ORDER_NONE) || '\'\''; + return 'print(' + argument0 + ')\n'; +}; + +Blockly.Python['text_prompt'] = function(block) { + // Prompt function. + var functionName = Blockly.Python.provideFunction_( + 'text_prompt', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(msg):', + ' try:', + ' return raw_input(msg)', + ' except NameError:', + ' return input(msg)']); + var msg = Blockly.Python.quote_(block.getTitleValue('TEXT')); + var code = functionName + '(' + msg + ')'; + var toNumber = block.getTitleValue('TYPE') == 'NUMBER'; + if (toNumber) { + code = 'float(' + code + ')'; + } + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; +}; diff --git a/generators/python/variables.js b/generators/python/variables.js new file mode 100644 index 000000000..5804f0772 --- /dev/null +++ b/generators/python/variables.js @@ -0,0 +1,45 @@ +/** + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Generating Python for variable blocks. + * @author q.neutron@gmail.com (Quynh Neutron) + */ +'use strict'; + +goog.provide('Blockly.Python.variables'); + +goog.require('Blockly.Python'); + + +Blockly.Python['variables_get'] = function(block) { + // Variable getter. + var code = Blockly.Python.variableDB_.getName(block.getTitleValue('VAR'), + Blockly.Variables.NAME_TYPE); + return [code, Blockly.Python.ORDER_ATOMIC]; +}; + +Blockly.Python['variables_set'] = function(block) { + // Variable setter. + var argument0 = Blockly.Python.valueToCode(block, 'VALUE', + Blockly.Python.ORDER_NONE) || '0'; + var varName = Blockly.Python.variableDB_.getName(block.getTitleValue('VAR'), + Blockly.Variables.NAME_TYPE); + return varName + ' = ' + argument0 + '\n'; +}; diff --git a/i18n/common.py b/i18n/common.py new file mode 100644 index 000000000..d648e3267 --- /dev/null +++ b/i18n/common.py @@ -0,0 +1,291 @@ +#!/usr/bin/python + +# Code shared by translation conversion scripts. +# +# Copyright 2013 Google Inc. +# http://blockly.googlecode.com/ +# +# 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. + +import codecs +import json +import os +from datetime import datetime + +class InputError(Exception): + """Exception raised for errors in the input. + + Attributes: + location -- where error occurred + msg -- explanation of the error + + """ + + def __init__(self, location, msg): + Exception.__init__(self, '{0}: {1}'.format(location, msg)) + self.location = location + self.msg = msg + + +def read_json_file(filename): + """Read a JSON file as UTF-8 into a dictionary, discarding @metadata. + + Args: + filename: The filename, which must end ".json". + + Returns: + The dictionary. + + Raises: + InputError: The filename did not end with ".json" or an error occurred + while opening or reading the file. + """ + if not filename.endswith('.json'): + raise InputError(filename, 'filenames must end with ".json"') + try: + # Read in file. + with codecs.open(filename, 'r', 'utf-8') as infile: + defs = json.load(infile) + if '@metadata' in defs: + del defs['@metadata'] + return defs + except ValueError, e: + print('Error reading ' + filename) + raise InputError(file, str(e)) + + +def _create_qqq_file(output_dir): + """Creates a qqq.json file with message documentation for translatewiki.net. + + The file consists of key-value pairs, where the keys are message ids and + the values are descriptions for the translators of the messages. + What documentation exists for the format can be found at: + http://translatewiki.net/wiki/Translating:Localisation_for_developers#Message_documentation + + The file should be closed by _close_qqq_file(). + + Parameters: + output_dir: The output directory. + + Returns: + A pointer to a file to which a left brace and newline have been written. + + Raises: + IOError: An error occurred while opening or writing the file. + """ + qqq_file_name = os.path.join(os.curdir, output_dir, 'qqq.json') + qqq_file = codecs.open(qqq_file_name, 'w', 'utf-8') + print 'Created file: ' + qqq_file_name + qqq_file.write('{\n') + return qqq_file + + +def _close_qqq_file(qqq_file): + """Closes a qqq.json file created and opened by _create_qqq_file(). + + This writes the final newlines and right brace. + + Args: + qqq_file: A file created by _create_qqq_file(). + + Raises: + IOError: An error occurred while writing to or closing the file. + """ + qqq_file.write('\n}\n') + qqq_file.close() + + +def _create_lang_file(author, lang, output_dir): + """Creates a .json file for translatewiki.net. + + The file consists of metadata, followed by key-value pairs, where the keys + are message ids and the values are the messages in the language specified + by the corresponding command-line argument. The file should be closed by + _close_lang_file(). + + Args: + author: Name and email address of contact for translators. + lang: ISO 639-1 source language code. + output_dir: Relative directory for output files. + + Returns: + A pointer to a file to which the metadata has been written. + + Raises: + IOError: An error occurred while opening or writing the file. + """ + lang_file_name = os.path.join(os.curdir, output_dir, lang + '.json') + lang_file = codecs.open(lang_file_name, 'w', 'utf-8') + print 'Created file: ' + lang_file_name + # string.format doesn't like printing braces, so break up our writes. + lang_file.write('{\n "@metadata": {') + lang_file.write(""" + "author": "{0}", + "lastupdated": "{1}", + "locale": "{2}", + "messagedocumentation" : "qqq" +""".format(author, str(datetime.now()), lang)) + lang_file.write(' },\n') + return lang_file + + +def _close_lang_file(lang_file): + """Closes a .json file created with _create_lang_file(). + + This also writes the terminating left brace and newline. + + Args: + lang_file: A file opened with _create_lang_file(). + + Raises: + IOError: An error occurred while writing to or closing the file. + """ + lang_file.write('\n}\n') + lang_file.close() + + +def _create_key_file(output_dir): + """Creates a keys.json file mapping Closure keys to Blockly keys. + + Args: + output_dir: Relative directory for output files. + + Raises: + IOError: An error occurred while creating the file. + """ + key_file_name = os.path.join(os.curdir, output_dir, 'keys.json') + key_file = open(key_file_name, 'w') + key_file.write('{\n') + print 'Created file: ' + key_file_name + return key_file + + +def _close_key_file(key_file): + """Closes a key file created and opened with _create_key_file(). + + Args: + key_file: A file created by _create_key_file(). + + Raises: + IOError: An error occurred while writing to or closing the file. + """ + key_file.write('\n}\n') + key_file.close() + + +def write_files(author, lang, output_dir, units, write_key_file): + """Writes the output files for the given units. + + There are three possible output files: + * lang_file: JSON file mapping meanings (e.g., Maze.turnLeft) to the + English text. The base name of the language file is specified by the + "lang" command-line argument. + * key_file: JSON file mapping meanings to Soy-generated keys (long hash + codes). This is only output if the parameter write_key_file is True. + * qqq_file: JSON file mapping meanings to descriptions. + + Args: + author: Name and email address of contact for translators. + lang: ISO 639-1 source language code. + output_dir: Relative directory for output files. + units: A list of dictionaries with entries for 'meaning', 'source', + 'description', and 'keys' (the last only if write_key_file is true), + in the order desired in the output files. + write_key_file: Whether to output a keys.json file. + + Raises: + IOError: An error occurs opening, writing to, or closing a file. + KeyError: An expected key is missing from units. + """ + lang_file = _create_lang_file(author, lang, output_dir) + qqq_file = _create_qqq_file(output_dir) + if write_key_file: + key_file = _create_key_file(output_dir) + first_entry = True + for unit in units: + if not first_entry: + lang_file.write(',\n') + if write_key_file: + key_file.write(',\n') + qqq_file.write(',\n') + lang_file.write(u' "{0}": "{1}"'.format( + unit['meaning'], + unit['source'].replace('"', "'"))) + if write_key_file: + key_file.write('"{0}": "{1}"'.format(unit['meaning'], unit['key'])) + qqq_file.write(u' "{0}": "{1}"'.format( + unit['meaning'], + unit['description'].replace('"', "'").replace( + '{lb}', '{').replace('{rb}', '}'))) + first_entry = False + _close_lang_file(lang_file) + if write_key_file: + _close_key_file(key_file) + _close_qqq_file(qqq_file) + + +def insert_breaks(s, min_length, max_length): + """Inserts line breaks to try to get line lengths within the given range. + + This tries to minimize raggedness and to break lines at punctuation + (periods and commas). It never splits words or numbers. Multiple spaces + may be converted into single spaces. + + Args: + s: The string to split. + min_length: The requested minimum number of characters per line. + max_length: The requested minimum number of characters per line. + + Returns: + A copy of the original string with zero or more line breaks inserted. + """ + newline = '\\n' + if len(s) < min_length: + return s + # Try splitting by sentences. This assumes sentences end with periods. + sentences = s.split('.') + # Remove empty sentences. + sentences = [sen for sen in sentences if sen] + + # If all sentences are at least min_length and at most max_length, + # then return one per line. + if not [sen for sen in sentences if + len(sen) > max_length or len(sen) < min_length]: + return newline.join([sen.strip() + '.' for sen in sentences]) + + # Otherwise, divide into words, and use a greedy algorithm for the first + # line, and try to get later lines as close as possible in length. + words = [word for word in s.split(' ') if word] + line1 = '' + while (len(line1) + 1 + len(words[0]) < max_length and + # Preferentially split on periods and commas. + (not ((line1.endswith('. ') or line1.endswith(', ')) and + len(line1) > min_length))): + line1 += words.pop(0) + ' ' + # If it all fits on one line, return that line. + if not words: + return line1 + ideal_length = len(line1) + output = line1 + line = '' + while words: + line += words.pop(0) + ' ' + if words: + potential_len = len(line) + len(words[0]) + if (potential_len > max_length or + potential_len - ideal_length > ideal_length - len(line) or + (line.endswith('. ') and len(line) > min_length)): + output += newline + line + line = '' + output += newline + line + return output diff --git a/i18n/create_messages.py b/i18n/create_messages.py new file mode 100755 index 000000000..2aa508560 --- /dev/null +++ b/i18n/create_messages.py @@ -0,0 +1,121 @@ +#!/usr/bin/python + +# Generate .js files defining Blockly core and language messages. +# +# Copyright 2013 Google Inc. +# http://blockly.googlecode.com/ +# +# 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. + +import argparse +import codecs +import os +from common import InputError +from common import read_json_file + + +def main(): + """Generate .js files defining Blockly core and language messages.""" + + # Process command-line arguments. + parser = argparse.ArgumentParser(description='Convert JSON files to JS.') + parser.add_argument('--source_lang', default='en', + help='ISO 639-1 source language code') + parser.add_argument('--source_lang_file', + default=os.path.join('json', 'en.json'), + help='Path to .json file for source language') + parser.add_argument('--source_synonym_file', + default=os.path.join('json', 'synonyms.json'), + help='Path to .json file with synonym definitions') + parser.add_argument('--output_dir', default='js/', + help='relative directory for output files') + parser.add_argument('--key_file', default='keys.json', + help='relative path to input keys file') + parser.add_argument('--min_length', default=30, + help='minimum line length (not counting last line)') + parser.add_argument('--max_length', default=50, + help='maximum line length (not guaranteed)') + parser.add_argument('--quiet', action='store_true', default=False, + help='do not write anything to standard output') + parser.add_argument('files', nargs='+', help='input files') + args = parser.parse_args() + if not args.output_dir.endswith(os.path.sep): + args.output_dir += os.path.sep + + # Read in source language .json file, which provides any values missing + # in target languages' .json files. + source_defs = read_json_file(os.path.join(os.curdir, args.source_lang_file)) + sorted_keys = source_defs.keys() + sorted_keys.sort() + + # Read in synonyms file, which must be output in every language. + synonym_defs = read_json_file(os.path.join( + os.curdir, args.source_synonym_file)) + synonym_text = '\n'.join(['Blockly.Msg.{0} = Blockly.Msg.{1};'.format( + key, synonym_defs[key]) for key in synonym_defs]) + + # Create each output file. + for arg_file in args.files: + (_, filename) = os.path.split(arg_file) + target_lang = filename[:filename.index('.')] + if target_lang not in ('qqq', 'keys', 'synonyms'): + target_defs = read_json_file(os.path.join(os.curdir, arg_file)) + + # Output file. + outname = os.path.join(os.curdir, args.output_dir, target_lang + '.js') + with codecs.open(outname, 'w', 'utf-8') as outfile: + outfile.write( + """// This file was automatically generated. Do not modify. + +'use strict'; + +goog.provide('Blockly.Msg.{0}'); + +goog.require('Blockly.Msg'); + +""".format(target_lang)) + # For each key in the source language file, output the target value + # if present; otherwise, output the source language value with a + # warning comment. + for key in sorted_keys: + if key in target_defs: + value = target_defs[key] + comment = '' + del target_defs[key] + else: + value = source_defs[key] + comment = ' // untranslated' + value = value.replace('"', '\\"') + outfile.write(u'Blockly.Msg.{0} = "{1}";{2}\n'.format( + key, value, comment)) + + # Announce any keys defined only for target language. + if target_defs: + extra_keys = [key for key in target_defs if key not in synonym_defs] + synonym_keys = [key for key in target_defs if key in synonym_defs] + if not args.quiet: + if extra_keys: + print('These extra keys appeared in {0}: {1}'.format( + filename, ', '.join(extra_keys))) + if synonym_keys: + print('These synonym keys appeared in {0}: {1}'.format( + filename, ', '.join(synonym_keys))) + + outfile.write(synonym_text) + + if not args.quiet: + print('Created {0}.'.format(outname)) + + +if __name__ == '__main__': + main() diff --git a/i18n/dedup_json.py b/i18n/dedup_json.py new file mode 100755 index 000000000..e0298de95 --- /dev/null +++ b/i18n/dedup_json.py @@ -0,0 +1,73 @@ +#!/usr/bin/python + +# Consolidates duplicate key-value pairs in a JSON file. +# If the same key is used with different values, no warning is given, +# and there is no guarantee about which key-value pair will be output. +# There is also no guarantee as to the order of the key-value pairs +# output. +# +# Copyright 2013 Google Inc. +# http://blockly.googlecode.com/ +# +# 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. + +import argparse +import codecs +import json +from common import InputError + + +def main(): + """Parses arguments and iterates over files. + + Raises: + IOError: An I/O error occurred with an input or output file. + InputError: Input JSON could not be parsed. + """ + + # Set up argument parser. + parser = argparse.ArgumentParser( + description='Removes duplicate key-value pairs from JSON files.') + parser.add_argument('--suffix', default='', + help='optional suffix for output files; ' + 'if empty, files will be changed in place') + parser.add_argument('files', nargs='+', help='input files') + args = parser.parse_args() + + # Iterate over files. + for filename in args.files: + # Read in json using Python libraries. This eliminates duplicates. + print('Processing ' + filename + '...') + try: + with codecs.open(filename, 'r', 'utf-8') as infile: + j = json.load(infile) + except ValueError, e: + print('Error reading ' + filename) + raise InputError(file, str(e)) + + # Built up output strings as an array to make output of delimiters easier. + output = [] + for key in j: + if key != '@metadata': + output.append('\t"' + key + '": "' + + j[key].replace('\n', '\\n') + '"') + + # Output results. + with codecs.open(filename + args.suffix, 'w', 'utf-8') as outfile: + outfile.write('{\n') + outfile.write(',\n'.join(output)) + outfile.write('\n}\n') + + +if __name__ == '__main__': + main() diff --git a/i18n/js_to_json.py b/i18n/js_to_json.py new file mode 100755 index 000000000..e52a00c7a --- /dev/null +++ b/i18n/js_to_json.py @@ -0,0 +1,120 @@ +#!/usr/bin/python + +# Gives the translation status of the specified apps and languages. +# +# Copyright 2013 Google Inc. +# http://blockly.googlecode.com/ +# +# 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. + +"""Extracts messages from .js files into .json files for translation. + +Specifically, lines with the following formats are extracted: + + /// Here is a description of the following message. + Blockly.SOME_KEY = 'Some value'; + +Adjacent "///" lines are concatenated. + +There are two output files, each of which is proper JSON. For each key, the +file en.json would get an entry of the form: + + "Blockly.SOME_KEY", "Some value", + +The file qqq.json would get: + + "Blockly.SOME_KEY", "Here is a description of the following message.", + +Commas would of course be omitted for the final entry of each value. + +@author Ellen Spertus (ellen.spertus@gmail.com) +""" + +import argparse +import codecs +import json +import os +import re +from common import write_files + + +_INPUT_DEF_PATTERN = re.compile("""Blockly.Msg.(\w*)\s*=\s*'([^']*)';?$""") + +_INPUT_SYN_PATTERN = re.compile( + """Blockly.Msg.(\w*)\s*=\s*Blockly.Msg.(\w*);""") + +def main(): + # Set up argument parser. + parser = argparse.ArgumentParser(description='Create translation files.') + parser.add_argument( + '--author', + default='Ellen Spertus ', + help='name and email address of contact for translators') + parser.add_argument('--lang', default='en', + help='ISO 639-1 source language code') + parser.add_argument('--output_dir', default='json', + help='relative directory for output files') + parser.add_argument('--input_file', default='messages.js', + help='input file') + parser.add_argument('--quiet', action='store_true', default=False, + help='only display warnings, not routine info') + args = parser.parse_args() + if (not args.output_dir.endswith(os.path.sep)): + args.output_dir += os.path.sep + + # Read and parse input file. + results = [] + synonyms = {} + description = '' + infile = codecs.open(args.input_file, 'r', 'utf-8') + for line in infile: + if line.startswith('///'): + if description: + description = description + ' ' + line[3:].strip() + else: + description = line[3:].strip() + else: + match = _INPUT_DEF_PATTERN.match(line) + if match: + result = {} + result['meaning'] = match.group(1) + result['source'] = match.group(2) + if not description: + print('Warning: No description for ' + result['meaning']) + result['description'] = description + description = '' + results.append(result) + else: + match = _INPUT_SYN_PATTERN.match(line) + if match: + if description: + print('Warning: Description preceding definition of synonym {0}.'. + format(match.group(1))) + description = '' + synonyms[match.group(1)] = match.group(2) + infile.close() + + # Create .json, keys.json, and qqq.json. + write_files(args.author, args.lang, args.output_dir, results, False) + + # Create synonyms.json. + synonym_file_name = os.path.join(os.curdir, args.output_dir, 'synonyms.json') + with open(synonym_file_name, 'w') as outfile: + json.dump(synonyms, outfile) + if not args.quiet: + print("Wrote {0} synonym pairs to {1}.".format( + len(synonyms), synonym_file_name)) + + +if __name__ == '__main__': + main() diff --git a/i18n/json_to_js.py b/i18n/json_to_js.py new file mode 100755 index 000000000..89de87f7d --- /dev/null +++ b/i18n/json_to_js.py @@ -0,0 +1,191 @@ +#!/usr/bin/python + +# Converts .json files into .js files for use within Blockly apps. +# +# Copyright 2013 Google Inc. +# http://blockly.googlecode.com/ +# +# 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. + +import argparse +import codecs # for codecs.open(..., 'utf-8') +import json # for json.load() +import os # for os.path() +import subprocess # for subprocess.check_call() +from common import InputError +from common import insert_breaks +from common import read_json_file + + +# Store parsed command-line arguments in global variable. +args = None + + +def _create_xlf(target_lang): + """Creates a .xlf file for Soy. + + Args: + target_lang: The ISO 639 language code for the target language. + This is used in the name of the file and in the metadata. + + Returns: + A pointer to a file to which the metadata has been written. + + Raises: + IOError: An error occurred while opening or writing the file. + """ + filename = os.path.join(os.curdir, args.output_dir, target_lang + '.xlf') + out_file = codecs.open(filename, 'w', 'utf-8') + out_file.write(""" + + + """.format(args.source_lang, target_lang)) + return out_file + + +def _close_xlf(xlf_file): + """Closes a .xlf file created with create_xlf(). + + This includes writing the terminating XML. + + Args: + xlf_file: A pointer to a file created by _create_xlf(). + + Raises: + IOError: An error occurred while writing to or closing the file. + """ + xlf_file.write(""" + + + +""") + xlf_file.close() + + +def _process_file(path_to_json, target_lang, key_dict): + """Creates an .xlf file corresponding to the specified .json input file. + + The name of the input file must be target_lang followed by '.json'. + The name of the output file will be target_lang followed by '.js'. + + Args: + path_to_json: Path to the directory of xx.json files. + target_lang: A IETF language code (RFC 4646), such as 'es' or 'pt-br'. + key_dict: Dictionary mapping Blockly keys (e.g., Maze.turnLeft) to + Closure keys (hash numbers). + + Raises: + IOError: An I/O error occurred with an input or output file. + InputError: Input JSON could not be parsed. + KeyError: Key found in input file but not in key file. + """ + keyfile = os.path.join(path_to_json, target_lang + '.json') + j = read_json_file(keyfile) + out_file = _create_xlf(target_lang) + for key in j: + if key != '@metadata': + try: + identifier = key_dict[key] + except KeyError, e: + print('Key "%s" is in %s but not in %s' % + (key, keyfile, args.key_file)) + raise e + target = j.get(key) + # Only insert line breaks for tooltips. + if key.lower().find('tooltip') != -1: + target = insert_breaks( + j.get(key), args.min_length, args.max_length) + out_file.write(u""" + + {1} + """.format(identifier, target)) + _close_xlf(out_file) + + +def main(): + """Parses arguments and iterates over files.""" + + # Set up argument parser. + parser = argparse.ArgumentParser(description='Convert JSON files to JS.') + parser.add_argument('--source_lang', default='en', + help='ISO 639-1 source language code') + parser.add_argument('--output_dir', default='generated', + help='relative directory for output files') + parser.add_argument('--key_file', default='json' + os.path.sep + 'keys.json', + help='relative path to input keys file') + parser.add_argument('--template', default='template.soy') + parser.add_argument('--min_length', default=30, + help='minimum line length (not counting last line)') + parser.add_argument('--max_length', default=50, + help='maximum line length (not guaranteed)') + parser.add_argument('--path_to_jar', + default='..' + os.path.sep + 'apps' + os.path.sep + + '_soy', + help='relative path from working directory to ' + 'SoyToJsSrcCompiler.jar') + parser.add_argument('files', nargs='+', help='input files') + + # Initialize global variables. + global args + args = parser.parse_args() + + # Make sure output_dir ends with slash. + if (not args.output_dir.endswith(os.path.sep)): + args.output_dir += os.path.sep + + # Read in keys.json, mapping descriptions (e.g., Maze.turnLeft) to + # Closure keys (long hash numbers). + key_file = open(args.key_file) + key_dict = json.load(key_file) + key_file.close() + + # Process each input file. + print('Creating .xlf files...') + processed_langs = [] + for arg_file in args.files: + (path_to_json, filename) = os.path.split(arg_file) + if not filename.endswith('.json'): + raise InputError(filename, 'filenames must end with ".json"') + target_lang = filename[:filename.index('.')] + if not target_lang in ('qqq', 'keys'): + processed_langs.append(target_lang) + _process_file(path_to_json, target_lang, key_dict) + + # Output command line for Closure compiler. + if processed_langs: + print('Creating .js files...') + processed_lang_list = ','.join(processed_langs) + subprocess.check_call([ + 'java', + '-jar', os.path.join(args.path_to_jar, 'SoyToJsSrcCompiler.jar'), + '--locales', processed_lang_list, + '--messageFilePathFormat', args.output_dir + '{LOCALE}.xlf', + '--outputPathFormat', args.output_dir + '{LOCALE}.js', + '--srcs', args.template]) + if len(processed_langs) == 1: + print('Created ' + processed_lang_list + '.js in ' + args.output_dir) + else: + print('Created {' + processed_lang_list + '}.js in ' + args.output_dir) + command = ['rm'] + command.extend(map(lambda s: args.output_dir + s + '.xlf', + processed_langs)) + subprocess.check_call(command) + print('Removed .xlf files.') + + +if __name__ == '__main__': + main() diff --git a/i18n/status.py b/i18n/status.py new file mode 100755 index 000000000..8a0d1f797 --- /dev/null +++ b/i18n/status.py @@ -0,0 +1,209 @@ +#!/usr/bin/python + +# Gives the translation status of the specified apps and languages. +# +# Copyright 2013 Google Inc. +# http://blockly.googlecode.com/ +# +# 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. + +"""Produce a table showing the translation status of each app by language. + +@author Ellen Spertus (ellen.spertus@gmail.com) +""" + +import argparse +import os +from common import read_json_file + +# Bogus language name representing all messages defined. +TOTAL = 'qqq' + +# List of key prefixes, which are app names, except for 'Apps', which +# has common messages. It is included here for convenience. +APPS = ['Apps', 'Code', 'Graph', 'Maze', 'Plane', 'Puzzle', 'Turtle'] + + +def get_prefix(s): + """Gets the portion of a string before the first period. + + Args: + s: A string. + + Returns: + The portion of the string before the first period, or the entire + string if it does not contain a period. + """ + return s.split('.')[0] + + +def get_prefix_count(prefix, arr): + """Counts how many strings in the array start with the prefix. + + Args: + prefix: The prefix string. + arr: An array of strings. + Returns: + The number of strings in arr starting with prefix. + """ + # This code was chosen for its elegance not its efficiency. + return len([elt for elt in arr if elt.startswith(prefix)]) + + +def output_as_html(messages, verbose): + """Outputs the given prefix counts and percentages as HTML. + + Specifically, a sortable HTML table is produced, where the app names + are column headers, and one language is output per row. Entries + are color-coded based on the percent completeness. + + Args: + messages: A dictionary of dictionaries, where the outer keys are language + codes used by translatewiki (generally, ISO 639 language codes) or + the string TOTAL, used to indicate the total set of messages. The + inner dictionary makes message keys to values in that language. + verbose: Whether to list missing keys. + """ + def generate_language_url(lang): + return 'https://translatewiki.net/wiki/Special:SupportedLanguages#' + lang + + def generate_number_as_percent(num, total, tag): + percent = num * 100 / total + if percent == 100: + color = 'green' + elif percent >= 90: + color = 'orange' + elif percent >= 60: + color = 'black' + else: + color = 'gray' + s = '{1} ({2}%)'.format(color, num, percent) + if verbose and percent < 100: + return '{1}'.format(tag, s) + else: + return s + + print('Blockly app translation status') + print("") + print('') + print('') + for lang in messages: + if lang != TOTAL: + print(''.format( + lang, generate_language_url(lang))) + for app in APPS: + print '' + print('') + print('
    Language' + + ''.join(APPS) + '
    {0}' + print(generate_number_as_percent( + get_prefix_count(app, messages[lang]), + get_prefix_count(app, messages[TOTAL]), + (lang + app))) + print '
    ALL') + print(''.join([str(get_prefix_count(app, TOTAL)) for app in APPS])) + print('
    ') + + if verbose: + for lang in messages: + if lang != TOTAL: + for app in APPS: + if (get_prefix_count(app, messages[lang]) < + get_prefix_count(app, messages[TOTAL])): + print('
    {1} ({0})'. + format(lang, app, generate_language_url(lang))) + print(' missing: ') + print(', '.join( + [key for key in messages[TOTAL] if + key.startswith(app) and key not in messages[lang]])) + print('

    ') + print('') + + +def output_as_text(messages, verbose): + """Outputs the given prefix counts and percentages as text. + + Args: + messages: A dictionary of dictionaries, where the outer keys are language + codes used by translatewiki (generally, ISO 639 language codes) or + the string TOTAL, used to indicate the total set of messages. The + inner dictionary makes message keys to values in that language. + verbose: Whether to list missing keys. + """ + def generate_number_as_percent(num, total): + return '{0} ({1}%)'.format(num, num * 100 / total) + MAX_WIDTH = len('999 (100%)') + 1 + FIELD_STRING = '{0: <' + str(MAX_WIDTH) + '}' + print(FIELD_STRING.format('Language') + ''.join( + [FIELD_STRING.format(app) for app in APPS])) + print(('-' * (MAX_WIDTH - 1) + ' ') * (len(APPS) + 1)) + for lang in messages: + if lang != TOTAL: + print(FIELD_STRING.format(lang) + + ''.join([FIELD_STRING.format(generate_number_as_percent( + get_prefix_count(app, messages[lang]), + get_prefix_count(app, messages[TOTAL]))) + for app in APPS])) + print(FIELD_STRING.format(TOTAL) + + ''.join( + [FIELD_STRING.format(get_prefix_count(app, messages[TOTAL])) + for app in APPS])) + if verbose: + for lang in messages: + if lang != TOTAL: + for app in APPS: + missing = [key for key in messages[TOTAL] + if key.startswith(app) and key not in messages[lang]] + print('{0} {1}: Missing: {2}'.format( + app.upper(), lang, (', '.join(missing) if missing else 'none'))) + + +def main(): + """Processes input files and outputs results in specified format. + """ + # Argument parsing. + parser = argparse.ArgumentParser( + description='Display translation status by app and language.') + parser.add_argument('--key_file', default='json' + os.path.sep + 'keys.json', + help='file with complete list of keys.') + parser.add_argument('--output', default='text', choices=['text', 'html'], + help='output format') + parser.add_argument('--verbose', action='store_true', default=False, + help='whether to indicate which messages were translated') + parser.add_argument('--app', default=None, choices=APPS, + help='if set, only consider the specified app (prefix).') + parser.add_argument('lang_files', nargs='+', + help='names of JSON files to examine') + args = parser.parse_args() + + # Read in JSON files. + messages = {} # A dictionary of dictionaries. + messages[TOTAL] = read_json_file(args.key_file) + for lang_file in args.lang_files: + prefix = get_prefix(os.path.split(lang_file)[1]) + # Skip non-language files. + if prefix not in ['qqq', 'keys']: + messages[prefix] = read_json_file(lang_file) + + # Output results. + if args.output == 'text': + output_as_text(messages, args.verbose) + elif args.output == 'html': + output_as_html(messages, args.verbose) + else: + print('No output?!') + + +if __name__ == '__main__': + main() diff --git a/i18n/tests.py b/i18n/tests.py new file mode 100644 index 000000000..fe818697b --- /dev/null +++ b/i18n/tests.py @@ -0,0 +1,47 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Tests of i18n scripts. +# +# Copyright 2013 Google Inc. +# http://blockly.googlecode.com/ +# +# 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. + +import common +import re +import unittest + +class TestSequenceFunctions(unittest.TestCase): + def test_insert_breaks(self): + spaces = re.compile(r'\s+|\\n') + def contains_all_chars(orig, result): + return re.sub(spaces, '', orig) == re.sub(spaces, '', result) + + sentences = [u'Quay Pegman qua bên trái hoặc bên phải 90 độ.', + u'Foo bar baz this is english that is okay bye.', + u'If there is a path in the specified direction, \nthen ' + + u'do some actions.', + u'If there is a path in the specified direction, then do ' + + u'the first block of actions. Otherwise, do the second ' + + u'block of actions.'] + for sentence in sentences: + output = common.insert_breaks(sentence, 30, 50) + self.assert_(contains_all_chars(sentence, output), + u'Mismatch between:\n{0}\n{1}'.format( + re.sub(spaces, '', sentence), + re.sub(spaces, '', output))) + + +if __name__ == '__main__': + unittest.main() diff --git a/i18n/xliff_to_json.py b/i18n/xliff_to_json.py new file mode 100755 index 000000000..0a701fe9d --- /dev/null +++ b/i18n/xliff_to_json.py @@ -0,0 +1,230 @@ +#!/usr/bin/python + +# Converts .xlf files into .json files for use at http://translatewiki.net. +# +# Copyright 2013 Google Inc. +# http://blockly.googlecode.com/ +# +# 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. + +import argparse +import os +import re +import subprocess +import sys +from xml.dom import minidom +from common import InputError +from common import write_files + +# Global variables +args = None # parsed command-line arguments + + +def _parse_trans_unit(trans_unit): + """Converts a trans-unit XML node into a more convenient dictionary format. + + Args: + trans_unit: An XML representation of a .xlf translation unit. + + Returns: + A dictionary with useful information about the translation unit. + The returned dictionary is guaranteed to have an entry for 'key' and + may have entries for 'source', 'target', 'description', and 'meaning' + if present in the argument. + + Raises: + InputError: A required field was not present. + """ + + def get_value(tag_name): + elts = trans_unit.getElementsByTagName(tag_name) + if not elts: + return None + elif len(elts) == 1: + return ''.join([child.toxml() for child in elts[0].childNodes]) + else: + raise InputError('', 'Unable to extract ' + tag_name) + + result = {} + key = trans_unit.getAttribute('id') + if not key: + raise InputError('', 'id attribute not found') + result['key'] = key + + # Get source and target, if present. + try: + result['source'] = get_value('source') + result['target'] = get_value('target') + except InputError, e: + raise InputError(key, e.msg) + + # Get notes, using the from value as key and the data as value. + notes = trans_unit.getElementsByTagName('note') + for note in notes: + from_value = note.getAttribute('from') + if from_value and len(note.childNodes) == 1: + result[from_value] = note.childNodes[0].data + else: + raise InputError(key, 'Unable to extract ' + from_value) + + return result + + +def _process_file(filename): + """Builds list of translation units from input file. + + Each translation unit in the input file includes: + - an id (opaquely generated by Soy) + - the Blockly name for the message + - the text in the source language (generally English) + - a description for the translator + + The Soy and Blockly ids are joined with a hyphen and serve as the + keys in both output files. The value is the corresponding text (in the + .json file) or the description (in the qqq.json file). + + Args: + filename: The name of an .xlf file produced by Closure. + + Raises: + IOError: An I/O error occurred with an input or output file. + InputError: The input file could not be parsed or lacked required + fields. + + Returns: + A list of dictionaries produced by parse_trans_unit(). + """ + try: + results = [] # list of dictionaries (return value) + names = [] # list of names of encountered keys (local variable) + try: + parsed_xml = minidom.parse(filename) + except IOError: + # Don't get caught by below handler + raise + except Exception, e: + print + raise InputError(filename, str(e)) + + # Make sure needed fields are present and non-empty. + for trans_unit in parsed_xml.getElementsByTagName('trans-unit'): + unit = _parse_trans_unit(trans_unit) + for key in ['description', 'meaning', 'source']: + if not key in unit or not unit[key]: + raise InputError(filename + ':' + unit['key'], + key + ' not found') + if unit['description'].lower() == 'ibid': + if unit['meaning'] not in names: + # If the term has not already been described, the use of 'ibid' + # is an error. + raise InputError( + filename, + 'First encountered definition of: ' + unit['meaning'] + + ' has definition: ' + unit['description'] + + '. This error can occur if the definition was not' + + ' provided on the first appearance of the message' + + ' or if the source (English-language) messages differ.') + else: + # If term has already been described, 'ibid' was used correctly, + # and we output nothing. + pass + else: + if unit['meaning'] in names: + raise InputError(filename, + 'Second definition of: ' + unit['meaning']) + names.append(unit['meaning']) + results.append(unit) + + return results + except IOError, e: + print 'Error with file {0}: {1}'.format(filename, e.strerror) + sys.exit(1) + + +def sort_units(units, templates): + """Sorts the translation units by their definition order in the template. + + Args: + units: A list of dictionaries produced by parse_trans_unit() + that have a non-empty value for the key 'meaning'. + templates: A string containing the Soy templates in which each of + the units' meanings is defined. + + Returns: + A new list of translation units, sorted by the order in which + their meaning is defined in the templates. + + Raises: + InputError: If a meaning definition cannot be found in the + templates. + """ + def key_function(unit): + match = re.search( + '\\smeaning\\s*=\\s*"{0}"\\s'.format(unit['meaning']), + templates) + if match: + return match.start() + else: + raise InputError(args.templates, + 'msg definition for meaning not found: ' + + unit['meaning']) + return sorted(units, key=key_function) + + +def main(): + """Parses arguments and processes the specified file. + + Raises: + IOError: An I/O error occurred with an input or output file. + InputError: Input files lacked required fields. + """ + # Set up argument parser. + parser = argparse.ArgumentParser(description='Create translation files.') + parser.add_argument( + '--author', + default='Ellen Spertus ', + help='name and email address of contact for translators') + parser.add_argument('--lang', default='en', + help='ISO 639-1 source language code') + parser.add_argument('--output_dir', default='json', + help='relative directory for output files') + parser.add_argument('--xlf', help='file containing xlf definitions') + parser.add_argument('--templates', default=['template.soy'], nargs='+', + help='relative path to Soy templates ' + '(used for ordering messages)') + global args + args = parser.parse_args() + + # Make sure output_dir ends with slash. + if (not args.output_dir.endswith(os.path.sep)): + args.output_dir += os.path.sep + + # Process the input file, and sort the entries. + units = _process_file(args.xlf) + files = [] + for filename in args.templates: + with open(filename) as myfile: + files.append(' '.join(line.strip() for line in myfile)) + sorted_units = sort_units(units, ' '.join(files)) + + # Write the output files. + write_files(args.author, args.lang, args.output_dir, sorted_units, True) + + # Delete the input .xlf file. + command = ['rm', args.xlf] + subprocess.check_call(command) + print('Removed ' + args.xlf) + + +if __name__ == '__main__': + main() diff --git a/javascript_compressed.js b/javascript_compressed.js new file mode 100644 index 000000000..9ae70acdb --- /dev/null +++ b/javascript_compressed.js @@ -0,0 +1,86 @@ +// Do not edit this file; automatically generated by build.py. +"use strict"; + +Blockly.JavaScript=new Blockly.Generator("JavaScript");Blockly.JavaScript.addReservedWords("Blockly,break,case,catch,continue,debugger,default,delete,do,else,finally,for,function,if,in,instanceof,new,return,switch,this,throw,try,typeof,var,void,while,with,class,enum,export,extends,import,super,implements,interface,let,package,private,protected,public,static,yield,const,null,true,false,Array,ArrayBuffer,Boolean,Date,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Error,eval,EvalError,Float32Array,Float64Array,Function,Infinity,Int16Array,Int32Array,Int8Array,isFinite,isNaN,Iterator,JSON,Math,NaN,Number,Object,parseFloat,parseInt,RangeError,ReferenceError,RegExp,StopIteration,String,SyntaxError,TypeError,Uint16Array,Uint32Array,Uint8Array,Uint8ClampedArray,undefined,uneval,URIError,applicationCache,closed,Components,content,_content,controllers,crypto,defaultStatus,dialogArguments,directories,document,frameElement,frames,fullScreen,globalStorage,history,innerHeight,innerWidth,length,location,locationbar,localStorage,menubar,messageManager,mozAnimationStartTime,mozInnerScreenX,mozInnerScreenY,mozPaintCount,name,navigator,opener,outerHeight,outerWidth,pageXOffset,pageYOffset,parent,performance,personalbar,pkcs11,returnValue,screen,screenX,screenY,scrollbars,scrollMaxX,scrollMaxY,scrollX,scrollY,self,sessionStorage,sidebar,status,statusbar,toolbar,top,URL,window,addEventListener,alert,atob,back,blur,btoa,captureEvents,clearImmediate,clearInterval,clearTimeout,close,confirm,disableExternalCapture,dispatchEvent,dump,enableExternalCapture,escape,find,focus,forward,GeckoActiveXObject,getAttention,getAttentionWithCycleCount,getComputedStyle,getSelection,home,matchMedia,maximize,minimize,moveBy,moveTo,mozRequestAnimationFrame,open,openDialog,postMessage,print,prompt,QueryInterface,releaseEvents,removeEventListener,resizeBy,resizeTo,restore,routeEvent,scroll,scrollBy,scrollByLines,scrollByPages,scrollTo,setCursor,setImmediate,setInterval,setResizable,setTimeout,showModalDialog,sizeToContent,stop,unescape,updateCommands,XPCNativeWrapper,XPCSafeJSObjectWrapper,onabort,onbeforeunload,onblur,onchange,onclick,onclose,oncontextmenu,ondevicemotion,ondeviceorientation,ondragdrop,onerror,onfocus,onhashchange,onkeydown,onkeypress,onkeyup,onload,onmousedown,onmousemove,onmouseout,onmouseover,onmouseup,onmozbeforepaint,onpaint,onpopstate,onreset,onresize,onscroll,onselect,onsubmit,onunload,onpageshow,onpagehide,Image,Option,Worker,Event,Range,File,FileReader,Blob,BlobBuilder,Attr,CDATASection,CharacterData,Comment,console,DocumentFragment,DocumentType,DomConfiguration,DOMError,DOMErrorHandler,DOMException,DOMImplementation,DOMImplementationList,DOMImplementationRegistry,DOMImplementationSource,DOMLocator,DOMObject,DOMString,DOMStringList,DOMTimeStamp,DOMUserData,Entity,EntityReference,MediaQueryList,MediaQueryListListener,NameList,NamedNodeMap,Node,NodeFilter,NodeIterator,NodeList,Notation,Plugin,PluginArray,ProcessingInstruction,SharedWorker,Text,TimeRanges,Treewalker,TypeInfo,UserDataHandler,Worker,WorkerGlobalScope,HTMLDocument,HTMLElement,HTMLAnchorElement,HTMLAppletElement,HTMLAudioElement,HTMLAreaElement,HTMLBaseElement,HTMLBaseFontElement,HTMLBodyElement,HTMLBRElement,HTMLButtonElement,HTMLCanvasElement,HTMLDirectoryElement,HTMLDivElement,HTMLDListElement,HTMLEmbedElement,HTMLFieldSetElement,HTMLFontElement,HTMLFormElement,HTMLFrameElement,HTMLFrameSetElement,HTMLHeadElement,HTMLHeadingElement,HTMLHtmlElement,HTMLHRElement,HTMLIFrameElement,HTMLImageElement,HTMLInputElement,HTMLKeygenElement,HTMLLabelElement,HTMLLIElement,HTMLLinkElement,HTMLMapElement,HTMLMenuElement,HTMLMetaElement,HTMLModElement,HTMLObjectElement,HTMLOListElement,HTMLOptGroupElement,HTMLOptionElement,HTMLOutputElement,HTMLParagraphElement,HTMLParamElement,HTMLPreElement,HTMLQuoteElement,HTMLScriptElement,HTMLSelectElement,HTMLSourceElement,HTMLSpanElement,HTMLStyleElement,HTMLTableElement,HTMLTableCaptionElement,HTMLTableCellElement,HTMLTableDataCellElement,HTMLTableHeaderCellElement,HTMLTableColElement,HTMLTableRowElement,HTMLTableSectionElement,HTMLTextAreaElement,HTMLTimeElement,HTMLTitleElement,HTMLTrackElement,HTMLUListElement,HTMLUnknownElement,HTMLVideoElement,HTMLCanvasElement,CanvasRenderingContext2D,CanvasGradient,CanvasPattern,TextMetrics,ImageData,CanvasPixelArray,HTMLAudioElement,HTMLVideoElement,NotifyAudioAvailableEvent,HTMLCollection,HTMLAllCollection,HTMLFormControlsCollection,HTMLOptionsCollection,HTMLPropertiesCollection,DOMTokenList,DOMSettableTokenList,DOMStringMap,RadioNodeList,SVGDocument,SVGElement,SVGAElement,SVGAltGlyphElement,SVGAltGlyphDefElement,SVGAltGlyphItemElement,SVGAnimationElement,SVGAnimateElement,SVGAnimateColorElement,SVGAnimateMotionElement,SVGAnimateTransformElement,SVGSetElement,SVGCircleElement,SVGClipPathElement,SVGColorProfileElement,SVGCursorElement,SVGDefsElement,SVGDescElement,SVGEllipseElement,SVGFilterElement,SVGFilterPrimitiveStandardAttributes,SVGFEBlendElement,SVGFEColorMatrixElement,SVGFEComponentTransferElement,SVGFECompositeElement,SVGFEConvolveMatrixElement,SVGFEDiffuseLightingElement,SVGFEDisplacementMapElement,SVGFEDistantLightElement,SVGFEFloodElement,SVGFEGaussianBlurElement,SVGFEImageElement,SVGFEMergeElement,SVGFEMergeNodeElement,SVGFEMorphologyElement,SVGFEOffsetElement,SVGFEPointLightElement,SVGFESpecularLightingElement,SVGFESpotLightElement,SVGFETileElement,SVGFETurbulenceElement,SVGComponentTransferFunctionElement,SVGFEFuncRElement,SVGFEFuncGElement,SVGFEFuncBElement,SVGFEFuncAElement,SVGFontElement,SVGFontFaceElement,SVGFontFaceFormatElement,SVGFontFaceNameElement,SVGFontFaceSrcElement,SVGFontFaceUriElement,SVGForeignObjectElement,SVGGElement,SVGGlyphElement,SVGGlyphRefElement,SVGGradientElement,SVGLinearGradientElement,SVGRadialGradientElement,SVGHKernElement,SVGImageElement,SVGLineElement,SVGMarkerElement,SVGMaskElement,SVGMetadataElement,SVGMissingGlyphElement,SVGMPathElement,SVGPathElement,SVGPatternElement,SVGPolylineElement,SVGPolygonElement,SVGRectElement,SVGScriptElement,SVGStopElement,SVGStyleElement,SVGSVGElement,SVGSwitchElement,SVGSymbolElement,SVGTextElement,SVGTextPathElement,SVGTitleElement,SVGTRefElement,SVGTSpanElement,SVGUseElement,SVGViewElement,SVGVKernElement,SVGAngle,SVGColor,SVGICCColor,SVGElementInstance,SVGElementInstanceList,SVGLength,SVGLengthList,SVGMatrix,SVGNumber,SVGNumberList,SVGPaint,SVGPoint,SVGPointList,SVGPreserveAspectRatio,SVGRect,SVGStringList,SVGTransform,SVGTransformList,SVGAnimatedAngle,SVGAnimatedBoolean,SVGAnimatedEnumeration,SVGAnimatedInteger,SVGAnimatedLength,SVGAnimatedLengthList,SVGAnimatedNumber,SVGAnimatedNumberList,SVGAnimatedPreserveAspectRatio,SVGAnimatedRect,SVGAnimatedString,SVGAnimatedTransformList,SVGPathSegList,SVGPathSeg,SVGPathSegArcAbs,SVGPathSegArcRel,SVGPathSegClosePath,SVGPathSegCurvetoCubicAbs,SVGPathSegCurvetoCubicRel,SVGPathSegCurvetoCubicSmoothAbs,SVGPathSegCurvetoCubicSmoothRel,SVGPathSegCurvetoQuadraticAbs,SVGPathSegCurvetoQuadraticRel,SVGPathSegCurvetoQuadraticSmoothAbs,SVGPathSegCurvetoQuadraticSmoothRel,SVGPathSegLinetoAbs,SVGPathSegLinetoHorizontalAbs,SVGPathSegLinetoHorizontalRel,SVGPathSegLinetoRel,SVGPathSegLinetoVerticalAbs,SVGPathSegLinetoVerticalRel,SVGPathSegMovetoAbs,SVGPathSegMovetoRel,ElementTimeControl,TimeEvent,SVGAnimatedPathData,SVGAnimatedPoints,SVGColorProfileRule,SVGCSSRule,SVGExternalResourcesRequired,SVGFitToViewBox,SVGLangSpace,SVGLocatable,SVGRenderingIntent,SVGStylable,SVGTests,SVGTextContentElement,SVGTextPositioningElement,SVGTransformable,SVGUnitTypes,SVGURIReference,SVGViewSpec,SVGZoomAndPan"); +Blockly.JavaScript.ORDER_ATOMIC=0;Blockly.JavaScript.ORDER_MEMBER=1;Blockly.JavaScript.ORDER_NEW=1;Blockly.JavaScript.ORDER_FUNCTION_CALL=2;Blockly.JavaScript.ORDER_INCREMENT=3;Blockly.JavaScript.ORDER_DECREMENT=3;Blockly.JavaScript.ORDER_LOGICAL_NOT=4;Blockly.JavaScript.ORDER_BITWISE_NOT=4;Blockly.JavaScript.ORDER_UNARY_PLUS=4;Blockly.JavaScript.ORDER_UNARY_NEGATION=4;Blockly.JavaScript.ORDER_TYPEOF=4;Blockly.JavaScript.ORDER_VOID=4;Blockly.JavaScript.ORDER_DELETE=4; +Blockly.JavaScript.ORDER_MULTIPLICATION=5;Blockly.JavaScript.ORDER_DIVISION=5;Blockly.JavaScript.ORDER_MODULUS=5;Blockly.JavaScript.ORDER_ADDITION=6;Blockly.JavaScript.ORDER_SUBTRACTION=6;Blockly.JavaScript.ORDER_BITWISE_SHIFT=7;Blockly.JavaScript.ORDER_RELATIONAL=8;Blockly.JavaScript.ORDER_IN=8;Blockly.JavaScript.ORDER_INSTANCEOF=8;Blockly.JavaScript.ORDER_EQUALITY=9;Blockly.JavaScript.ORDER_BITWISE_AND=10;Blockly.JavaScript.ORDER_BITWISE_XOR=11;Blockly.JavaScript.ORDER_BITWISE_OR=12; +Blockly.JavaScript.ORDER_LOGICAL_AND=13;Blockly.JavaScript.ORDER_LOGICAL_OR=14;Blockly.JavaScript.ORDER_CONDITIONAL=15;Blockly.JavaScript.ORDER_ASSIGNMENT=16;Blockly.JavaScript.ORDER_COMMA=17;Blockly.JavaScript.ORDER_NONE=99;Blockly.JavaScript.INFINITE_LOOP_TRAP=null; +Blockly.JavaScript.init=function(){Blockly.JavaScript.definitions_=Object.create(null);if(Blockly.Variables){Blockly.JavaScript.variableDB_?Blockly.JavaScript.variableDB_.reset():Blockly.JavaScript.variableDB_=new Blockly.Names(Blockly.JavaScript.RESERVED_WORDS_);for(var a=[],b=Blockly.Variables.allVariables(),c=0;c 0";break;case "NEGATIVE":d=b+" < 0";break;case "DIVISIBLE_BY":a=Blockly.JavaScript.valueToCode(a,"DIVISOR",Blockly.JavaScript.ORDER_MODULUS)||"0",d=b+" % "+a+" == 0"}return[d, +Blockly.JavaScript.ORDER_EQUALITY]};Blockly.JavaScript.math_change=function(a){var b=Blockly.JavaScript.valueToCode(a,"DELTA",Blockly.JavaScript.ORDER_ADDITION)||"0";a=Blockly.JavaScript.variableDB_.getName(a.getTitleValue("VAR"),Blockly.Variables.NAME_TYPE);return a+" = (typeof "+a+" == 'number' ? "+a+" : 0) + "+b+";\n"};Blockly.JavaScript.math_round=Blockly.JavaScript.math_single;Blockly.JavaScript.math_trig=Blockly.JavaScript.math_single; +Blockly.JavaScript.math_on_list=function(a){var b=a.getTitleValue("OP");switch(b){case "SUM":a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_MEMBER)||"[]";a+=".reduce(function(x, y) {return x + y;})";break;case "MIN":a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_COMMA)||"[]";a="Math.min.apply(null, "+a+")";break;case "MAX":a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_COMMA)||"[]";a="Math.max.apply(null, "+a+")";break;case "AVERAGE":if(!Blockly.JavaScript.definitions_.math_mean){var c= +Blockly.JavaScript.variableDB_.getDistinctName("math_mean",Blockly.Generator.NAME_TYPE);Blockly.JavaScript.math_on_list.math_mean=c;b=[];b.push("function "+c+"(myList) {");b.push(" return myList.reduce(function(x, y) {return x + y;}) / myList.length;");b.push("}");Blockly.JavaScript.definitions_.math_mean=b.join("\n")}a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_NONE)||"[]";a=Blockly.JavaScript.math_on_list.math_mean+"("+a+")";break;case "MEDIAN":Blockly.JavaScript.definitions_.math_median|| +(c=Blockly.JavaScript.variableDB_.getDistinctName("math_median",Blockly.Generator.NAME_TYPE),Blockly.JavaScript.math_on_list.math_median=c,b=[],b.push("function "+c+"(myList) {"),b.push(" var localList = myList.filter(function (x) {return typeof x == 'number';});"),b.push(" if (!localList.length) return null;"),b.push(" localList.sort(function(a, b) {return b - a;});"),b.push(" if (localList.length % 2 == 0) {"),b.push(" return (localList[localList.length / 2 - 1] + localList[localList.length / 2]) / 2;"), +b.push(" } else {"),b.push(" return localList[(localList.length - 1) / 2];"),b.push(" }"),b.push("}"),Blockly.JavaScript.definitions_.math_median=b.join("\n"));a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_NONE)||"[]";a=Blockly.JavaScript.math_on_list.math_median+"("+a+")";break;case "MODE":Blockly.JavaScript.definitions_.math_modes||(c=Blockly.JavaScript.variableDB_.getDistinctName("math_modes",Blockly.Generator.NAME_TYPE),Blockly.JavaScript.math_on_list.math_modes=c,b= +[],b.push("function "+c+"(values) {"),b.push(" var modes = [];"),b.push(" var counts = [];"),b.push(" var maxCount = 0;"),b.push(" for (var i = 0; i < values.length; i++) {"),b.push(" var value = values[i];"),b.push(" var found = false;"),b.push(" var thisCount;"),b.push(" for (var j = 0; j < counts.length; j++) {"),b.push(" if (counts[j][0] === value) {"),b.push(" thisCount = ++counts[j][1];"),b.push(" found = true;"),b.push(" break;"),b.push(" }"), +b.push(" }"),b.push(" if (!found) {"),b.push(" counts.push([value, 1]);"),b.push(" thisCount = 1;"),b.push(" }"),b.push(" maxCount = Math.max(thisCount, maxCount);"),b.push(" }"),b.push(" for (var j = 0; j < counts.length; j++) {"),b.push(" if (counts[j][1] == maxCount) {"),b.push(" modes.push(counts[j][0]);"),b.push(" }"),b.push(" }"),b.push(" return modes;"),b.push("}"),Blockly.JavaScript.definitions_.math_modes=b.join("\n"));a=Blockly.JavaScript.valueToCode(a, +"LIST",Blockly.JavaScript.ORDER_NONE)||"[]";a=Blockly.JavaScript.math_on_list.math_modes+"("+a+")";break;case "STD_DEV":Blockly.JavaScript.definitions_.math_standard_deviation||(c=Blockly.JavaScript.variableDB_.getDistinctName("math_standard_deviation",Blockly.Generator.NAME_TYPE),Blockly.JavaScript.math_on_list.math_standard_deviation=c,b=[],b.push("function "+c+"(numbers) {"),b.push(" var n = numbers.length;"),b.push(" if (!n) return null;"),b.push(" var mean = numbers.reduce(function(x, y) {return x + y;}) / n;"), +b.push(" var variance = 0;"),b.push(" for (var j = 0; j < n; j++) {"),b.push(" variance += Math.pow(numbers[j] - mean, 2);"),b.push(" }"),b.push(" variance = variance / n;"),b.push(" return Math.sqrt(variance);"),b.push("}"),Blockly.JavaScript.definitions_.math_standard_deviation=b.join("\n"));a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_NONE)||"[]";a=Blockly.JavaScript.math_on_list.math_standard_deviation+"("+a+")";break;case "RANDOM":Blockly.JavaScript.definitions_.math_random_item|| +(c=Blockly.JavaScript.variableDB_.getDistinctName("math_random_item",Blockly.Generator.NAME_TYPE),Blockly.JavaScript.math_on_list.math_random_item=c,b=[],b.push("function "+c+"(list) {"),b.push(" var x = Math.floor(Math.random() * list.length);"),b.push(" return list[x];"),b.push("}"),Blockly.JavaScript.definitions_.math_random_item=b.join("\n"));a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_NONE)||"[]";a=Blockly.JavaScript.math_on_list.math_random_item+"("+a+")";break;default:throw"Unknown operator: "+ +b;}return[a,Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.math_modulo=function(a){var b=Blockly.JavaScript.valueToCode(a,"DIVIDEND",Blockly.JavaScript.ORDER_MODULUS)||"0";a=Blockly.JavaScript.valueToCode(a,"DIVISOR",Blockly.JavaScript.ORDER_MODULUS)||"0";return[b+" % "+a,Blockly.JavaScript.ORDER_MODULUS]}; +Blockly.JavaScript.math_constrain=function(a){var b=Blockly.JavaScript.valueToCode(a,"VALUE",Blockly.JavaScript.ORDER_COMMA)||"0",c=Blockly.JavaScript.valueToCode(a,"LOW",Blockly.JavaScript.ORDER_COMMA)||"0";a=Blockly.JavaScript.valueToCode(a,"HIGH",Blockly.JavaScript.ORDER_COMMA)||"Infinity";return["Math.min(Math.max("+b+", "+c+"), "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]}; +Blockly.JavaScript.math_random_int=function(a){var b=Blockly.JavaScript.valueToCode(a,"FROM",Blockly.JavaScript.ORDER_COMMA)||"0";a=Blockly.JavaScript.valueToCode(a,"TO",Blockly.JavaScript.ORDER_COMMA)||"0";if(!Blockly.JavaScript.definitions_.math_random_int){var c=Blockly.JavaScript.variableDB_.getDistinctName("math_random_int",Blockly.Generator.NAME_TYPE);Blockly.JavaScript.math_random_int.random_function=c;var d=[];d.push("function "+c+"(a, b) {");d.push(" if (a > b) {");d.push(" // Swap a and b to ensure a is smaller."); +d.push(" var c = a;");d.push(" a = b;");d.push(" b = c;");d.push(" }");d.push(" return Math.floor(Math.random() * (b - a + 1) + a);");d.push("}");Blockly.JavaScript.definitions_.math_random_int=d.join("\n")}return[Blockly.JavaScript.math_random_int.random_function+"("+b+", "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.math_random_float=function(a){return["Math.random()",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.procedures={}; +Blockly.JavaScript.procedures_defreturn=function(a){var b=Blockly.JavaScript.variableDB_.getName(a.getTitleValue("NAME"),Blockly.Procedures.NAME_TYPE),c=Blockly.JavaScript.statementToCode(a,"STACK");Blockly.JavaScript.INFINITE_LOOP_TRAP&&(c=Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g,"'"+a.id+"'")+c);var d=Blockly.JavaScript.valueToCode(a,"RETURN",Blockly.JavaScript.ORDER_NONE)||"";d&&(d=" return "+d+";\n");for(var e=[],g=0;g",GTE:">="}[a.getTitleValue("OP")],c="=="==b||"!="==b?Blockly.JavaScript.ORDER_EQUALITY:Blockly.JavaScript.ORDER_RELATIONAL,d=Blockly.JavaScript.valueToCode(a,"A",c)||"0";a=Blockly.JavaScript.valueToCode(a,"B",c)||"0";return[d+" "+b+" "+a,c]}; +Blockly.JavaScript.logic_operation=function(a){var b="AND"==a.getTitleValue("OP")?"&&":"||",c="&&"==b?Blockly.JavaScript.ORDER_LOGICAL_AND:Blockly.JavaScript.ORDER_LOGICAL_OR,d=Blockly.JavaScript.valueToCode(a,"A",c);a=Blockly.JavaScript.valueToCode(a,"B",c);if(d||a){var e="&&"==b?"true":"false";d||(d=e);a||(a=e)}else a=d="false";return[d+" "+b+" "+a,c]}; +Blockly.JavaScript.logic_negate=function(a){var b=Blockly.JavaScript.ORDER_LOGICAL_NOT;return["!"+(Blockly.JavaScript.valueToCode(a,"BOOL",b)||"true"),b]};Blockly.JavaScript.logic_boolean=function(a){return["TRUE"==a.getTitleValue("BOOL")?"true":"false",Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.logic_null=function(a){return["null",Blockly.JavaScript.ORDER_ATOMIC]}; +Blockly.JavaScript.logic_ternary=function(a){var b=Blockly.JavaScript.valueToCode(a,"IF",Blockly.JavaScript.ORDER_CONDITIONAL)||"false",c=Blockly.JavaScript.valueToCode(a,"THEN",Blockly.JavaScript.ORDER_CONDITIONAL)||"null";a=Blockly.JavaScript.valueToCode(a,"ELSE",Blockly.JavaScript.ORDER_CONDITIONAL)||"null";return[b+" ? "+c+" : "+a,Blockly.JavaScript.ORDER_CONDITIONAL]};Blockly.JavaScript.lists={};Blockly.JavaScript.lists_create_empty=function(a){return["[]",Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.lists_create_with=function(a){for(var b=Array(a.itemCount_),c=0;c= ")+d+"; "+b;b=Math.abs(parseFloat(e));a=(1==b?a+(f?"++":"--"):a+((f?" += ":" -= ")+b))+(") {\n"+g+"}\n")}else a="",f=c,c.match(/^\w+$/)||Blockly.isNumber(c)||(f=Blockly.JavaScript.variableDB_.getDistinctName(b+"_start",Blockly.Variables.NAME_TYPE),a+="var "+f+" = "+c+";\n"),c=d,d.match(/^\w+$/)||Blockly.isNumber(d)||(c=Blockly.JavaScript.variableDB_.getDistinctName(b+ +"_end",Blockly.Variables.NAME_TYPE),a+="var "+c+" = "+d+";\n"),d=Blockly.JavaScript.variableDB_.getDistinctName(b+"_inc",Blockly.Variables.NAME_TYPE),a+="var "+d+" = ",a=Blockly.isNumber(e)?a+(Math.abs(e)+";\n"):a+("Math.abs("+e+");\n"),a+="if ("+f+" > "+c+") {\n",a+=" "+d+" = -"+d+";\n",a+="}\n",a+="for ("+b+" = "+f+";\n "+d+" >= 0 ? "+b+" <= "+c+" : "+b+" >= "+c+";\n "+b+" += "+d+") {\n"+g+"}\n";return a}; +Blockly.JavaScript.controls_forEach=function(a){var b=Blockly.JavaScript.variableDB_.getName(a.getTitleValue("VAR"),Blockly.Variables.NAME_TYPE),c=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_ASSIGNMENT)||"[]",d=Blockly.JavaScript.statementToCode(a,"DO");Blockly.JavaScript.INFINITE_LOOP_TRAP&&(d=Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g,"'"+a.id+"'")+d);a=Blockly.JavaScript.variableDB_.getDistinctName(b+"_index",Blockly.Variables.NAME_TYPE);if(c.match(/^\w+$/))b="for (var "+ +a+" in "+c+") {\n"+(" "+b+" = "+c+"["+a+"];\n"+d)+"}\n";else var e=Blockly.JavaScript.variableDB_.getDistinctName(b+"_list",Blockly.Variables.NAME_TYPE),d=" "+b+" = "+e+"["+a+"];\n"+d,b="var "+e+" = "+c+";\nfor (var "+a+" in "+e+") {\n"+d+"}\n";return b};Blockly.JavaScript.controls_flow_statements=function(a){switch(a.getTitleValue("FLOW")){case "BREAK":return"break;\n";case "CONTINUE":return"continue;\n"}throw"Unknown flow statement.";};Blockly.JavaScript.colour={};Blockly.JavaScript.colour_picker=function(a){return["'"+a.getTitleValue("COLOUR")+"'",Blockly.JavaScript.ORDER_ATOMIC]}; +Blockly.JavaScript.colour_random=function(a){if(!Blockly.JavaScript.definitions_.colour_random){a=Blockly.JavaScript.variableDB_.getDistinctName("colour_random",Blockly.Generator.NAME_TYPE);Blockly.JavaScript.colour_random.functionName=a;var b=[];b.push("function "+a+"() {");b.push(" var num = Math.floor(Math.random() * Math.pow(2, 24));");b.push(" return '#' + ('00000' + num.toString(16)).substr(-6);");b.push("}");Blockly.JavaScript.definitions_.colour_random=b.join("\n")}return[Blockly.JavaScript.colour_random.functionName+ +"()",Blockly.JavaScript.ORDER_FUNCTION_CALL]}; +Blockly.JavaScript.colour_rgb=function(a){var b=Blockly.JavaScript.valueToCode(a,"RED",Blockly.JavaScript.ORDER_COMMA)||0,c=Blockly.JavaScript.valueToCode(a,"GREEN",Blockly.JavaScript.ORDER_COMMA)||0;a=Blockly.JavaScript.valueToCode(a,"BLUE",Blockly.JavaScript.ORDER_COMMA)||0;if(!Blockly.JavaScript.definitions_.colour_rgb){var d=Blockly.JavaScript.variableDB_.getDistinctName("colour_rgb",Blockly.Generator.NAME_TYPE);Blockly.JavaScript.colour_rgb.functionName=d;var e=[];e.push("function "+d+"(r, g, b) {"); +e.push(" r = Math.max(Math.min(Number(r), 100), 0) * 2.55;");e.push(" g = Math.max(Math.min(Number(g), 100), 0) * 2.55;");e.push(" b = Math.max(Math.min(Number(b), 100), 0) * 2.55;");e.push(" r = ('0' + (Math.round(r) || 0).toString(16)).slice(-2);");e.push(" g = ('0' + (Math.round(g) || 0).toString(16)).slice(-2);");e.push(" b = ('0' + (Math.round(b) || 0).toString(16)).slice(-2);");e.push(" return '#' + r + g + b;");e.push("}");Blockly.JavaScript.definitions_.colour_rgb=e.join("\n")}return[Blockly.JavaScript.colour_rgb.functionName+ +"("+b+", "+c+", "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]}; +Blockly.JavaScript.colour_blend=function(a){var b=Blockly.JavaScript.valueToCode(a,"COLOUR1",Blockly.JavaScript.ORDER_COMMA)||"'#000000'",c=Blockly.JavaScript.valueToCode(a,"COLOUR2",Blockly.JavaScript.ORDER_COMMA)||"'#000000'";a=Blockly.JavaScript.valueToCode(a,"RATIO",Blockly.JavaScript.ORDER_COMMA)||0.5;if(!Blockly.JavaScript.definitions_.colour_blend){var d=Blockly.JavaScript.variableDB_.getDistinctName("colour_blend",Blockly.Generator.NAME_TYPE);Blockly.JavaScript.colour_blend.functionName=d; +var e=[];e.push("function "+d+"(c1, c2, ratio) {");e.push(" ratio = Math.max(Math.min(Number(ratio), 1), 0);");e.push(" var r1 = parseInt(c1.substring(1, 3), 16);");e.push(" var g1 = parseInt(c1.substring(3, 5), 16);");e.push(" var b1 = parseInt(c1.substring(5, 7), 16);");e.push(" var r2 = parseInt(c2.substring(1, 3), 16);");e.push(" var g2 = parseInt(c2.substring(3, 5), 16);");e.push(" var b2 = parseInt(c2.substring(5, 7), 16);");e.push(" var r = Math.round(r1 * (1 - ratio) + r2 * ratio);"); +e.push(" var g = Math.round(g1 * (1 - ratio) + g2 * ratio);");e.push(" var b = Math.round(b1 * (1 - ratio) + b2 * ratio);");e.push(" r = ('0' + (r || 0).toString(16)).slice(-2);");e.push(" g = ('0' + (g || 0).toString(16)).slice(-2);");e.push(" b = ('0' + (b || 0).toString(16)).slice(-2);");e.push(" return '#' + r + g + b;");e.push("}");Blockly.JavaScript.definitions_.colour_blend=e.join("\n")}return[Blockly.JavaScript.colour_blend.functionName+"("+b+", "+c+", "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]}; \ No newline at end of file diff --git a/media/1x1.gif b/media/1x1.gif new file mode 100644 index 000000000..308551123 Binary files /dev/null and b/media/1x1.gif differ diff --git a/media/click.mp3 b/media/click.mp3 new file mode 100644 index 000000000..4534b0ddc Binary files /dev/null and b/media/click.mp3 differ diff --git a/media/click.ogg b/media/click.ogg new file mode 100644 index 000000000..e8ae42a61 Binary files /dev/null and b/media/click.ogg differ diff --git a/media/click.wav b/media/click.wav new file mode 100644 index 000000000..41a50cd76 Binary files /dev/null and b/media/click.wav differ diff --git a/media/delete.mp3 b/media/delete.mp3 new file mode 100644 index 000000000..442bd9c1f Binary files /dev/null and b/media/delete.mp3 differ diff --git a/media/delete.ogg b/media/delete.ogg new file mode 100644 index 000000000..67f84ac19 Binary files /dev/null and b/media/delete.ogg differ diff --git a/media/delete.wav b/media/delete.wav new file mode 100644 index 000000000..18debcf96 Binary files /dev/null and b/media/delete.wav differ diff --git a/media/handclosed.cur b/media/handclosed.cur new file mode 100644 index 000000000..f06c243e7 Binary files /dev/null and b/media/handclosed.cur differ diff --git a/media/handopen.cur b/media/handopen.cur new file mode 100644 index 000000000..da44588b2 Binary files /dev/null and b/media/handopen.cur differ diff --git a/media/quote0.png b/media/quote0.png new file mode 100644 index 000000000..850231e25 Binary files /dev/null and b/media/quote0.png differ diff --git a/media/quote1.png b/media/quote1.png new file mode 100644 index 000000000..9c7932fa9 Binary files /dev/null and b/media/quote1.png differ diff --git a/media/trashbody.png b/media/trashbody.png new file mode 100644 index 000000000..89b57fe3b Binary files /dev/null and b/media/trashbody.png differ diff --git a/media/trashlid.png b/media/trashlid.png new file mode 100644 index 000000000..6531da4a2 Binary files /dev/null and b/media/trashlid.png differ diff --git a/media/tree.png b/media/tree.png new file mode 100644 index 000000000..47fbfc2ca Binary files /dev/null and b/media/tree.png differ diff --git a/msg/js/de.js b/msg/js/de.js new file mode 100644 index 000000000..87302696f --- /dev/null +++ b/msg/js/de.js @@ -0,0 +1,377 @@ +// This file was automatically generated. Do not modify. + +'use strict'; + +goog.provide('Blockly.Msg.de'); + +goog.require('Blockly.Msg'); + +Blockly.Msg.ADD_COMMENT = "Kommentar hinzufügen"; +Blockly.Msg.CHANGE_VALUE_TITLE = "Wert ändern:"; +Blockly.Msg.COLLAPSE_ALL = "Collapse Blocks"; +Blockly.Msg.COLLAPSE_BLOCK = "Block zusammenfalten"; +Blockly.Msg.COLOUR_BLEND_COLOUR1 = "Farbe 1"; +Blockly.Msg.COLOUR_BLEND_COLOUR2 = "mit Farbe 2"; +Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; +Blockly.Msg.COLOUR_BLEND_RATIO = "im Verhältniss"; +Blockly.Msg.COLOUR_BLEND_TITLE = "mische"; +Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Vermische 2 Farbe mit konfigurierbaren Farbverhältniss (0.0 - 1.0)."; +Blockly.Msg.COLOUR_PICKER_HELPURL = "http://de.wikipedia.org/wiki/Farbe"; +Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Wählen eine Farbe von der Palette."; +Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated +Blockly.Msg.COLOUR_RANDOM_TITLE = "random colour"; +Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Choose a colour at random."; +Blockly.Msg.COLOUR_RGB_BLUE = "blau"; +Blockly.Msg.COLOUR_RGB_GREEN = "grün"; +Blockly.Msg.COLOUR_RGB_HELPURL = "http://de.wikipedia.org/wiki/RGB-Farbraum"; +Blockly.Msg.COLOUR_RGB_RED = "rot"; +Blockly.Msg.COLOUR_RGB_TITLE = "Farbe mit"; +Blockly.Msg.COLOUR_RGB_TOOLTIP = "Kreiere eine Farbe mit selbst definierten rot, grün und blau Werten. Alle Werte müssen zwischen 0 und 100 liegen."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "http://de.wikipedia.org/wiki/Kontrollstruktur"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "ausbrechen aus der Schleife"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "mit der nächsten Iteration fortfahren aus der Schleife"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Die umgebene Schleife beenden."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Diese Anweisung abbrechen und mit der nächsten Schleifeniteration fortfahren."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Warnung: Diese block sollte nur in einer Schleife verwendet werden."; +Blockly.Msg.CONTROLS_FOREACH_HELPURL = "http://de.wikipedia.org/wiki/For-Schleif"; +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = "aus der Liste"; +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = ""; +Blockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = "Für Wert"; +Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Führe eine Anweisung für jeden Wert in der Liste aus und setzte dabei die Variable \"%1\" auf den aktuellen Listen Wert."; +Blockly.Msg.CONTROLS_FOR_HELPURL = "http://de.wikipedia.org/wiki/For-Schleif"; +Blockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = "von %1 bis %2 mit %3"; +Blockly.Msg.CONTROLS_FOR_INPUT_WITH = "Zähle"; +Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Zähle die Variable \"%1\" von einem Startwert bis zu einem Zielwert und führe für jeden Wert eine Anweisung aus."; +Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Eine weitere Bedingung hinzufügen."; +Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Eine oder Bedingung hinzufügen, führt eine Anweisung aus falls keine Bedingung zutrifft."; +Blockly.Msg.CONTROLS_IF_HELPURL = "http://code.google.com/p/blockly/wiki/If_Then"; +Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Hinzufügen, entfernen oder sortieren von Sektionen"; +Blockly.Msg.CONTROLS_IF_MSG_ELSE = "oder"; +Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "oder wenn"; +Blockly.Msg.CONTROLS_IF_MSG_IF = "wenn"; +Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Wenn eine Bedingung wahr (true) ist, dann führe eine Anweisung aus."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Wenn eine Bedingung wahr (true) ist, dann führe die erste Anweisung aus. Ansonsten führe die zweite Anweisung aus."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Wenn der erste Bedingung wahr (true) ist, dann führe die erste Anweisung aus. Oder wenn die zweite Bedingung wahr (true) ist, dann führe die zweite Anweisung aus."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Wenn der erste Bedingung wahr (true) ist, dann führe die erste Anweisung aus. Oder wenn die zweite Bedingung wahr (true) ist, dann führe die zweite Anweisung aus. Falls keine der beiden Bedingungen wahr (true) ist, dann führe die dritte Anweisung aus."; +Blockly.Msg.CONTROLS_REPEAT_HELPURL = "http://de.wikipedia.org/wiki/For-Schleife"; +Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "mache"; +Blockly.Msg.CONTROLS_REPEAT_TITLE = "wiederhole %1 mal"; +Blockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = "wiederhole"; +Blockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = "mal"; +Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Eine Anweisung mehrfach ausführen."; +Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "http://de.wikipedia.org/wiki/Schleife_%28Programmierung%29"; +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "Wiederhole bis"; +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "Wiederhole solange"; +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Führe die Anweisung solange aus wie die Bedingung falsch (false) ist."; +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Führe die Anweisung solange aus wie die Bedingung wahr (true) ist."; +Blockly.Msg.DELETE_BLOCK = "Block löschen"; +Blockly.Msg.DELETE_X_BLOCKS = "Block %1 löschen"; +Blockly.Msg.DISABLE_BLOCK = "Block deaktivieren"; +Blockly.Msg.DUPLICATE_BLOCK = "Kopieren"; +Blockly.Msg.ENABLE_BLOCK = "Block aktivieren"; +Blockly.Msg.EXPAND_ALL = "Expand Blocks"; +Blockly.Msg.EXPAND_BLOCK = "Block entfalten"; +Blockly.Msg.EXTERNAL_INPUTS = "externe Eingänge"; +Blockly.Msg.HELP = "Hilfe"; +Blockly.Msg.INLINE_INPUTS = "interne Eingänge"; +Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "http://en.wikipedia.org/wiki/Linked_list#Empty_lists"; +Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "Erzeuge eine leere Liste"; +Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Erzeugt eine leere Liste ohne Inhalt."; +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "Liste"; +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Hinzufügen, entfernen und sortieren von Elementen."; +Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "Erzeuge Liste mit"; +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Ein Element zur Liste hinzufügen."; +Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Erzeugt eine List mit konfigurierten Elementen."; +Blockly.Msg.LISTS_GET_INDEX_FIRST = "erste"; +Blockly.Msg.LISTS_GET_INDEX_FROM_END = "#te von hinten"; +Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#te"; +Blockly.Msg.LISTS_GET_INDEX_GET = "Nehme"; +Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "Nehme und entferne"; +Blockly.Msg.LISTS_GET_INDEX_LAST = "letzte"; +Blockly.Msg.LISTS_GET_INDEX_RANDOM = "zufälliges"; +Blockly.Msg.LISTS_GET_INDEX_REMOVE = "Entferne"; +Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Extrahiere das erste Element von der Liste."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = "Extrahiere das #1te Element vom Ende der Liste."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = "Extrahiere das #1te Element von der Liste."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Extrahiere das letzte Element von der Liste."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Extrahiere ein zufälliges Element von der Liste."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Extrahiere und entfernt das erste Element von der Liste."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = "Extrahiere und entfernt das #1te Element vom Ende der Liste."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = "Extrahiere und entfernt das #1te Element von der Liste."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Extrahiere und entfernt das letzte Element von der Liste."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Extrahiere und entfernt ein zufälliges Element von der Liste."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Entfernt das erste Element von der Liste."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = "Entfernt das #1te Element vom Ende der Liste."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = "Entfernt das #1te Element von der Liste."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Entfernt das letzte Element von der Liste."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Entfernt ein zufälliges Element von der Liste."; +Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "zu # vom Ende"; +Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "zu #"; +Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "zum Letzten"; +Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm"; +Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "erhalte Unterliste vom Ersten"; +Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "erhalte Unterliste von # vom Ende"; +Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "erhalte Unterliste von #"; +Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; +Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Creates a copy of the specified portion of a list."; +Blockly.Msg.LISTS_INDEX_OF_FIRST = "Suche erstes Vorkommniss"; +Blockly.Msg.LISTS_INDEX_OF_HELPURL = "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm"; +Blockly.Msg.LISTS_INDEX_OF_LAST = "Suche letztes Vorkommniss"; +Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Sucht die Position (index) eines Elementes in der Liste Gibt 0 zurück wenn nichts gefunden wurde."; +Blockly.Msg.LISTS_INLIST = "in der Liste"; +Blockly.Msg.LISTS_IS_EMPTY_HELPURL = "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html"; +Blockly.Msg.LISTS_IS_EMPTY_TITLE = "%1 ist leer?"; +Blockly.Msg.LISTS_LENGTH_HELPURL = "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html"; +Blockly.Msg.LISTS_LENGTH_TITLE = "länge %1"; +Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Die Anzahl von Elementen in der Liste."; +Blockly.Msg.LISTS_REPEAT_HELPURL = "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm"; +Blockly.Msg.LISTS_REPEAT_TITLE = "Erzeuge Liste mit Element %1 wiederhole es %2 mal"; +Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Erzeugt eine Liste mit einer variablen Anzahl von Elementen"; +Blockly.Msg.LISTS_SET_INDEX_HELPURL = "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm"; +Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "auf"; +Blockly.Msg.LISTS_SET_INDEX_INSERT = "insert"; +Blockly.Msg.LISTS_SET_INDEX_SET = "set"; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Inserts the item at the start of a list."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = "Inserts the item at the specified position in a list. #1 is the last item."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = "Inserts the item at the specified position in a list. #1 is the first item."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Append the item to the end of a list."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Inserts the item randomly in a list."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Sets the first item in a list."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = "Sets the item at the specified position in a list. #1 is the last item."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = "Sets the item at the specified position in a list. #1 is the first item."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Sets the last item in a list."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Sets a random item in a list."; +Blockly.Msg.LISTS_TOOLTIP = "Ist wahr (true), wenn die Liste leer ist."; +Blockly.Msg.LOGIC_BOOLEAN_FALSE = "falsch"; +Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "http://code.google.com/p/blockly/wiki/True_False"; +Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Ist entweder wahr (true) oder falsch (false)"; +Blockly.Msg.LOGIC_BOOLEAN_TRUE = "wahr"; +Blockly.Msg.LOGIC_COMPARE_HELPURL = "http://de.wikipedia.org/wiki/Vergleich_%28Zahlen%29"; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Ist wahr (true) wenn beide Werte identisch sind."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Ist wahr (true) wenn der erste Wert grösser als der zweite Wert ist."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Ist wahr (true) wenn der erste Wert grösser als oder gleich gross wie zweite Wert ist."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Ist wahr (true) wenn der erste Wert kleiner als der zweite Wert ist."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Ist wahr (true) wenn der erste Wert kleiner als oder gleich gross wie zweite Wert ist."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Ist wahr (true) wenn beide Werte unterschiedlich sind."; +Blockly.Msg.LOGIC_NEGATE_HELPURL = "http://code.google.com/p/blockly/wiki/Not"; +Blockly.Msg.LOGIC_NEGATE_TITLE = "nicht %1"; +Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Ist wahr (true) wenn der Eingabewert falsch (false) ist. Ist falsch (false) wenn der Eingabewert wahr (true) ist."; +Blockly.Msg.LOGIC_NULL = "null"; +Blockly.Msg.LOGIC_NULL_HELPURL = "http://de.wikipedia.org/wiki/Nullwert"; +Blockly.Msg.LOGIC_NULL_TOOLTIP = "Ist NULL."; +Blockly.Msg.LOGIC_OPERATION_AND = "und"; +Blockly.Msg.LOGIC_OPERATION_HELPURL = "http://code.google.com/p/blockly/wiki/And_Or"; +Blockly.Msg.LOGIC_OPERATION_OR = "oder"; +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Ist wahr (true) wenn beide Werte wahr (true) sind."; +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Ist wahr (true) wenn einer der beiden Werte wahr (true) ist."; +Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; +Blockly.Msg.LOGIC_TERNARY_HELPURL = "http://de.wikipedia.org/wiki/%3F:#Auswahloperator"; +Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "wenn falsch"; +Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "wenn wahr"; +Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Überprüft eine Bedingung \"test\". Wenn die Bedingung wahr ist wird der \"wenn wahr\" Wert zurückgegeben, andernfalls der \"wenn falsch\" Wert"; +Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated +Blockly.Msg.MATH_ARITHMETIC_HELPURL = "http://de.wikipedia.org/wiki/Grundrechenart"; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Ist die Summe zweier Werte."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Ist der Quotient zweier Werte."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Ist die Differenz zweier Werte."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Ist das Produkt zweier Werte."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Ist der erste Wert potenziert mit dem zweiten Wert."; +Blockly.Msg.MATH_CHANGE_HELPURL = "http://de.wikipedia.org/wiki/Inkrement_und_Dekrement"; +Blockly.Msg.MATH_CHANGE_INPUT_BY = "um"; +Blockly.Msg.MATH_CHANGE_TITLE_CHANGE = "erhöhe"; +Blockly.Msg.MATH_CHANGE_TOOLTIP = "Addiert einen Wert zur Variable \"%1\" hinzu."; +Blockly.Msg.MATH_CONSTANT_HELPURL = "http://de.wikipedia.org/wiki/Mathematische_Konstante"; +Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Mathematische Konstanten wie: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…) oder ∞ (unendlich)."; +Blockly.Msg.MATH_CONSTRAIN_HELPURL = "http://en.wikipedia.org/wiki/Clamping_%28graphics%29"; +Blockly.Msg.MATH_CONSTRAIN_TITLE = "begrenzen %1 von %2 bis %3"; +Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Begrenzt den Wertebereich mittels von / bis Werte. (inklusiv)"; +Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated +Blockly.Msg.MATH_IS_DIVISIBLE_BY = "ist teilbar durch"; +Blockly.Msg.MATH_IS_EVEN = "ist gerade"; +Blockly.Msg.MATH_IS_NEGATIVE = "ist negativ"; +Blockly.Msg.MATH_IS_ODD = "ist ungerade"; +Blockly.Msg.MATH_IS_POSITIVE = "ist positiv"; +Blockly.Msg.MATH_IS_PRIME = "ist eine Primenzahl"; +Blockly.Msg.MATH_IS_TOOLTIP = "Überprüft ob eine Zahl gerade, ungerade, eine Primenzahl, ganzzahlig, positiv, negativ oder durch eine zweite Zahl teilbar ist. Gibt wahr (true) oder falsch (false) zurück."; +Blockly.Msg.MATH_IS_WHOLE = "ganze Zahl"; +Blockly.Msg.MATH_MODULO_HELPURL = "http://de.wikipedia.org/wiki/Modulo"; +Blockly.Msg.MATH_MODULO_TITLE = "Rest von %1 ÷ %2"; +Blockly.Msg.MATH_MODULO_TOOLTIP = "Der Rest nach einer Division."; +Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated +Blockly.Msg.MATH_NUMBER_HELPURL = "http://de.wikipedia.org/wiki/Zahl"; +Blockly.Msg.MATH_NUMBER_TOOLTIP = "Eine Zahl."; +Blockly.Msg.MATH_ONLIST_HELPURL = "http://www.sysplus.ch/einstieg.php?links=menu&seite=4125&grad=Crash&prog=Excel"; +Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "Mittelwert einer Liste"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "Maximalwert einer Liste"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "Median einer Liste"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "Minimalwert einer Liste"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "Modulo / Restwert einer Liste"; +Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "Zufallswert einer Liste"; +Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "Standart Abweichung einer Liste"; +Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "Summme einer Liste"; +Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Ist der Durchschnittswert aller Werte in einer Liste."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Ist der grösste Wert in einer Liste."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Ist der Zentralwert aller Werte in einer Liste."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Ist der kleinste Wert in einer Liste."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Findet den am häufigsten vorkommenden Wert in einer Liste. Falls kein Wert öfter vorkomme als alle anderen, wird die originale Liste zurückgegen"; +Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Gebe einen Zufallswert aus der Liste zurück."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Ist die standartiesierte Standartabweichung aller Werte in der Liste"; +Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Ist die Summe aller Werte in einer Liste."; +Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated +Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "http://de.wikipedia.org/wiki/Zufallszahlen"; +Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "Zufallszahl (0.0 -1.0)"; +Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Erzeuge eine Zufallszahl zwischen 0.0 (inklusiv) und 1.0 (exklusiv)."; +Blockly.Msg.MATH_RANDOM_INT_HELPURL = "http://de.wikipedia.org/wiki/Zufallszahlen"; +Blockly.Msg.MATH_RANDOM_INT_TITLE = "ganzahliger Zufallswerte zwischen %1 bis %2"; +Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Erzeuge eine ganzahligen Zufallswert zwischen zwei Werten (inklusiv)."; +Blockly.Msg.MATH_ROUND_HELPURL = "http://de.wikipedia.org/wiki/Runden"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "runden"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "ab runden"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "auf runden"; +Blockly.Msg.MATH_ROUND_TOOLTIP = "Eine Zahl auf oder ab runden."; +Blockly.Msg.MATH_SINGLE_HELPURL = "http://de.wikipedia.org/wiki/Quadratwurzel"; +Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "Absolutwert"; +Blockly.Msg.MATH_SINGLE_OP_ROOT = "Quadratwurzel"; +Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Ist der Absolutwert eines Wertes."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Ist Wert der Exponentialfunktion eines Wertes."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Ist der natürliche Logarithmus eines Wertes."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Ist der dekadische Logarithmus eines Wertes."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Negiert einen Wert."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Rechnet 10 hoch Eingabewert."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Ist die Qudratwurzel eines Wertes."; +Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated +Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated +Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated +Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated +Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated +Blockly.Msg.MATH_TRIG_HELPURL = "http://de.wikipedia.org/wiki/Trigonometrie"; +Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated +Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated +Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Ist der Arcuscosinus des Eingabewertes."; +Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Ist der Arcussinus des Eingabewertes."; +Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Ist der Arcustangens des Eingabewertes."; +Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Ist der Cosinus eins Winkels."; +Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Ist der Sinus eins Winkels."; +Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Ist der Tangens eins Winkels."; +Blockly.Msg.NEW_VARIABLE = "Neue Variable..."; +Blockly.Msg.NEW_VARIABLE_TITLE = "Name der neuen Variable:"; +Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; +Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "mit:"; +Blockly.Msg.PROCEDURES_CALLNORETURN_CALL = ""; +Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "http://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29"; +Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Rufe einen Funktionsblock ohne Rückgabewert auf."; +Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "http://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29"; +Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Rufe einen Funktionsblock mit Rückgabewert auf."; +Blockly.Msg.PROCEDURES_CREATE_DO = "Erzeuge \"Aufruf %1\""; +Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; +Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "http://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29"; +Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "Funktionsblock"; +Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "to"; +Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Ein Funktionsblock ohne Rückgabewert."; +Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "http://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29"; +Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "gebe zurück"; +Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Ein Funktionsblock mit Rückgabewert."; +Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Warnung: dieser Funktionsblock hat doppelte Parameter."; +Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Markiere Funktionsblock"; +Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Wenn der erste Wert wahr (true) ist, Gebe den zweiten Wert zurück."; +Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Warnung: Dieser Block darf nur innerhalb eines Funktionsblock genutzt werden."; +Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "Variable:"; +Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "Parameter"; +Blockly.Msg.REMOVE_COMMENT = "Kommentar entfernen"; +Blockly.Msg.RENAME_VARIABLE = "Variable umbenennen..."; +Blockly.Msg.RENAME_VARIABLE_TITLE = "Alle \"%1\" Variablen umbenennen in:"; +Blockly.Msg.TEXT_APPEND_APPENDTEXT = "Text anhängen"; +Blockly.Msg.TEXT_APPEND_HELPURL = "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html"; +Blockly.Msg.TEXT_APPEND_TO = "An"; +Blockly.Msg.TEXT_APPEND_TOOLTIP = "Text an die Variable \"%1\" anhängen."; +Blockly.Msg.TEXT_CHANGECASE_HELPURL = "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html"; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "umwandeln in kleinbuchstaben"; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "umwandeln in Wörter"; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "umwandeln in GROSSBUCHSTABEN"; +Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Wandelt Schreibweise von Texten um, in Grossbuchstaben, Kleinbuchstaben oder den ersten Buchstaben jedes Wortes gross und die anderen klein."; +Blockly.Msg.TEXT_CHARAT_FIRST = "Nehme ersten Buchstabe"; +Blockly.Msg.TEXT_CHARAT_FROM_END = "Nehme #te Buchstabe von hinten"; +Blockly.Msg.TEXT_CHARAT_FROM_START = "Nehme Buchstabe #ten"; +Blockly.Msg.TEXT_CHARAT_HELPURL = "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm"; +Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "vom Text"; +Blockly.Msg.TEXT_CHARAT_LAST = "Nehme letzten Buchstabe"; +Blockly.Msg.TEXT_CHARAT_RANDOM = "Nehme zufälligen Buchstabe"; +Blockly.Msg.TEXT_CHARAT_TAIL = ""; +Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Extrahiere einen Buchstaben von einer spezifizierten Position."; +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Ein Element zum Text hinzufügen."; +Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "verbinden"; +Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Hinzufügen, entfernen und sortieren von Elementen."; +Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "bis #te Buchstabe von hinten"; +Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "bis Buchstabe #ten"; +Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "bis letzten Buchstabe"; +Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm"; +Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "in Text"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "ersten Buchstabe"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "#te Buchstabe von hinten"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "Buchstabe #ten"; +Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; +Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Returns a specified portion of the text."; +Blockly.Msg.TEXT_INDEXOF_HELPURL = "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm"; +Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "im Text"; +Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "Suche erstes Vorkommniss des Begriff"; +Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "Suche letztes Vorkommniss des Begriff"; +Blockly.Msg.TEXT_INDEXOF_TAIL = ""; +Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Findest das erste / letzte Vorkommniss eines cuchbegriffes in einem Text. Gibt die Position des Begriffes oder 0 zurück."; +Blockly.Msg.TEXT_ISEMPTY_HELPURL = "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html"; +Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 ist leer?"; +Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Ist wahr (true), wenn der Text leer ist."; +Blockly.Msg.TEXT_JOIN_HELPURL = ""; +Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "Erstelle Text aus"; +Blockly.Msg.TEXT_JOIN_TOOLTIP = "Erstellt einen Text durch das verbinden von mehreren Textelementen."; +Blockly.Msg.TEXT_LENGTH_HELPURL = "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html"; +Blockly.Msg.TEXT_LENGTH_TITLE = "länge %1"; +Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Die Anzahl von Zeichen in einem Textes. (inkl. Leerzeichen)"; +Blockly.Msg.TEXT_PRINT_HELPURL = "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html"; +Blockly.Msg.TEXT_PRINT_TITLE = "Ausgabe %1"; +Blockly.Msg.TEXT_PRINT_TOOLTIP = "Gib den Inhalt einer Variable aus."; +Blockly.Msg.TEXT_PROMPT_HELPURL = "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode92.html"; +Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Fragt den Benutzer nach ein Zahl."; +Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Fragt den Benutzer nach einem Text."; +Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "Fragt nach Zahl mit Hinweis"; +Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "Fragt nach Text mit Hinweis"; +Blockly.Msg.TEXT_TEXT_HELPURL = "http://de.wikipedia.org/wiki/Zeichenkette"; +Blockly.Msg.TEXT_TEXT_TOOLTIP = "Ein Buchstabe, Text oder Satz."; +Blockly.Msg.TEXT_TRIM_HELPURL = "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html"; +Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "entferne Leerzeichen von Anfang und Ende Seiten"; +Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "entferne Leerzeichen von Anfang Seite"; +Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "entferne Leerzeichen von Ende Seite"; +Blockly.Msg.TEXT_TRIM_TOOLTIP = "Entfernt Leerzeichen vom Anfang und / oder Ende eines Textes."; +Blockly.Msg.VARIABLES_DEFAULT_NAME = "Element"; +Blockly.Msg.VARIABLES_GET_CREATE_SET = "Erzeuge \"Schreibe %1\""; +Blockly.Msg.VARIABLES_GET_HELPURL = "http://de.wikipedia.org/wiki/Variable_%28Programmierung%29"; +Blockly.Msg.VARIABLES_GET_TAIL = ""; +Blockly.Msg.VARIABLES_GET_TITLE = ""; +Blockly.Msg.VARIABLES_GET_TOOLTIP = "Gibt den Wert der Variable zurück."; +Blockly.Msg.VARIABLES_SET_CREATE_GET = "Erzeuge \"Lese %1\""; +Blockly.Msg.VARIABLES_SET_HELPURL = "http://de.wikipedia.org/wiki/Variable_%28Programmierung%29"; +Blockly.Msg.VARIABLES_SET_TAIL = ""; +Blockly.Msg.VARIABLES_SET_TITLE = "Schreibe"; +Blockly.Msg.VARIABLES_SET_TOOLTIP = "Setzt den Wert einer Variable."; +Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; +Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; +Blockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; +Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL; +Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; +Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; +Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; \ No newline at end of file diff --git a/msg/js/en.js b/msg/js/en.js new file mode 100644 index 000000000..45b801904 --- /dev/null +++ b/msg/js/en.js @@ -0,0 +1,377 @@ +// This file was automatically generated. Do not modify. + +'use strict'; + +goog.provide('Blockly.Msg.en'); + +goog.require('Blockly.Msg'); + +Blockly.Msg.ADD_COMMENT = "Add Comment"; +Blockly.Msg.CHANGE_VALUE_TITLE = "Change value:"; +Blockly.Msg.COLLAPSE_ALL = "Collapse Blocks"; +Blockly.Msg.COLLAPSE_BLOCK = "Collapse Block"; +Blockly.Msg.COLOUR_BLEND_COLOUR1 = "colour 1"; +Blockly.Msg.COLOUR_BLEND_COLOUR2 = "colour 2"; +Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; +Blockly.Msg.COLOUR_BLEND_RATIO = "ratio"; +Blockly.Msg.COLOUR_BLEND_TITLE = "blend"; +Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Blends two colours together with a given ratio (0.0 - 1.0)."; +Blockly.Msg.COLOUR_PICKER_HELPURL = "http://en.wikipedia.org/wiki/Color"; +Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Choose a colour from the palette."; +Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; +Blockly.Msg.COLOUR_RANDOM_TITLE = "random colour"; +Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Choose a colour at random."; +Blockly.Msg.COLOUR_RGB_BLUE = "blue"; +Blockly.Msg.COLOUR_RGB_GREEN = "green"; +Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; +Blockly.Msg.COLOUR_RGB_RED = "red"; +Blockly.Msg.COLOUR_RGB_TITLE = "colour with"; +Blockly.Msg.COLOUR_RGB_TOOLTIP = "Create a colour with the specified amount of red, green, and blue. All values must be between 0 and 100."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "break out of loop"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "continue with next iteration of loop"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Break out of the containing loop."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Skip the rest of this loop, and continue with the next iteration."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Warning: This block may only be used within a loop."; +Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#for_each for each block"; +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = "in list"; +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = ""; +Blockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = "for each item"; +Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "For each item in a list, set the variable '%1' to the item, and then do some statements."; +Blockly.Msg.CONTROLS_FOR_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#count_with"; +Blockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = "from %1 to %2 by %3"; +Blockly.Msg.CONTROLS_FOR_INPUT_WITH = "count with"; +Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Have the variable %1 take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks."; +Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Add a condition to the if block."; +Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Add a final, catch-all condition to the if block."; +Blockly.Msg.CONTROLS_IF_HELPURL = "http://code.google.com/p/blockly/wiki/If_Then"; +Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Add, remove, or reorder sections to reconfigure this if block."; +Blockly.Msg.CONTROLS_IF_MSG_ELSE = "else"; +Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "else if"; +Blockly.Msg.CONTROLS_IF_MSG_IF = "if"; +Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "If a value is true, then do some statements."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "If a value is true, then do the first block of statements. Otherwise, do the second block of statements."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements. If none of the values are true, do the last block of statements."; +Blockly.Msg.CONTROLS_REPEAT_HELPURL = "http://en.wikipedia.org/wiki/For_loop"; +Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "do"; +Blockly.Msg.CONTROLS_REPEAT_TITLE = "repeat %1 times"; +Blockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = "repeat"; +Blockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = "times"; +Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Do some statements several times."; +Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "http://code.google.com/p/blockly/wiki/Repeat"; +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "repeat until"; +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "repeat while"; +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "While a value is false, then do some statements."; +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "While a value is true, then do some statements."; +Blockly.Msg.DELETE_BLOCK = "Delete Block"; +Blockly.Msg.DELETE_X_BLOCKS = "Delete %1 Blocks"; +Blockly.Msg.DISABLE_BLOCK = "Disable Block"; +Blockly.Msg.DUPLICATE_BLOCK = "Duplicate"; +Blockly.Msg.ENABLE_BLOCK = "Enable Block"; +Blockly.Msg.EXPAND_ALL = "Expand Blocks"; +Blockly.Msg.EXPAND_BLOCK = "Expand Block"; +Blockly.Msg.EXTERNAL_INPUTS = "External Inputs"; +Blockly.Msg.HELP = "Help"; +Blockly.Msg.INLINE_INPUTS = "Inline Inputs"; +Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "http://en.wikipedia.org/wiki/Linked_list#Empty_lists"; +Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "create empty list"; +Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Returns a list, of length 0, containing no data records"; +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "list"; +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Add, remove, or reorder sections to reconfigure this list block."; +Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "create list with"; +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Add an item to the list."; +Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Create a list with any number of items."; +Blockly.Msg.LISTS_GET_INDEX_FIRST = "first"; +Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# from end"; +Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; +Blockly.Msg.LISTS_GET_INDEX_GET = "get"; +Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "get and remove"; +Blockly.Msg.LISTS_GET_INDEX_LAST = "last"; +Blockly.Msg.LISTS_GET_INDEX_RANDOM = "random"; +Blockly.Msg.LISTS_GET_INDEX_REMOVE = "remove"; +Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Returns the first item in a list."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = "Returns the item at the specified position in a list. #1 is the last item."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = "Returns the item at the specified position in a list. #1 is the first item."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Returns the last item in a list."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Returns a random item in a list."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Removes and returns the first item in a list."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = "Removes and returns the item at the specified position in a list. #1 is the last item."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = "Removes and returns the item at the specified position in a list. #1 is the first item."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Removes and returns the last item in a list."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Removes and returns a random item in a list."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Removes the first item in a list."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = "Removes the item at the specified position in a list. #1 is the last item."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = "Removes the item at the specified position in a list. #1 is the first item."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Removes the last item in a list."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Removes a random item in a list."; +Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "to # from end"; +Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "to #"; +Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "to last"; +Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist"; +Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "get sub-list from first"; +Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "get sub-list from # from end"; +Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "get sub-list from #"; +Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; +Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Creates a copy of the specified portion of a list."; +Blockly.Msg.LISTS_INDEX_OF_FIRST = "find first occurrence of item"; +Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List"; +Blockly.Msg.LISTS_INDEX_OF_LAST = "find last occurrence of item"; +Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Returns the index of the first/last occurrence of the item in the list. Returns 0 if text is not found."; +Blockly.Msg.LISTS_INLIST = "in list"; +Blockly.Msg.LISTS_IS_EMPTY_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#is_empty"; +Blockly.Msg.LISTS_IS_EMPTY_TITLE = "%1 is empty"; +Blockly.Msg.LISTS_LENGTH_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#length_of"; +Blockly.Msg.LISTS_LENGTH_TITLE = "length of %1"; +Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Returns the length of a list."; +Blockly.Msg.LISTS_REPEAT_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#create_list_with"; +Blockly.Msg.LISTS_REPEAT_TITLE = "create list with item %1 repeated %2 times"; +Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Creates a list consisting of the given value repeated the specified number of times."; +Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#in_list_..._set"; +Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "as"; +Blockly.Msg.LISTS_SET_INDEX_INSERT = "insert at"; +Blockly.Msg.LISTS_SET_INDEX_SET = "set"; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Inserts the item at the start of a list."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = "Inserts the item at the specified position in a list. #1 is the last item."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = "Inserts the item at the specified position in a list. #1 is the first item."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Append the item to the end of a list."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Inserts the item randomly in a list."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Sets the first item in a list."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = "Sets the item at the specified position in a list. #1 is the last item."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = "Sets the item at the specified position in a list. #1 is the first item."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Sets the last item in a list."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Sets a random item in a list."; +Blockly.Msg.LISTS_TOOLTIP = "Returns true if the list is empty."; +Blockly.Msg.LOGIC_BOOLEAN_FALSE = "false"; +Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "http://code.google.com/p/blockly/wiki/True_False"; +Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Returns either true or false."; +Blockly.Msg.LOGIC_BOOLEAN_TRUE = "true"; +Blockly.Msg.LOGIC_COMPARE_HELPURL = "http://en.wikipedia.org/wiki/Inequality_(mathematics)"; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Return true if both inputs equal each other."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Return true if the first input is greater than the second input."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Return true if the first input is greater than or equal to the second input."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Return true if the first input is smaller than the second input."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Return true if the first input is smaller than or equal to the second input."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Return true if both inputs are not equal to each other."; +Blockly.Msg.LOGIC_NEGATE_HELPURL = "http://code.google.com/p/blockly/wiki/Not"; +Blockly.Msg.LOGIC_NEGATE_TITLE = "not %1"; +Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Returns true if the input is false. Returns false if the input is true."; +Blockly.Msg.LOGIC_NULL = "null"; +Blockly.Msg.LOGIC_NULL_HELPURL = "http://en.wikipedia.org/wiki/Nullable_type"; +Blockly.Msg.LOGIC_NULL_TOOLTIP = "Returns null."; +Blockly.Msg.LOGIC_OPERATION_AND = "and"; +Blockly.Msg.LOGIC_OPERATION_HELPURL = "http://code.google.com/p/blockly/wiki/And_Or"; +Blockly.Msg.LOGIC_OPERATION_OR = "or"; +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Return true if both inputs are true."; +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Return true if at least one of the inputs is true."; +Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; +Blockly.Msg.LOGIC_TERNARY_HELPURL = "http://en.wikipedia.org/wiki/%3F:"; +Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "if false"; +Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "if true"; +Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value."; +Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; +Blockly.Msg.MATH_ARITHMETIC_HELPURL = "http://en.wikipedia.org/wiki/Arithmetic"; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Return the sum of the two numbers."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Return the quotient of the two numbers."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Return the difference of the two numbers."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Return the product of the two numbers."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Return the first number raised to the power of the second number."; +Blockly.Msg.MATH_CHANGE_HELPURL = "http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; +Blockly.Msg.MATH_CHANGE_INPUT_BY = "by"; +Blockly.Msg.MATH_CHANGE_TITLE_CHANGE = "change"; +Blockly.Msg.MATH_CHANGE_TOOLTIP = "Add a number to variable '%1'."; +Blockly.Msg.MATH_CONSTANT_HELPURL = "http://en.wikipedia.org/wiki/Mathematical_constant"; +Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity)."; +Blockly.Msg.MATH_CONSTRAIN_HELPURL = "http://en.wikipedia.org/wiki/Clamping_%28graphics%29"; +Blockly.Msg.MATH_CONSTRAIN_TITLE = "constrain %1 low %2 high %3"; +Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Constrain a number to be between the specified limits (inclusive)."; +Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; +Blockly.Msg.MATH_IS_DIVISIBLE_BY = "is divisible by"; +Blockly.Msg.MATH_IS_EVEN = "is even"; +Blockly.Msg.MATH_IS_NEGATIVE = "is negative"; +Blockly.Msg.MATH_IS_ODD = "is odd"; +Blockly.Msg.MATH_IS_POSITIVE = "is positive"; +Blockly.Msg.MATH_IS_PRIME = "is prime"; +Blockly.Msg.MATH_IS_TOOLTIP = "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false."; +Blockly.Msg.MATH_IS_WHOLE = "is whole"; +Blockly.Msg.MATH_MODULO_HELPURL = "http://en.wikipedia.org/wiki/Modulo_operation"; +Blockly.Msg.MATH_MODULO_TITLE = "remainder of %1 ÷ %2"; +Blockly.Msg.MATH_MODULO_TOOLTIP = "Return the remainder from dividing the two numbers."; +Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; +Blockly.Msg.MATH_NUMBER_HELPURL = "http://en.wikipedia.org/wiki/Number"; +Blockly.Msg.MATH_NUMBER_TOOLTIP = "A number."; +Blockly.Msg.MATH_ONLIST_HELPURL = ""; +Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "average of list"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "max of list"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "median of list"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "min of list"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "modes of list"; +Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "random item of list"; +Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "standard deviation of list"; +Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "sum of list"; +Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Return the average (arithmetic mean) of the numeric values in the list."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Return the largest number in the list."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Return the median number in the list."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Return the smallest number in the list."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Return a list of the most common item(s) in the list."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Return a random element from the list."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Return the standard deviation of the list."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Return the sum of all the numbers in the list."; +Blockly.Msg.MATH_POWER_SYMBOL = "^"; +Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "http://en.wikipedia.org/wiki/Random_number_generation"; +Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "random fraction"; +Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive)."; +Blockly.Msg.MATH_RANDOM_INT_HELPURL = "http://en.wikipedia.org/wiki/Random_number_generation"; +Blockly.Msg.MATH_RANDOM_INT_TITLE = "random integer from %1 to %2"; +Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Return a random integer between the two specified limits, inclusive."; +Blockly.Msg.MATH_ROUND_HELPURL = "http://en.wikipedia.org/wiki/Rounding"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "round"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "round down"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "round up"; +Blockly.Msg.MATH_ROUND_TOOLTIP = "Round a number up or down."; +Blockly.Msg.MATH_SINGLE_HELPURL = "http://en.wikipedia.org/wiki/Square_root"; +Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "absolute"; +Blockly.Msg.MATH_SINGLE_OP_ROOT = "square root"; +Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Return the absolute value of a number."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Return e to the power of a number."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Return the natural logarithm of a number."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Return the base 10 logarithm of a number."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Return the negation of a number."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Return 10 to the power of a number."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Return the square root of a number."; +Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; +Blockly.Msg.MATH_TRIG_ACOS = "acos"; +Blockly.Msg.MATH_TRIG_ASIN = "asin"; +Blockly.Msg.MATH_TRIG_ATAN = "atan"; +Blockly.Msg.MATH_TRIG_COS = "cos"; +Blockly.Msg.MATH_TRIG_HELPURL = "http://en.wikipedia.org/wiki/Trigonometric_functions"; +Blockly.Msg.MATH_TRIG_SIN = "sin"; +Blockly.Msg.MATH_TRIG_TAN = "tan"; +Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Return the arccosine of a number."; +Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Return the arcsine of a number."; +Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Return the arctangent of a number."; +Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Return the cosine of a degree (not radian)."; +Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Return the sine of a degree (not radian)."; +Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Return the tangent of a degree (not radian)."; +Blockly.Msg.NEW_VARIABLE = "New variable..."; +Blockly.Msg.NEW_VARIABLE_TITLE = "New variable name:"; +Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; +Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "with:"; +Blockly.Msg.PROCEDURES_CALLNORETURN_CALL = ""; +Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; +Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Run the user-defined function '%1'."; +Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; +Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Run the user-defined function '%1' and use its output."; +Blockly.Msg.PROCEDURES_CREATE_DO = "Create '%1'"; +Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; +Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; +Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "do something"; +Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "to"; +Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Creates a function with no output."; +Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; +Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "return"; +Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Creates a function with an output."; +Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Warning: This function has duplicate parameters."; +Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Highlight function definition"; +Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "If a value is true, then return a second value."; +Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Warning: This block may be used only within a function definition."; +Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "input name:"; +Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "inputs"; +Blockly.Msg.REMOVE_COMMENT = "Remove Comment"; +Blockly.Msg.RENAME_VARIABLE = "Rename variable..."; +Blockly.Msg.RENAME_VARIABLE_TITLE = "Rename all '%1' variables to:"; +Blockly.Msg.TEXT_APPEND_APPENDTEXT = "append text"; +Blockly.Msg.TEXT_APPEND_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Text_modification"; +Blockly.Msg.TEXT_APPEND_TO = "to"; +Blockly.Msg.TEXT_APPEND_TOOLTIP = "Append some text to variable '%1'."; +Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case"; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "to lower case"; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "to Title Case"; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "to UPPER CASE"; +Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Return a copy of the text in a different case."; +Blockly.Msg.TEXT_CHARAT_FIRST = "get first letter"; +Blockly.Msg.TEXT_CHARAT_FROM_END = "get letter # from end"; +Blockly.Msg.TEXT_CHARAT_FROM_START = "get letter #"; +Blockly.Msg.TEXT_CHARAT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Extracting_text"; +Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "in text"; +Blockly.Msg.TEXT_CHARAT_LAST = "get last letter"; +Blockly.Msg.TEXT_CHARAT_RANDOM = "get random letter"; +Blockly.Msg.TEXT_CHARAT_TAIL = ""; +Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Returns the letter at the specified position."; +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Add an item to the text."; +Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "join"; +Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Add, remove, or reorder sections to reconfigure this text block."; +Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "to letter # from end"; +Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "to letter #"; +Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "to last letter"; +Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text"; +Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "in text"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "get substring from first letter"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "get substring from letter # from end"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "get substring from letter #"; +Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; +Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Returns a specified portion of the text."; +Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Finding_text"; +Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "in text"; +Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "find first occurrence of text"; +Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "find last occurrence of text"; +Blockly.Msg.TEXT_INDEXOF_TAIL = ""; +Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Returns the index of the first/last occurrence of first text in the second text. Returns 0 if text is not found."; +Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text"; +Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 is empty"; +Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Returns true if the provided text is empty."; +Blockly.Msg.TEXT_JOIN_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Text_creation"; +Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "create text with"; +Blockly.Msg.TEXT_JOIN_TOOLTIP = "Create a piece of text by joining together any number of items."; +Blockly.Msg.TEXT_LENGTH_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Text_modification"; +Blockly.Msg.TEXT_LENGTH_TITLE = "length of %1"; +Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Returns the number of letters (including spaces) in the provided text."; +Blockly.Msg.TEXT_PRINT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Printing_text"; +Blockly.Msg.TEXT_PRINT_TITLE = "print %1"; +Blockly.Msg.TEXT_PRINT_TOOLTIP = "Print the specified text, number or other value."; +Blockly.Msg.TEXT_PROMPT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user"; +Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Prompt for user for a number."; +Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Prompt for user for some text."; +Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "prompt for number with message"; +Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "prompt for text with message"; +Blockly.Msg.TEXT_TEXT_HELPURL = "http://en.wikipedia.org/wiki/String_(computer_science)"; +Blockly.Msg.TEXT_TEXT_TOOLTIP = "A letter, word, or line of text."; +Blockly.Msg.TEXT_TRIM_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces"; +Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "trim spaces from both sides"; +Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "trim spaces from left side"; +Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "trim spaces from right side"; +Blockly.Msg.TEXT_TRIM_TOOLTIP = "Return a copy of the text with spaces removed from one or both ends."; +Blockly.Msg.VARIABLES_DEFAULT_NAME = "item"; +Blockly.Msg.VARIABLES_GET_CREATE_SET = "Create 'set %1'"; +Blockly.Msg.VARIABLES_GET_HELPURL = "http://code.google.com/p/blockly/wiki/Variables#Get"; +Blockly.Msg.VARIABLES_GET_TAIL = ""; +Blockly.Msg.VARIABLES_GET_TITLE = ""; +Blockly.Msg.VARIABLES_GET_TOOLTIP = "Returns the value of this variable."; +Blockly.Msg.VARIABLES_SET_CREATE_GET = "Create 'get %1'"; +Blockly.Msg.VARIABLES_SET_HELPURL = "http://code.google.com/p/blockly/wiki/Variables#Set"; +Blockly.Msg.VARIABLES_SET_TAIL = "to"; +Blockly.Msg.VARIABLES_SET_TITLE = "set"; +Blockly.Msg.VARIABLES_SET_TOOLTIP = "Sets this variable to be equal to the input."; +Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; +Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; +Blockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; +Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL; +Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; +Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; +Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; \ No newline at end of file diff --git a/msg/js/en_us.js b/msg/js/en_us.js new file mode 100644 index 000000000..e7e75182a --- /dev/null +++ b/msg/js/en_us.js @@ -0,0 +1,507 @@ +/** + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview English strings. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Msg.en_us'); + +goog.require('Blockly.Msg'); + + +/** + * Due to the frequency of long strings, the 80-column wrap rule need not apply + * to message files. + */ + +// Context menus. +Blockly.Msg.DUPLICATE_BLOCK = 'Duplicate'; +Blockly.Msg.REMOVE_COMMENT = 'Remove Comment'; +Blockly.Msg.ADD_COMMENT = 'Add Comment'; +Blockly.Msg.EXTERNAL_INPUTS = 'External Inputs'; +Blockly.Msg.INLINE_INPUTS = 'Inline Inputs'; +Blockly.Msg.DELETE_BLOCK = 'Delete Block'; +Blockly.Msg.DELETE_X_BLOCKS = 'Delete %1 Blocks'; +Blockly.Msg.COLLAPSE_BLOCK = 'Collapse Block'; +Blockly.Msg.EXPAND_BLOCK = 'Expand Block'; +Blockly.Msg.DISABLE_BLOCK = 'Disable Block'; +Blockly.Msg.ENABLE_BLOCK = 'Enable Block'; +Blockly.Msg.HELP = 'Help'; +Blockly.Msg.COLLAPSE_ALL = 'Collapse Blocks'; +Blockly.Msg.EXPAND_ALL = 'Expand Blocks'; + +// Variable renaming. +Blockly.Msg.CHANGE_VALUE_TITLE = 'Change value:'; +Blockly.Msg.NEW_VARIABLE = 'New variable...'; +Blockly.Msg.NEW_VARIABLE_TITLE = 'New variable name:'; +Blockly.Msg.RENAME_VARIABLE = 'Rename variable...'; +Blockly.Msg.RENAME_VARIABLE_TITLE = 'Rename all "%1" variables to:'; + +// Colour Blocks. +Blockly.Msg.COLOUR_PICKER_HELPURL = 'http://en.wikipedia.org/wiki/Color'; +Blockly.Msg.COLOUR_PICKER_TOOLTIP = 'Choose a color from the palette.'; + +Blockly.Msg.COLOUR_RANDOM_HELPURL = 'http://randomcolour.com'; +Blockly.Msg.COLOUR_RANDOM_TITLE = 'random color'; +Blockly.Msg.COLOUR_RANDOM_TOOLTIP = 'Choose a color at random.'; + +Blockly.Msg.COLOUR_RGB_HELPURL = 'http://www.december.com/html/spec/colorper.html'; +Blockly.Msg.COLOUR_RGB_TITLE = 'color with'; +Blockly.Msg.COLOUR_RGB_RED = 'red'; +Blockly.Msg.COLOUR_RGB_GREEN = 'green'; +Blockly.Msg.COLOUR_RGB_BLUE = 'blue'; +Blockly.Msg.COLOUR_RGB_TOOLTIP = 'Create a color with the specified amount of red, green,\n' + + 'and blue. All values must be between 0 and 100.'; + +Blockly.Msg.COLOUR_BLEND_HELPURL = 'http://meyerweb.com/eric/tools/color-blend/'; +Blockly.Msg.COLOUR_BLEND_TITLE = 'blend'; +Blockly.Msg.COLOUR_BLEND_COLOUR1 = 'color 1'; +Blockly.Msg.COLOUR_BLEND_COLOUR2 = 'color 2'; +Blockly.Msg.COLOUR_BLEND_RATIO = 'ratio'; +Blockly.Msg.COLOUR_BLEND_TOOLTIP = 'Blends two colors together with a given ratio (0.0 - 1.0).'; + +// Loop Blocks. +Blockly.Msg.CONTROLS_REPEAT_HELPURL = 'http://en.wikipedia.org/wiki/For_loop'; +Blockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = 'repeat'; +Blockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = 'times'; +Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = 'do'; +Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = 'Do some statements several times.'; + +Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = 'http://code.google.com/p/blockly/wiki/Repeat'; +Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = 'do'; +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = 'repeat while'; +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = 'repeat until'; +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = 'While a value is true, then do some statements.'; +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = 'While a value is false, then do some statements.'; + +Blockly.Msg.CONTROLS_FOR_HELPURL = 'http://en.wikipedia.org/wiki/For_loop'; +Blockly.Msg.CONTROLS_FOR_INPUT_WITH = 'count with'; +Blockly.Msg.CONTROLS_FOR_INPUT_VAR = 'x'; +Blockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = 'from %1 to %2 y %3'; +Blockly.Msg.CONTROLS_FOR_INPUT_DO = 'do'; +Blockly.Msg.CONTROLS_FOR_TAIL = ''; +Blockly.Msg.CONTROLS_FOR_TOOLTIP = 'Count from a start number to an end number by the specified interval.\n' + + 'For each count, set the current count number to\n' + + 'variable "%1", and then do some statements.'; + +Blockly.Msg.CONTROLS_FOREACH_HELPURL = 'http://en.wikipedia.org/wiki/For_loop'; +Blockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = 'for each item'; +Blockly.Msg.CONTROLS_FOREACH_INPUT_VAR = 'x'; +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = 'in list'; +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = ''; +Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = 'do'; +Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = 'For each item in a list, set the item to\n' + + 'variable "%1", and then do some statements.'; + +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = 'http://en.wikipedia.org/wiki/Control_flow'; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = 'break out of loop'; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = 'continue with next iteration of loop'; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = 'Break out of the containing loop.'; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = 'Skip the rest of this loop, and\n' + + 'continue with the next iteration.'; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = 'Warning:\n' + + 'This block may only\n' + + 'be used within a loop.'; + +// Logic Blocks. +Blockly.Msg.CONTROLS_IF_HELPURL = 'http://code.google.com/p/blockly/wiki/If_Then'; +Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = 'If a value is true, then do some statements.'; +Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = 'If a value is true, then do the first block of statements.\n' + + 'Otherwise, do the second block of statements.'; +Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = 'If the first value is true, then do the first block of statements.\n' + + 'Otherwise, if the second value is true, do the second block of statements.'; +Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = 'If the first value is true, then do the first block of statements.\n' + + 'Otherwise, if the second value is true, do the second block of statements.\n' + + 'If none of the values are true, do the last block of statements.'; +Blockly.Msg.CONTROLS_IF_MSG_IF = 'if'; +Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = 'else if'; +Blockly.Msg.CONTROLS_IF_MSG_ELSE = 'else'; +Blockly.Msg.CONTROLS_IF_MSG_THEN = 'do'; +Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = 'if'; +Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = 'Add, remove, or reorder sections\n' + + 'to reconfigure this if block.'; +Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = 'else if'; +Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = 'Add a condition to the if block.'; +Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = 'else'; +Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = 'Add a final, catch-all condition to the if block.'; + +Blockly.Msg.LOGIC_COMPARE_HELPURL = 'http://en.wikipedia.org/wiki/Inequality_(mathematics)'; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = 'Return true if both inputs equal each other.'; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = 'Return true if both inputs are not equal to each other.'; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = 'Return true if the first input is smaller\n' + + 'than the second input.'; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = 'Return true if the first input is smaller\n' + + 'than or equal to the second input.'; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = 'Return true if the first input is greater\n' + + 'than the second input.'; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = 'Return true if the first input is greater\n' + + 'than or equal to the second input.'; + +Blockly.Msg.LOGIC_OPERATION_HELPURL = 'http://code.google.com/p/blockly/wiki/And_Or'; +Blockly.Msg.LOGIC_OPERATION_AND = 'and'; +Blockly.Msg.LOGIC_OPERATION_OR = 'or'; +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = 'Return true if both inputs are true.'; +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = 'Return true if either inputs are true.'; + +Blockly.Msg.LOGIC_NEGATE_HELPURL = 'http://code.google.com/p/blockly/wiki/Not'; +Blockly.Msg.LOGIC_NEGATE_INPUT_NOT = 'not'; +Blockly.Msg.LOGIC_NEGATE_TOOLTIP = 'Returns true if the input is false.\n' + + 'Returns false if the input is true.'; + +Blockly.Msg.LOGIC_BOOLEAN_HELPURL = 'http://code.google.com/p/blockly/wiki/True_False'; +Blockly.Msg.LOGIC_BOOLEAN_TRUE = 'true'; +Blockly.Msg.LOGIC_BOOLEAN_FALSE = 'false'; +Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = 'Returns either true or false.'; + +Blockly.Msg.LOGIC_NULL_HELPURL = 'http://en.wikipedia.org/wiki/Nullable_type'; +Blockly.Msg.LOGIC_NULL = 'null'; +Blockly.Msg.LOGIC_NULL_TOOLTIP = 'Returns null.'; + +Blockly.Msg.LOGIC_TERNARY_HELPURL = 'http://en.wikipedia.org/wiki/%3F:'; +Blockly.Msg.LOGIC_TERNARY_CONDITION = 'test'; +Blockly.Msg.LOGIC_TERNARY_IF_TRUE = 'if true'; +Blockly.Msg.LOGIC_TERNARY_IF_FALSE = 'if false'; +Blockly.Msg.LOGIC_TERNARY_TOOLTIP = 'Check the condition in "test". If the condition is true\n' + + 'returns the "if true" value, otherwise returns the "if false" value.'; + +// Math Blocks. +Blockly.Msg.MATH_NUMBER_HELPURL = 'http://en.wikipedia.org/wiki/Number'; +Blockly.Msg.MATH_NUMBER_TOOLTIP = 'A number.'; + +Blockly.Msg.MATH_ARITHMETIC_HELPURL = 'http://en.wikipedia.org/wiki/Arithmetic'; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = 'Return the sum of the two numbers.'; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = 'Return the difference of the two numbers.'; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = 'Return the product of the two numbers.'; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = 'Return the quotient of the two numbers.'; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = 'Return the first number raised to\n' + + 'the power of the second number.'; + +Blockly.Msg.MATH_SINGLE_HELPURL = 'http://en.wikipedia.org/wiki/Square_root'; +Blockly.Msg.MATH_SINGLE_OP_ROOT = 'square root'; +Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = 'absolute'; +Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = 'Return the square root of a number.'; +Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = 'Return the absolute value of a number.'; +Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = 'Return the negation of a number.'; +Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = 'Return the natural logarithm of a number.'; +Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = 'Return the base 10 logarithm of a number.'; +Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = 'Return e to the power of a number.'; +Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = 'Return 10 to the power of a number.'; + +Blockly.Msg.MATH_TRIG_HELPURL = 'http://en.wikipedia.org/wiki/Trigonometric_functions'; +Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = 'Return the sine of a degree (not radian).'; +Blockly.Msg.MATH_TRIG_TOOLTIP_COS = 'Return the cosine of a degree (not radian).'; +Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = 'Return the tangent of a degree (not radian).'; +Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = 'Return the arcsine of a number.'; +Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = 'Return the arccosine of a number.'; +Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = 'Return the arctangent of a number.'; + +Blockly.Msg.MATH_CONSTANT_HELPURL = 'http://en.wikipedia.org/wiki/Mathematical_constant'; +Blockly.Msg.MATH_CONSTANT_TOOLTIP = 'Return one of the common constants: \u03c0 (3.141\u2026), e (2.718\u2026), \u03c6 (1.618\u2026),\n' + + 'sqrt(2) (1.414\u2026), sqrt(\u00bd) (0.707\u2026), or \u221e (infinity).'; + +Blockly.Msg.MATH_IS_EVEN = 'is even'; +Blockly.Msg.MATH_IS_ODD = 'is odd'; +Blockly.Msg.MATH_IS_PRIME = 'is prime'; +Blockly.Msg.MATH_IS_WHOLE = 'is whole'; +Blockly.Msg.MATH_IS_POSITIVE = 'is positive'; +Blockly.Msg.MATH_IS_NEGATIVE = 'is negative'; +Blockly.Msg.MATH_IS_DIVISIBLE_BY = 'is divisible by'; +Blockly.Msg.MATH_IS_TOOLTIP = 'Check if a number is an even, odd, prime, whole, positive, negative,\n' + + 'or if it is divisible by certain number. Returns true or false.'; + +Blockly.Msg.MATH_CHANGE_HELPURL = 'http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter'; +Blockly.Msg.MATH_CHANGE_TITLE_CHANGE = 'change'; +Blockly.Msg.MATH_CHANGE_TITLE_ITEM = 'item'; +Blockly.Msg.MATH_CHANGE_INPUT_BY = 'by'; +Blockly.Msg.MATH_CHANGE_TOOLTIP = 'Add a number to variable "%1".'; + +Blockly.Msg.MATH_ROUND_HELPURL = 'http://en.wikipedia.org/wiki/Rounding'; +Blockly.Msg.MATH_ROUND_TOOLTIP = 'Round a number up or down.'; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = 'round'; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = 'round up'; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = 'round down'; + +Blockly.Msg.MATH_ONLIST_HELPURL = ''; +Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = 'sum of list'; +Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = 'min of list'; +Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = 'max of list'; +Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = 'average of list'; +Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = 'median of list'; +Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = 'modes of list'; +Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = 'standard deviation of list'; +Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = 'random item of list'; +Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = 'Return the sum of all the numbers in the list.'; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = 'Return the smallest number in the list.'; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = 'Return the largest number in the list.'; +Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = 'Return the arithmetic mean of the list.'; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = 'Return the median number in the list.'; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = 'Return a list of the most common item(s) in the list.'; +Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = 'Return the standard deviation of the list.'; +Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = 'Return a random element from the list.'; + +Blockly.Msg.MATH_MODULO_HELPURL = 'http://en.wikipedia.org/wiki/Modulo_operation'; +Blockly.Msg.MATH_MODULO_INPUT_DIVIDEND = 'remainder of'; +Blockly.Msg.MATH_MODULO_TOOLTIP = 'Return the remainder from dividing the two numbers.'; + +Blockly.Msg.MATH_CONSTRAIN_HELPURL = 'http://en.wikipedia.org/wiki/Clamping_%28graphics%29'; +Blockly.Msg.MATH_CONSTRAIN_INPUT_CONSTRAIN = 'constrain'; +Blockly.Msg.MATH_CONSTRAIN_INPUT_LOW = 'low'; +Blockly.Msg.MATH_CONSTRAIN_INPUT_HIGH = 'high'; +Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = 'Constrain a number to be between the specified limits (inclusive).'; + +Blockly.Msg.MATH_RANDOM_INT_HELPURL = 'http://en.wikipedia.org/wiki/Random_number_generation'; +Blockly.Msg.MATH_RANDOM_INT_TITLE = 'random integer from %1 to %2'; +Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = 'Return a random integer between the two\n' + + 'specified limits, inclusive.'; + +Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = 'http://en.wikipedia.org/wiki/Random_number_generation'; +Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = 'random fraction'; +Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = 'Return a random fraction between\n' + + '0.0 (inclusive) and 1.0 (exclusive).'; + +// Text Blocks. +Blockly.Msg.TEXT_TEXT_HELPURL = 'http://en.wikipedia.org/wiki/String_(computer_science)'; +Blockly.Msg.TEXT_TEXT_TOOLTIP = 'A letter, word, or line of text.'; + +Blockly.Msg.TEXT_JOIN_HELPURL = ''; +Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = 'create text with'; +Blockly.Msg.TEXT_JOIN_TOOLTIP = 'Create a piece of text by joining\n' + + 'together any number of items.'; + +Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = 'join'; +Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = 'Add, remove, or reorder sections to reconfigure this text block.'; + +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = 'item'; +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = 'Add an item to the text.'; + +Blockly.Msg.TEXT_APPEND_HELPURL = 'http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html'; +Blockly.Msg.TEXT_APPEND_TO = 'to'; +Blockly.Msg.TEXT_APPEND_APPENDTEXT = 'append text'; +Blockly.Msg.TEXT_APPEND_VARIABLE = 'item'; +Blockly.Msg.TEXT_APPEND_TOOLTIP = 'Append some text to variable "%1".'; + +Blockly.Msg.TEXT_LENGTH_HELPURL = 'http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html'; +Blockly.Msg.TEXT_LENGTH_INPUT_LENGTH = 'length of'; +Blockly.Msg.TEXT_LENGTH_TOOLTIP = 'Returns number of letters (including spaces)\n' + + 'in the provided text.'; + +Blockly.Msg.TEXT_ISEMPTY_HELPURL = 'http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html'; +Blockly.Msg.TEXT_ISEMPTY_INPUT_ISEMPTY = 'is empty'; +Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = 'Returns true if the provided text is empty.'; + +Blockly.Msg.TEXT_INDEXOF_HELPURL = 'http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm'; +Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = 'in text'; +Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = 'find first occurrence of text'; +Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = 'find last occurrence of text'; +Blockly.Msg.TEXT_INDEXOF_TOOLTIP = 'Returns the index of the first/last occurrence\n' + + 'of first text in the second text.\n' + + 'Returns 0 if text is not found.'; + +Blockly.Msg.TEXT_CHARAT_HELPURL = 'http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm'; +Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = 'in text'; +Blockly.Msg.TEXT_CHARAT_FROM_START = 'get letter #'; +Blockly.Msg.TEXT_CHARAT_FROM_END = 'get letter # from end'; +Blockly.Msg.TEXT_CHARAT_FIRST = 'get first letter'; +Blockly.Msg.TEXT_CHARAT_LAST = 'get last letter'; +Blockly.Msg.TEXT_CHARAT_RANDOM = 'get random letter'; +Blockly.Msg.TEXT_CHARAT_TOOLTIP = 'Returns the letter at the specified position.'; + +Blockly.Msg.TEXT_SUBSTRING_HELPURL = 'http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm'; +Blockly.Msg.TEXT_SUBSTRING_INPUT_IN_TEXT = 'in text'; +Blockly.Msg.TEXT_SUBSTRING_INPUT_AT1 = 'get substring from'; +Blockly.Msg.TEXT_SUBSTRING_INPUT_AT2 = 'to'; +Blockly.Msg.TEXT_SUBSTRING_FROM_START = 'letter #'; +Blockly.Msg.TEXT_SUBSTRING_FROM_END = 'letter # from end'; +Blockly.Msg.TEXT_SUBSTRING_FIRST = 'first letter'; +Blockly.Msg.TEXT_SUBSTRING_LAST = 'last letter'; +Blockly.Msg.TEXT_SUBSTRING_TOOLTIP = 'Returns a specified portion of the text.'; + +Blockly.Msg.TEXT_CHANGECASE_HELPURL = 'http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html'; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = 'to UPPER CASE'; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = 'to lower case'; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = 'to Title Case'; +Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = 'Return a copy of the text in a different case.'; + +Blockly.Msg.TEXT_TRIM_HELPURL = 'http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html'; +Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = 'trim spaces from both sides'; +Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = 'trim spaces from left side'; +Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = 'trim spaces from right side'; +Blockly.Msg.TEXT_TRIM_TOOLTIP = 'Return a copy of the text with spaces\n' + + 'removed from one or both ends.'; + +Blockly.Msg.TEXT_PRINT_HELPURL = 'http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html'; +Blockly.Msg.TEXT_PRINT_TITLE_PRINT = 'print'; +Blockly.Msg.TEXT_PRINT_TOOLTIP = 'Print the specified text, number or other value.'; + +Blockly.Msg.TEXT_PROMPT_HELPURL = 'http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode92.html'; +Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = 'prompt for text with message'; +Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = 'prompt for number with message'; +Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = 'Prompt for user for a number.'; +Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = 'Prompt for user for some text.'; + +// Lists Blocks. +Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = 'http://en.wikipedia.org/wiki/Linked_list#Empty_lists'; +Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = 'create empty list'; +Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = 'Returns a list, of length 0, containing no data records'; + +Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = 'create list with'; +Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = 'Create a list with any number of items.'; + +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = 'list'; +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = 'Add, remove, or reorder sections to reconfigure this list block.'; + +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = 'item'; +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = 'Add an item to the list.'; + +Blockly.Msg.LISTS_REPEAT_HELPURL = 'http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm'; +Blockly.Msg.LISTS_REPEAT_INPUT_WITH = 'create list with item'; +Blockly.Msg.LISTS_REPEAT_INPUT_REPEATED = 'repeated'; +Blockly.Msg.LISTS_REPEAT_INPUT_TIMES = 'times'; +Blockly.Msg.LISTS_REPEAT_TOOLTIP = 'Creates a list consisting of the given value\n' + + 'repeated the specified number of times.'; + +Blockly.Msg.LISTS_LENGTH_HELPURL = 'http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html'; +Blockly.Msg.LISTS_LENGTH_INPUT_LENGTH = 'length of'; +Blockly.Msg.LISTS_LENGTH_TOOLTIP = 'Returns the length of a list.'; + +Blockly.Msg.LISTS_IS_EMPTY_HELPURL = 'http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html'; +Blockly.Msg.LISTS_INPUT_IS_EMPTY = 'is empty'; +Blockly.Msg.LISTS_TOOLTIP = 'Returns true if the list is empty.'; + +Blockly.Msg.LISTS_INDEX_OF_HELPURL = 'http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm'; +Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = 'in list'; +Blockly.Msg.LISTS_INDEX_OF_FIRST = 'find first occurrence of item'; +Blockly.Msg.LISTS_INDEX_OF_LAST = 'find last occurrence of item'; +Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = 'Returns the index of the first/last occurrence\n' + + 'of the item in the list.\n' + + 'Returns 0 if text is not found.'; + +Blockly.Msg.LISTS_GET_INDEX_HELPURL = 'http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm'; +Blockly.Msg.LISTS_GET_INDEX_GET = 'get'; +Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = 'get and remove'; +Blockly.Msg.LISTS_GET_INDEX_REMOVE = 'remove'; +Blockly.Msg.LISTS_GET_INDEX_FROM_START = '#'; +Blockly.Msg.LISTS_GET_INDEX_FROM_END = '# from end'; +Blockly.Msg.LISTS_GET_INDEX_FIRST = 'first'; +Blockly.Msg.LISTS_GET_INDEX_LAST = 'last'; +Blockly.Msg.LISTS_GET_INDEX_RANDOM = 'random'; +Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = 'in list'; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = 'Returns the item at the specified position in a list.\n' + + '#1 is the first item.'; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = 'Returns the item at the specified position in a list.\n' + + '#1 is the last item.'; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = 'Returns the first item in a list.'; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = 'Returns the last item in a list.'; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = 'Returns a random item in a list.'; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = 'Removes and returns the item at the specified position\n' + + ' in a list. #1 is the first item.'; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = 'Removes and returns the item at the specified position\n' + + ' in a list. #1 is the last item.'; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = 'Removes and returns the first item in a list.'; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = 'Removes and returns the last item in a list.'; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = 'Removes and returns a random item in a list.'; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = 'Removes the item at the specified position\n' + + ' in a list. #1 is the first item.'; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = 'Removes the item at the specified position\n' + + ' in a list. #1 is the last item.'; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = 'Removes the first item in a list.'; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = 'Removes the last item in a list.'; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = 'Removes a random item in a list.'; + +Blockly.Msg.LISTS_SET_INDEX_HELPURL = 'http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm'; +Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = 'in list'; +Blockly.Msg.LISTS_SET_INDEX_SET = 'set'; +Blockly.Msg.LISTS_SET_INDEX_INSERT = 'insert at'; +Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = 'as'; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = 'Sets the item at the specified position in a list.\n' + + '#1 is the first item.'; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = 'Sets the item at the specified position in a list.\n' + + '#1 is the last item.'; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = 'Sets the first item in a list.'; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = 'Sets the last item in a list.'; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = 'Sets a random item in a list.'; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = 'Inserts the item at the specified position in a list.\n' + + '#1 is the first item.'; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = 'Inserts the item at the specified position in a list.\n' + + '#1 is the last item.'; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = 'Inserts the item at the start of a list.'; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = 'Append the item to the end of a list.'; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = 'Inserts the item randomly in a list.'; + +Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = 'http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm'; +Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = 'in list'; +Blockly.Msg.LISTS_GET_SUBLIST_INPUT_AT1 = 'get sub-list from'; +Blockly.Msg.LISTS_GET_SUBLIST_INPUT_AT2 = 'to'; +Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = 'Creates a copy of the specified portion of a list.'; + +// Variables Blocks. +Blockly.Msg.VARIABLES_GET_HELPURL = 'http://en.wikipedia.org/wiki/Variable_(computer_science)'; +Blockly.Msg.VARIABLES_GET_TITLE = ''; +Blockly.Msg.VARIABLES_GET_ITEM = 'item'; +Blockly.Msg.VARIABLES_GET_TAIL = ''; +Blockly.Msg.VARIABLES_GET_TOOLTIP = 'Returns the value of this variable.'; +Blockly.Msg.VARIABLES_GET_CREATE_SET = 'Create "set %1"'; + +Blockly.Msg.VARIABLES_SET_HELPURL = 'http://en.wikipedia.org/wiki/Variable_(computer_science)'; +Blockly.Msg.VARIABLES_SET_TITLE = 'set'; +Blockly.Msg.VARIABLES_SET_ITEM = 'item'; +Blockly.Msg.VARIABLES_SET_TAIL = 'to'; +Blockly.Msg.VARIABLES_SET_TOOLTIP = 'Sets this variable to be equal to the input.'; +Blockly.Msg.VARIABLES_SET_CREATE_GET = 'Create "get %1"'; + +// Procedures Blocks. +Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = 'http://en.wikipedia.org/wiki/Procedure_%28computer_science%29'; +Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = 'to'; +Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = 'do something'; +Blockly.Msg.PROCEDURES_BEFORE_PARAMS = 'with:'; +Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ''; +Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = 'Creates a function with no output.'; + +Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = 'http://en.wikipedia.org/wiki/Procedure_%28computer_science%29'; +Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; +Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; +Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; +Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = 'return'; +Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = 'Creates a function with an output.'; + +Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = 'Warning:\n' + + 'This function has\n' + + 'duplicate parameters.'; + +Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = 'http://en.wikipedia.org/wiki/Procedure_%28computer_science%29'; +Blockly.Msg.PROCEDURES_CALLNORETURN_CALL = ''; +Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = 'Run the user-defined function "%1".'; + +Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = 'http://en.wikipedia.org/wiki/Procedure_%28computer_science%29'; +Blockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL; +Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = 'Run the user-defined function "%1" and use its output.'; + +Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = 'inputs'; +Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = 'input name:'; + +Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = 'Highlight procedure definition'; +Blockly.Msg.PROCEDURES_CREATE_DO = 'Create "%1"'; + +Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = 'If a value is true, then return a value.'; +Blockly.Msg.PROCEDURES_IFRETURN_WARNING = 'Warning:\n' + + 'This block may only be\n' + + 'used within a function definition.'; diff --git a/msg/js/fa.js b/msg/js/fa.js new file mode 100644 index 000000000..35c41c8da --- /dev/null +++ b/msg/js/fa.js @@ -0,0 +1,377 @@ +// This file was automatically generated. Do not modify. + +'use strict'; + +goog.provide('Blockly.Msg.fa'); + +goog.require('Blockly.Msg'); + +Blockly.Msg.ADD_COMMENT = "افزودن نظر"; +Blockly.Msg.CHANGE_VALUE_TITLE = "تغییر مقدار:"; +Blockly.Msg.COLLAPSE_ALL = "فروپاشی بلوک‌ها"; +Blockly.Msg.COLLAPSE_BLOCK = "فروپاشی بلوک"; +Blockly.Msg.COLOUR_BLEND_COLOUR1 = "رنگ ۱"; +Blockly.Msg.COLOUR_BLEND_COLOUR2 = "رنگ ۲"; +Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated +Blockly.Msg.COLOUR_BLEND_RATIO = "نسبت"; +Blockly.Msg.COLOUR_BLEND_TITLE = "مخلوط"; +Blockly.Msg.COLOUR_BLEND_TOOLTIP = "دو رنگ را با نسبت مشخص‌شده مخلوط می‌کند (۰٫۰ - ۱٫۰)"; +Blockly.Msg.COLOUR_PICKER_HELPURL = "http://fa.wikipedia.org/wiki/%D8%B1%D9%86%DA%AF"; +Blockly.Msg.COLOUR_PICKER_TOOLTIP = "انتخاب یک رنگ از تخته‌رنگ."; +Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated +Blockly.Msg.COLOUR_RANDOM_TITLE = "رنگ تصادفی"; +Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "انتخاب یک رنگ به شکل تصادفی."; +Blockly.Msg.COLOUR_RGB_BLUE = "آبی"; +Blockly.Msg.COLOUR_RGB_GREEN = "سبز"; +Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated +Blockly.Msg.COLOUR_RGB_RED = "قرمز"; +Blockly.Msg.COLOUR_RGB_TITLE = "رنگ با"; +Blockly.Msg.COLOUR_RGB_TOOLTIP = "ساخت یک رنگ با مقدار مشخص‌شده‌ای از قرمز، سبز و آبی. همهٔ مقادیر باید بین ۰ تا ۱۰۰ باشند."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks"; // untranslated +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "شکستن حلقه"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "ادامه با تکرار بعدی حلقه"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "شکستن حلقهٔ شامل."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "پریدن از بقیهٔ حلقه و ادامه با تکرار بعدی."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "اخطار: این بلوک ممکن است فقط داخل یک حلقه استفاده شود."; +Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#for_each for each block"; // untranslated +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = "در فهرست"; +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = ""; // untranslated +Blockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = "برای هر مورد"; +Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "برای هر مورد در این فهرست، تنظیم متغیر «%1» به مورد و انجام تعدادی عبارت."; +Blockly.Msg.CONTROLS_FOR_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#count_with"; // untranslated +Blockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = "از %1 به %2 با گام‌های %3"; +Blockly.Msg.CONTROLS_FOR_INPUT_WITH = "با تعداد"; +Blockly.Msg.CONTROLS_FOR_TOOLTIP = "متغیر %1 را در مقادیر شروع‌شده از عدد انتهای به عدد انتهایی را دارد، با فواصل مشخص‌شده می‌شمارد و این بلوک مشخص‌شده را انجام می‌دهد."; +Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "افزودن یک شرط به بلوک اگر."; +Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "اضافه‌کردن نهایی، گرفتن همهٔ شرایط به بلوک اگر."; +Blockly.Msg.CONTROLS_IF_HELPURL = "http://code.google.com/p/blockly/wiki/If_Then"; // untranslated +Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "اضافه، حذف یا ترتیب‌سازی قسمت‌ها برای تنظیم مجدد این بلوک اگر مسدود است."; +Blockly.Msg.CONTROLS_IF_MSG_ELSE = "آنگاه"; +Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "اگر آنگاه"; +Blockly.Msg.CONTROLS_IF_MSG_IF = "اگر"; +Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "اگر یک مقدار صحیح است، سپس چند عبارت را انجام بده."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "اگر یک مقدار صحیح است، اول بلوک اول عبارات را انجام بده. در غیر این صورت بلوک دوم عبارات انجام بده."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "اگر مقدار اول صحیح بود، از آن بلوک اول عبارات را انجام بده. در غیر این صورت، اگر مقدار دوم صحیح است، بلوک دوم عبارات را انجام بده."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "اگر مقدار اول درست است، بلوک اول عبارات را انجام بده. در غیر این صورت، اگر مقدار دوم درست باشد بلوک دوم عبارات را انجام بده. اگر هیچ از مقادیر درست نبود، آخرین بلوک عبارات را انجام بده."; +Blockly.Msg.CONTROLS_REPEAT_HELPURL = "http://fa.wikipedia.org/wiki/%D8%AD%D9%84%D9%82%D9%87_%D9%81%D9%88%D8%B1"; +Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "انحام"; +Blockly.Msg.CONTROLS_REPEAT_TITLE = "%1 بار تکرار"; +Blockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = "تکرار"; +Blockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = "بار"; +Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "انجام چند عبارت چندین بار."; +Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "http://code.google.com/p/blockly/wiki/Repeat"; // untranslated +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "تکرار تا زمانی که"; +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "تکرار در حالی که"; +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "تا زمانی که یک مقدار ناصحیح است، چند عبارت را انجام بده."; +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "تا زمانی که یک مقدار صحیح است، چند عبارت را انجام بده."; +Blockly.Msg.DELETE_BLOCK = "حذف بلوک"; +Blockly.Msg.DELETE_X_BLOCKS = "حذف بلوک‌های %1"; +Blockly.Msg.DISABLE_BLOCK = "غیرفعال‌سازی بلوک"; +Blockly.Msg.DUPLICATE_BLOCK = "تکراری"; +Blockly.Msg.ENABLE_BLOCK = "فعال‌سازی بلوک"; +Blockly.Msg.EXPAND_ALL = "گسترش بلوک‌ها"; +Blockly.Msg.EXPAND_BLOCK = "گسترش بلوک"; +Blockly.Msg.EXTERNAL_INPUTS = "ورودی‌های خارجی"; +Blockly.Msg.HELP = "راهنما"; +Blockly.Msg.INLINE_INPUTS = "ورودی‌های درون خطی"; +Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "http://en.wikipedia.org/wiki/Linked_list#Empty_lists"; // untranslated +Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "ایجاد فهرست خالی"; +Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "فهرستی با طول صفر شامل هیچ رکورد داده‌ای بر می‌گرداند."; +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "فهرست"; +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "اضافه‌کردن، حذف‌کردن یا ترتیب‌سازی مجدد بخش‌ها این بلوک فهرستی."; +Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "ایجاد فهرست با"; +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "اضافه‌کردن یک مورد به فهرست."; +Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "فهرستی از هر عددی از موارد می‌سازد."; +Blockly.Msg.LISTS_GET_INDEX_FIRST = "اولین"; +Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# از انتها"; +Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated +Blockly.Msg.LISTS_GET_INDEX_GET = "گرفتن"; +Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "گرفتن و حذف‌کردن"; +Blockly.Msg.LISTS_GET_INDEX_LAST = "آخرین"; +Blockly.Msg.LISTS_GET_INDEX_RANDOM = "تصادفی"; +Blockly.Msg.LISTS_GET_INDEX_REMOVE = "حذف‌کردن"; +Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "اولین مورد یک فهرست را بر می‌گرداند."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = "موردی در محل مشخص در فهرست بر می‌گرداند. #1 آخرین مورد است."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = "موردی در محل مشخص‌شده بر می‌گرداند. #1 اولین مورد است."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "آخرین مورد در یک فهرست را بر می‌گرداند."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "یک مورد تصادفی در یک فهرست بر می‌گرداند."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "اولین مورد مشخص‌شده در فهرست را حذف و بر می‌گرداند."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = "مورد در محل مشخص‌شده در فهرست را حذف و بر می‌گرداند. #1 آخرین مورد است."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = "مورد در محل مشخص‌شده در فهرست را حذف و بر می‌گرداند. #1 اولین مورد است."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "آخرین مورد مشخص‌شده در فهرست را حذف و بر می‌گرداند."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "مورد تصادفی‌ای را در فهرست حذف و بر می‌گرداند."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "اولین مورد را در یک فهرست حذف می‌کند."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = "مورد مشخص‌شده در موقعیت مشخص در یک فهرست را حذف و بر می‌گرداند. #1 آخرین مورد است."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = "مورد مشخص‌شده در موقعیت مشخص در یک فهرست را حذف و بر می‌گرداند. #1 اولین مورد است."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "آخرین مورد را در یک فهرست حذف می‌کند."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "یک مورد تصادفی را یک فهرست حذف می‌کند."; +Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "به # از انتها"; +Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "به #"; +Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "به آخرین"; +Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist"; // untranslated +Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "گرفتن زیرمجموعه‌ای از ابتدا"; +Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "گرفتن زیرمجموعه‌ای از # از انتها"; +Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "گرفتن زیرمجموعه‌ای از #"; +Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated +Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "کپی از قسمت مشخص‌شدهٔ لیست درست می‌کند."; +Blockly.Msg.LISTS_INDEX_OF_FIRST = "یافتن اولین رخ‌داد مورد"; +Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List"; // untranslated +Blockly.Msg.LISTS_INDEX_OF_LAST = "یافتن آخرین رخ‌داد مورد"; +Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "شاخصی از اولین/آخرین رخ‌داد مورد در فهرست را بر می‌گرداند. ۰ بر می‌گرداند اگر متن موجود نبود."; +Blockly.Msg.LISTS_INLIST = "در فهرست"; +Blockly.Msg.LISTS_IS_EMPTY_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#is_empty"; // untranslated +Blockly.Msg.LISTS_IS_EMPTY_TITLE = "%1 خالی است"; +Blockly.Msg.LISTS_LENGTH_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#length_of"; // untranslated +Blockly.Msg.LISTS_LENGTH_TITLE = "طول %1"; +Blockly.Msg.LISTS_LENGTH_TOOLTIP = "طول یک فهرست را برمی‌گرداند."; +Blockly.Msg.LISTS_REPEAT_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#create_list_with"; // untranslated +Blockly.Msg.LISTS_REPEAT_TITLE = "فهرستی با %1 تکرارشده به اندازهٔ %2 می‌سازد"; +Blockly.Msg.LISTS_REPEAT_TOOLTIP = "فهرستی شامل مقادیر داده‌شدهٔ تکرار شده عدد مشخص‌شده می‌سازد."; +Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#in_list_..._set"; // untranslated +Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "به‌عنوان"; +Blockly.Msg.LISTS_SET_INDEX_INSERT = "درج در"; +Blockly.Msg.LISTS_SET_INDEX_SET = "مجموعه"; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "موردی به ته فهرست اضافه می‌کند."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = "موردی در موقعیت مشخص‌شده در یک فهرست اضافه می‌کند. #1 آخرین مورد است."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = "موردی در موقعیت مشخص‌شده در یک فهرست اضافه می‌کند. #1 اولین مورد است."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "موردی به ته فهرست الحاق می‌کند."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "مورد را به صورت تصادفی در یک فهرست می‌افزاید."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "اولین مورد در یک فهرست را تعیین می‌کند."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = "مورد مشخص‌شده در یک فهرست را قرار می‌دهد. #1 آخرین مورد است."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = "مورد مشخص‌شده در یک فهرست را قرار می‌دهد. #1 اولین مورد است."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "آخرین مورد در یک فهرست را تعیین می‌کند."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "یک مورد تصادفی در یک فهرست را تعیین می‌کند."; +Blockly.Msg.LISTS_TOOLTIP = "اگر فهرست خالی است مقدار صجیج بر می‌گرداند."; +Blockly.Msg.LOGIC_BOOLEAN_FALSE = "ناصحیح"; +Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "http://code.google.com/p/blockly/wiki/True_False"; // untranslated +Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "بازگرداندن یکی از صحیح یا ناصحیح."; +Blockly.Msg.LOGIC_BOOLEAN_TRUE = "صحیح"; +Blockly.Msg.LOGIC_COMPARE_HELPURL = "http://fa.wikipedia.org/wiki/%D9%86%D8%A7%D8%A8%D8%B1%D8%A7%D8%A8%D8%B1%DB%8C"; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "بازگشت صحیح اگر هر دو ورودی با یکدیگر برابر باشد."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "بازگرداندن صحیح اگر ورودی اول بزرگتر از ورودی دوم باشد."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "بازگرداندن صحیح اگر ورودی اول بزرگتر یا مساوی یا ورودی دوم باشد."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "بازگرداندن صحیح اگر ورودی اول کوچکتر از ورودی دوم باشد."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "بازگرداندن صحیح اگر ورودی اول کوچکتر یا مساوی با ورودی دوم باشد."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "برگرداندن صحیح اگر هر دو ورودی با یکدیگر برابر نباشند."; +Blockly.Msg.LOGIC_NEGATE_HELPURL = "http://code.google.com/p/blockly/wiki/Not"; // untranslated +Blockly.Msg.LOGIC_NEGATE_TITLE = "نه %1"; +Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "صجیج باز می‌گرداند اگر ورودی نا صحیح باشند. ناصحیح بازمی‌گرداند اگر ورودی صحیح باشد."; +Blockly.Msg.LOGIC_NULL = "تهی"; +Blockly.Msg.LOGIC_NULL_HELPURL = "http://en.wikipedia.org/wiki/Nullable_type"; // untranslated +Blockly.Msg.LOGIC_NULL_TOOLTIP = "تهی بازمی‌گرداند."; +Blockly.Msg.LOGIC_OPERATION_AND = "و"; +Blockly.Msg.LOGIC_OPERATION_HELPURL = "http://code.google.com/p/blockly/wiki/And_Or"; // untranslated +Blockly.Msg.LOGIC_OPERATION_OR = "یا"; +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "بازگرداندن صحیح اگر هر دو ورودی صحیح باشد."; +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "بازگرداندن صحیح اگر یکی از دو ورودی صحیح باشد."; +Blockly.Msg.LOGIC_TERNARY_CONDITION = "آزمایش"; +Blockly.Msg.LOGIC_TERNARY_HELPURL = "http://en.wikipedia.org/wiki/%3F:"; // untranslated +Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "اگر ناصحیح"; +Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "اگر صحیح"; +Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "بررسی وضعیت در «آزمایش». اگر وضعیت صحیح باشد، مقدار «اگر صحیح» را بر می‌گرداند در غیر اینصورت مقدار «اگر ناصحیح» را."; +Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated +Blockly.Msg.MATH_ARITHMETIC_HELPURL = "http://fa.wikipedia.org/wiki/%D8%AD%D8%B3%D8%A7%D8%A8"; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "بازگرداندن مقدار جمع دو عدد."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "بازگرداندن باقی‌ماندهٔ دو عدد."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "بازگرداندن تفاوت دو عدد."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "بازگرداندن حاصلضرب دو عدد."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "بازگرداندن اولین عددی که از توان عدد دوم حاصل شده باشد."; +Blockly.Msg.MATH_CHANGE_HELPURL = "http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; // untranslated +Blockly.Msg.MATH_CHANGE_INPUT_BY = "با"; +Blockly.Msg.MATH_CHANGE_TITLE_CHANGE = "تغییر"; +Blockly.Msg.MATH_CHANGE_TOOLTIP = "افزودن یک عدد به متغیر '%1'."; +Blockly.Msg.MATH_CONSTANT_HELPURL = "http://fa.wikipedia.org/wiki/%D8%AB%D8%A7%D8%A8%D8%AA_%D8%B1%DB%8C%D8%A7%D8%B6%DB%8C"; +Blockly.Msg.MATH_CONSTANT_TOOLTIP = "یکی از مقادیر مشترک را برمی‌گرداند: π (۳٫۱۴۱…)، e (۲٫۷۱۸...)، φ (۱٫۶۱۸)، sqrt(۲) (۱٫۴۱۴)، sqrt(۱/۲) (۰٫۷۰۷...) و یا ∞ (بی‌نهایت)."; +Blockly.Msg.MATH_CONSTRAIN_HELPURL = "http://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated +Blockly.Msg.MATH_CONSTRAIN_TITLE = "محدودکردن %1 پایین %2 بالا %3"; +Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "محدودکردن یک عدد بین محدودیت‌های مشخص‌شده (بسته)."; +Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated +Blockly.Msg.MATH_IS_DIVISIBLE_BY = "تقسیم شده بر"; +Blockly.Msg.MATH_IS_EVEN = "زوج است"; +Blockly.Msg.MATH_IS_NEGATIVE = "منفی است"; +Blockly.Msg.MATH_IS_ODD = "فرد است"; +Blockly.Msg.MATH_IS_POSITIVE = "مثبت است"; +Blockly.Msg.MATH_IS_PRIME = "عدد اول است"; +Blockly.Msg.MATH_IS_TOOLTIP = "بررسی می‌کند که آیا یک عدد زوج، فرد، اول، کامل، مثبت، منفی یا بخش‌پذیر عدد خاصی باشد را بررسی می‌کند. درست یا نادرست باز می‌گرداند."; +Blockly.Msg.MATH_IS_WHOLE = "کامل است"; +Blockly.Msg.MATH_MODULO_HELPURL = "http://fa.wikipedia.org/wiki/%D8%B9%D9%85%D9%84%DB%8C%D8%A7%D8%AA_%D9%BE%DB%8C%D9%85%D8%A7%D9%86%D9%87"; +Blockly.Msg.MATH_MODULO_TITLE = "باقی‌ماندهٔ %1 + %2"; +Blockly.Msg.MATH_MODULO_TOOLTIP = "باقی‌ماندهٔ تقسیم دو عدد را بر می‌گرداند."; +Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated +Blockly.Msg.MATH_NUMBER_HELPURL = "http://fa.wikipedia.org/wiki/%D8%B9%D8%AF%D8%AF"; +Blockly.Msg.MATH_NUMBER_TOOLTIP = "یک عدد."; +Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated +Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "میانگین فهرست"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "بزرگ‌ترین فهرست"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "میانهٔ فهرست"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "کوچکترین فهرست"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "مد فهرست"; +Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "مورد تصادفی از فهرست"; +Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "انحراف معیار فهرست"; +Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "جمع فهرست"; +Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "میانگین (میانگین ریاضی) مقادیر عددی فهرست را بر می‌گرداند."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "بزرگ‌ترین عدد در فهرست را باز می‌گرداند."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "میانهٔ عدد در فهرست را بر می‌گرداند."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "کوچک‌ترین عدد در فهرست را باز می‌گرداند."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "شایع‌ترین قلم(های) در فهرست را بر می‌گرداند."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "موردی تصادفی از فهرست را بر می‌گرداند."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "انحراف معیار فهرست را بر می‌گرداند."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "جمع همهٔ عددهای فهرست را باز می‌گرداند."; +Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated +Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "http://fa.wikipedia.org/wiki/%D8%AA%D9%88%D9%84%DB%8C%D8%AF_%D8%A7%D8%B9%D8%AF%D8%A7%D8%AF_%D8%AA%D8%B5%D8%A7%D8%AF%D9%81%DB%8C"; +Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "کسر تصادفی"; +Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "بازگرداندن کسری تصادفی بین ۰٫۰ (بسته) تا ۱٫۰ (باز)."; +Blockly.Msg.MATH_RANDOM_INT_HELPURL = "http://fa.wikipedia.org/wiki/%D8%AA%D9%88%D9%84%DB%8C%D8%AF_%D8%A7%D8%B9%D8%AF%D8%A7%D8%AF_%D8%AA%D8%B5%D8%A7%D8%AF%D9%81%DB%8C"; +Blockly.Msg.MATH_RANDOM_INT_TITLE = "عدد صحیح تصادفی بین %1 تا %2"; +Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "یک عدد تصادفی بین دو مقدار مشخص‌شده به صورت بسته باز می‌گرداند."; +Blockly.Msg.MATH_ROUND_HELPURL = "http://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "گردکردن"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "گرد به پایین"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "گرد به بالا"; +Blockly.Msg.MATH_ROUND_TOOLTIP = "گردکردن یک عدد به بالا یا پایین."; +Blockly.Msg.MATH_SINGLE_HELPURL = "http://fa.wikipedia.org/wiki/%D8%B1%DB%8C%D8%B4%D9%87_%D8%AF%D9%88%D9%85"; +Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "مطلق"; +Blockly.Msg.MATH_SINGLE_OP_ROOT = "ریشهٔ دوم"; +Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "قدر مطلق یک عدد را بازمی‌گرداند."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "بازگرداندن توان e یک عدد."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "لوگاریتم طبیعی یک عدد را باز می‌گرداند."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "بازگرداندن لگاریتم بر پایهٔ ۱۰ یک عدد."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "منفی‌شدهٔ یک عدد را باز می‌گرداند."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "بازگرداندن توان ۱۰ یک عدد."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "ریشهٔ دوم یک عدد را باز می‌گرداند."; +Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated +Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated +Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated +Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated +Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated +Blockly.Msg.MATH_TRIG_HELPURL = "http://fa.wikipedia.org/wiki/%D8%AA%D8%A7%D8%A8%D8%B9%E2%80%8C%D9%87%D8%A7%DB%8C_%D9%85%D8%AB%D9%84%D8%AB%D8%A7%D8%AA%DB%8C"; +Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated +Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated +Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "بازگرداندن آرک‌کسینوس درجه (نه رادیان)."; +Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "بازگرداندن آرک‌سینوس درجه (نه رادیان)."; +Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "بازگرداندن آرک‌تانژانت درجه (نه رادیان)."; +Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "بازگرداندن کسینوس درجه (نه رادیان)."; +Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "بازگرداندن سینوس درجه (نه رادیان)."; +Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "بازگرداندن تانژانت یک درجه (نه رادیان)."; +Blockly.Msg.NEW_VARIABLE = "متغیر جدید..."; +Blockly.Msg.NEW_VARIABLE_TITLE = "نام متغیر جدید:"; +Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated +Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "با:"; +Blockly.Msg.PROCEDURES_CALLNORETURN_CALL = ""; // untranslated +Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "http://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29"; +Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "اجرای تابع تعریف‌شده توسط کاربر «%1»."; +Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "http://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29"; +Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "اجرای تابع تعریف‌شده توسط کاربر «%1» و استفاده از خروجی آن."; +Blockly.Msg.PROCEDURES_CREATE_DO = "ساختن «%1»"; +Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated +Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated +Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "انجام چیزی"; +Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "به"; +Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "تابعی می‌سازد بدون هیچ خروجی."; +Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated +Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "بازگشت"; +Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "تابعی با یک خروجی می‌سازد."; +Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "اخطار: این تابعی پارامتر تکراری دارد."; +Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "برجسته‌سازی تعریف تابع"; +Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "اگر یک مقدار صحیح است، مقدار دوم را برگردان."; +Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "اخطار: این بلوگ احتمالاً فقط داخل یک تابع استفاده می‌شود."; +Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "نام ورودی:"; +Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "ورودی‌ها"; +Blockly.Msg.REMOVE_COMMENT = "حذف نظر"; +Blockly.Msg.RENAME_VARIABLE = "تغییر نام متغیر..."; +Blockly.Msg.RENAME_VARIABLE_TITLE = "تغییر نام همهٔ متغیرهای «%1» به:"; +Blockly.Msg.TEXT_APPEND_APPENDTEXT = "الحاق متن"; +Blockly.Msg.TEXT_APPEND_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Text_modification"; // untranslated +Blockly.Msg.TEXT_APPEND_TO = "به"; +Blockly.Msg.TEXT_APPEND_TOOLTIP = "الحاق متنی به متغیر «%1»."; +Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case"; // untranslated +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "به حروف کوچک"; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "به حروف بزرگ عنوان"; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "به حروف بزرگ"; +Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "بازگرداندن کپی متن در حالتی متفاوت."; +Blockly.Msg.TEXT_CHARAT_FIRST = "گرفتن اولین حرف"; +Blockly.Msg.TEXT_CHARAT_FROM_END = "گرفتن حرف # از آخر"; +Blockly.Msg.TEXT_CHARAT_FROM_START = "گرفتن حرف #"; +Blockly.Msg.TEXT_CHARAT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Extracting_text"; // untranslated +Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "در متن"; +Blockly.Msg.TEXT_CHARAT_LAST = "گرفتن آخرین حرف"; +Blockly.Msg.TEXT_CHARAT_RANDOM = "گرفتن حرف تصادفی"; +Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated +Blockly.Msg.TEXT_CHARAT_TOOLTIP = "حرفی در موقعیت مشخص‌شده بر می‌گرداند."; +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "افزودن یک مورد به متن."; +Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "عضویت"; +Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "اضافه‌کردن، حذف یا مرتب‌سازی بحش‌ها برای تنظیم مجدد این بلوک متنی."; +Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "به حرف # از انتها"; +Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "به حرف #"; +Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "به آخرین حرف"; +Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text"; // untranslated +Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "در متن"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "گرفتن زیرمتن از اولین حرف"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "گرفتن زیرمتن از حرف # به انتها"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "گرفتن زیرمتن از حرف #"; +Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated +Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "قسمت مشخصی‌شده‌ای از متن را بر می‌گرداند."; +Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Finding_text"; // untranslated +Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "در متن"; +Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "اولین رخداد متن را بیاب"; +Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "آخرین رخداد متن را بیاب"; +Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated +Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "شاخصی از اولین آخرین رخ‌داد متن اول در متن دوم بر می‌گرداند. اگر متن یافت نشد ۰ باز می‌گرداند."; +Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text"; // untranslated +Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 خالی است"; +Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "اضافه‌کردن صحیح اگر متن فراهم‌شده خالی است."; +Blockly.Msg.TEXT_JOIN_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Text_creation"; // untranslated +Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "ایجاد متن با"; +Blockly.Msg.TEXT_JOIN_TOOLTIP = "یک تکه‌ای از متن را با چسپاندن همهٔ تعداد از موارد ایجاد می‌کند."; +Blockly.Msg.TEXT_LENGTH_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Text_modification"; // untranslated +Blockly.Msg.TEXT_LENGTH_TITLE = "طول %1"; +Blockly.Msg.TEXT_LENGTH_TOOLTIP = "بازگرداندن عددی از حروف (شامل فاصله‌ها) در متن فراهم‌شده."; +Blockly.Msg.TEXT_PRINT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Printing_text"; // untranslated +Blockly.Msg.TEXT_PRINT_TITLE = "چاپ %1"; +Blockly.Msg.TEXT_PRINT_TOOLTIP = "چاپ متن، عدد یا هر مقدار دیگر مشخص‌شده."; +Blockly.Msg.TEXT_PROMPT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user"; // untranslated +Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "اعلان برای کاربر با یک عدد."; +Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "اعلان برای کاربر برای یک متن."; +Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "اعلان برای عدد با پیام"; +Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "اعلان برای متن با پیام"; +Blockly.Msg.TEXT_TEXT_HELPURL = "http://fa.wikipedia.org/wiki/%D8%B1%D8%B4%D8%AA%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29"; +Blockly.Msg.TEXT_TEXT_TOOLTIP = "یک حرف، کلمه یا خطی از متن."; +Blockly.Msg.TEXT_TRIM_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces"; // untranslated +Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "تراشیدن فاصله‌ها از هر دو طرف"; +Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "تراشیدن فاصله‌ها از طرف چپ"; +Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "تراشیدن فاصله‌ها از طرف چپ"; +Blockly.Msg.TEXT_TRIM_TOOLTIP = "کپی از متن با فاصله‌های حذف‌شده از یک یا هر دو پایان باز می‌گرداند."; +Blockly.Msg.VARIABLES_DEFAULT_NAME = "مورد"; +Blockly.Msg.VARIABLES_GET_CREATE_SET = "درست‌کردن «تنظیم %1»"; +Blockly.Msg.VARIABLES_GET_HELPURL = "http://code.google.com/p/blockly/wiki/Variables#Get"; // untranslated +Blockly.Msg.VARIABLES_GET_TAIL = ""; // untranslated +Blockly.Msg.VARIABLES_GET_TITLE = ""; // untranslated +Blockly.Msg.VARIABLES_GET_TOOLTIP = "مقدار این متغیر را بر می‌گرداند."; +Blockly.Msg.VARIABLES_SET_CREATE_GET = "درست‌کردن «گرفتن %1»"; +Blockly.Msg.VARIABLES_SET_HELPURL = "http://code.google.com/p/blockly/wiki/Variables#Set"; // untranslated +Blockly.Msg.VARIABLES_SET_TAIL = "به"; +Blockly.Msg.VARIABLES_SET_TITLE = "مجموعه"; +Blockly.Msg.VARIABLES_SET_TOOLTIP = "متغیر برابر با خروجی را مشخص می‌کند."; +Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; +Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; +Blockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; +Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL; +Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; +Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; +Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; \ No newline at end of file diff --git a/msg/js/hu.js b/msg/js/hu.js new file mode 100644 index 000000000..f3e9d7cc2 --- /dev/null +++ b/msg/js/hu.js @@ -0,0 +1,377 @@ +// This file was automatically generated. Do not modify. + +'use strict'; + +goog.provide('Blockly.Msg.hu'); + +goog.require('Blockly.Msg'); + +Blockly.Msg.ADD_COMMENT = "Megjegyzés hozzáadása"; +Blockly.Msg.CHANGE_VALUE_TITLE = "Érték módosítása:"; +Blockly.Msg.COLLAPSE_ALL = "Collapse Blocks"; // untranslated +Blockly.Msg.COLLAPSE_BLOCK = "Összezár"; +Blockly.Msg.COLOUR_BLEND_COLOUR1 = ""; +Blockly.Msg.COLOUR_BLEND_COLOUR2 = "+"; +Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated +Blockly.Msg.COLOUR_BLEND_RATIO = "arány:"; +Blockly.Msg.COLOUR_BLEND_TITLE = "Színkeverés"; +Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Két színt kever össze a megadott arányban (0.0 - 1.0)."; +Blockly.Msg.COLOUR_PICKER_HELPURL = "http://hu.wikipedia.org/wiki/Szín"; +Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Válassz színt a palettáról."; +Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated +Blockly.Msg.COLOUR_RANDOM_TITLE = "Véletlen szín"; +Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Véletlenszerűen kiválasztott szín."; +Blockly.Msg.COLOUR_RGB_BLUE = "kék"; +Blockly.Msg.COLOUR_RGB_GREEN = "zöld"; +Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated +Blockly.Msg.COLOUR_RGB_RED = "vörös"; +Blockly.Msg.COLOUR_RGB_TITLE = "Szín"; +Blockly.Msg.COLOUR_RGB_TOOLTIP = "Szín előállítása a megadott vörös, zöld, és kék értékekkel. Minden értéknek 0 és 100 közé kell esnie."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks"; // untranslated +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "befejezi az ismétlést"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "folytatja a következővel"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Megszakítja végtelen ciklust."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Megszakítja az aktuális futást és folytatja elölről."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Figyelem: Ez a blokk, csak egy ciklusban használható."; +Blockly.Msg.CONTROLS_FOREACH_HELPURL = "http://hu.wikipedia.org/wiki/Ciklus_(programoz%C3%A1s)#Iter.C3.A1l.C3.B3_ciklus"; +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = "elemre a"; +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = "listában"; +Blockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = "Minden"; +Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "A lista elemszámának megfelelő lépésszámú ciklus. A \"%1\" változó minden lépésben megkapja a lista adott elemének értékét. Minden lépésben végrehajtódnak az utasítások."; +Blockly.Msg.CONTROLS_FOR_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#count_with"; // untranslated +Blockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = "ettől: %1 eddig: %2 lépésköz: %3"; +Blockly.Msg.CONTROLS_FOR_INPUT_WITH = "Számold ezzel"; +Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Véges lépésszámú ciklus. A \"%1\" változó értékét számolja ki a kezdőérték és a végérték között. Minden lépésben végrehajtódnak az utasítások."; +Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Újabb feltételes elágazás."; +Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Add a final, catch-all condition to the if block."; // untranslated +Blockly.Msg.CONTROLS_IF_HELPURL = "http://code.google.com/p/blockly/wiki/If_Then"; // untranslated +Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "A feltételes elágazás (ha) blokk testreszabásához bővítsd, töröld vagy rendezd át a részeit."; +Blockly.Msg.CONTROLS_IF_MSG_ELSE = "különben"; +Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "ha"; +Blockly.Msg.CONTROLS_IF_MSG_IF = "Ha"; +Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Ha a kifejezés igaz, akkor végrehajtjuk az utasításokat."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Ha a kifejezés igaz, akkor végrehajtjuk az első utasítás blokkot. Különben a második utasítás blokk kerül végrehajtásra."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Ha az első kifejezés igaz, akkor végrehajtjuk az első utasítás blokkot. Ha a második kifejezés igaz, akkor végrehajtjuk a második utasítás blokkot."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Ha az első kifejezés igaz, akkor végrehajtjuk az első utasítás blokkot. Ha a második kifejezés igaz, akkor végrehajtjuk a második utasítás blokkot. Amennyiben egyik kifejezés sem igaz, akkor az utolsó utasítás blokk kerül végrehajtásra."; +Blockly.Msg.CONTROLS_REPEAT_HELPURL = "http://hu.wikipedia.org/wiki/Ciklus_(programoz%C3%A1s)#Sz.C3.A1ml.C3.A1l.C3.B3s_.28FOR.29_ciklus"; +Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = ""; +Blockly.Msg.CONTROLS_REPEAT_TITLE = "Ismételd %1 alkalommal"; +Blockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = "Ismételd"; +Blockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = "alkalommal"; +Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Megadott kódrészlet ismételt végrehajtása."; +Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "http://code.google.com/p/blockly/wiki/Repeat"; // untranslated +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "amíg nem"; +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "amíg"; +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Amíg a feltétel hamis, végrehajtja az utasításokat."; +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Amíg a feltétel igaz, végrehajtja az utasításokat."; +Blockly.Msg.DELETE_BLOCK = "Töröl"; +Blockly.Msg.DELETE_X_BLOCKS = "%1 blokk törlése"; +Blockly.Msg.DISABLE_BLOCK = "Letilt"; +Blockly.Msg.DUPLICATE_BLOCK = "Másolat"; +Blockly.Msg.ENABLE_BLOCK = "Engedélyez"; +Blockly.Msg.EXPAND_ALL = "Expand Blocks"; // untranslated +Blockly.Msg.EXPAND_BLOCK = "Kibont"; +Blockly.Msg.EXTERNAL_INPUTS = "Külső kapcsolatok"; +Blockly.Msg.HELP = "Sugó"; +Blockly.Msg.INLINE_INPUTS = "Belső kapcsolatok"; +Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "http://en.wikipedia.org/wiki/Linked_list#Empty_lists"; // untranslated +Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "üres lista"; +Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Elemeket nem tartalmazó üres listát ad eredményül"; +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "lista"; +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Add, remove, or reorder sections to reconfigure this list block."; +Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "Lista készítés, elemek:"; +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Elem hozzáadása listához."; +Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Listát készít a megadott elemekből."; +Blockly.Msg.LISTS_GET_INDEX_FIRST = "az első"; +Blockly.Msg.LISTS_GET_INDEX_FROM_END = "a végétől számított"; +Blockly.Msg.LISTS_GET_INDEX_FROM_START = "az elejétől számított"; +Blockly.Msg.LISTS_GET_INDEX_GET = "listában értéke"; +Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "listából kivétele"; +Blockly.Msg.LISTS_GET_INDEX_LAST = "az utolsó"; +Blockly.Msg.LISTS_GET_INDEX_RANDOM = "bármely"; +Blockly.Msg.LISTS_GET_INDEX_REMOVE = "listából törlése"; +Blockly.Msg.LISTS_GET_INDEX_TAIL = "elem"; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "A lista első elemét adja eredményül."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = "A lista megadott sorszámú elemét adja eredményül. 1 az utolsó elemet jelenti."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = "A lista megadott sorszámú elemét adja eredményül. 1 az első elemet jelenti."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "A lista utolsó elemét adja eredményül."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "A lista véletlenszerűen választott elemét adja eredményül."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Az első elem kivétele a listából."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = "A megadott sorszámú elem kivétele a listából 1 az utolsó elemet jelenti."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = "A megadott sorszámú elem kivétele a listából 1 az első elemet jelenti."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Az utolsó elem kivétele a listából."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Véletlenszerűen választott elem kivétele a listából."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Az első elem törlése a listából."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = "A megadott sorszámú elem törlése a listából 1 az utolsó elemet jelenti."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = "A megadott sorszámú elem törlése a listából 1 az első elemet jelenti."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Az utolsó elem törlése a listából."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Véletlenszerűen választott elem törlése a listából."; +Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "és a végétől számított"; +Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "és az elejétől számított"; +Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "és az utolsó"; +Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist"; // untranslated +Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "részlistája az első"; +Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "részlistája a végétől számított"; +Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "részlistája az elejétől számított"; +Blockly.Msg.LISTS_GET_SUBLIST_TAIL = "elem között"; +Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "A lista adott részéről másolat."; +Blockly.Msg.LISTS_INDEX_OF_FIRST = "listában első előfordulásának"; +Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List"; // untranslated +Blockly.Msg.LISTS_INDEX_OF_LAST = "listában utolsó előfordulásának"; +Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "A megadtott elem eslő vagy utolsó előfordulásával tér vissza. 0 esetén nincs ilyen eleme a listának."; +Blockly.Msg.LISTS_INLIST = "A(z)"; +Blockly.Msg.LISTS_IS_EMPTY_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#is_empty"; // untranslated +Blockly.Msg.LISTS_IS_EMPTY_TITLE = "%1 üres lista?"; +Blockly.Msg.LISTS_LENGTH_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#length_of"; // untranslated +Blockly.Msg.LISTS_LENGTH_TITLE = "hossz %1 listában"; +Blockly.Msg.LISTS_LENGTH_TOOLTIP = "A lista elemszámát adja eredményül."; +Blockly.Msg.LISTS_REPEAT_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#create_list_with"; // untranslated +Blockly.Msg.LISTS_REPEAT_TITLE = "Lista készítése %1 elemet %2 alkalommal hozzáadva"; +Blockly.Msg.LISTS_REPEAT_TOOLTIP = "A megadtott elem felhasználásával n elemű listát készít"; +Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#in_list_..._set"; // untranslated +Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "elemet mint"; +Blockly.Msg.LISTS_SET_INDEX_INSERT = "illeszd be"; +Blockly.Msg.LISTS_SET_INDEX_SET = "állítsd be"; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Beszúrás a lista elejére."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = "Beszúrás a megadott sorszámú elem elé a listában. 1 az utolsó elemet jelenti."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = "Beszúrás a megadott sorszámú elem elé a listában. 1 az első elemet jelenti."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Beszúrás a lista végére."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Beszúrás véletlenszerűen választott elem elé a listában."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Az első elem cseréje a listában."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = "A megadott sorszámú elem cseréje a listában. 1 az utolsó elemet jelenti."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = "A megadott sorszámú elem cseréje a listában. 1 az első elemet jelenti."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Az utolsó elem cseréje a listában."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Véletlenszerűen választott elem cseréje a listában."; +Blockly.Msg.LISTS_TOOLTIP = "Az eredmény igaz, ha a lista nem tartalmaz elemeket."; +Blockly.Msg.LOGIC_BOOLEAN_FALSE = "hamis"; +Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "http://code.google.com/p/blockly/wiki/True_False"; // untranslated +Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Igaz, vagy Hamis érték"; +Blockly.Msg.LOGIC_BOOLEAN_TRUE = "igaz"; +Blockly.Msg.LOGIC_COMPARE_HELPURL = "http://en.wikipedia.org/wiki/Inequality_(mathematics)"; // untranslated +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Igaz, ha a kifejezés két oldala egyenlő."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Igaz, ha a bal oldali kifejezés nagyobb, mint a jobb oldali."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Igaz, ha a bal oldali kifejezés nagyobb vagy egyenlő, mint a jobb oldali."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Igaz, ha a bal oldali kifejezés kisebb, mint a jobb oldali."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Igaz, ha a bal oldali kifejezés kisebb vagy egyenlő, mint a jobb oldali."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Igaz, ha a kifejezés két oldala nem egyenlő.."; +Blockly.Msg.LOGIC_NEGATE_HELPURL = "http://code.google.com/p/blockly/wiki/Not"; // untranslated +Blockly.Msg.LOGIC_NEGATE_TITLE = "nem %1"; +Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Igaz, ha a kifejezés hamis. Hamis, ha a kifejezés igaz."; +Blockly.Msg.LOGIC_NULL = "null"; +Blockly.Msg.LOGIC_NULL_HELPURL = "http://en.wikipedia.org/wiki/Nullable_type"; // untranslated +Blockly.Msg.LOGIC_NULL_TOOLTIP = "null érték."; +Blockly.Msg.LOGIC_OPERATION_AND = "és"; +Blockly.Msg.LOGIC_OPERATION_HELPURL = "http://code.google.com/p/blockly/wiki/And_Or"; // untranslated +Blockly.Msg.LOGIC_OPERATION_OR = "vagy"; +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Igaz, ha mindkét kifejezés igaz."; +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Igaz, ha bármelyik kifejezés igaz."; +Blockly.Msg.LOGIC_TERNARY_CONDITION = "kifejezés:"; +Blockly.Msg.LOGIC_TERNARY_HELPURL = "http://en.wikipedia.org/wiki/%3F:"; // untranslated +Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "érték, ha hamis:"; +Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "érték, ha igaz:"; +Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Kiértékeli a kifejezést. Ha a kifejezés igaz visszatér az \"érték, ha igaz\" értékkel, különben az \"érték, ha hamis\" értékkel."; +Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated +Blockly.Msg.MATH_ARITHMETIC_HELPURL = "http://en.wikipedia.org/wiki/Arithmetic"; // untranslated +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Két szám összege."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Két szám hányadosa."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Két szám különbsége."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Két szám szorzata."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Az első számnak a második számmal megyegyező hatványa."; +Blockly.Msg.MATH_CHANGE_HELPURL = "http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; // untranslated +Blockly.Msg.MATH_CHANGE_INPUT_BY = "értékének növelése"; +Blockly.Msg.MATH_CHANGE_TITLE_CHANGE = "a"; +Blockly.Msg.MATH_CHANGE_TOOLTIP = "A(z) \"%1\" változó értékének növelése."; +Blockly.Msg.MATH_CONSTANT_HELPURL = "http://en.wikipedia.org/wiki/Mathematical_constant"; // untranslated +Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Ismert matematikai konstans: π (3.141…), e (2.718…), φ (1.618…), gyök(2) (1.414…), gyök(½) (0.707…), vagy ∞ (végtelen)."; +Blockly.Msg.MATH_CONSTRAIN_HELPURL = "http://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated +Blockly.Msg.MATH_CONSTRAIN_TITLE = "korlátozd %1 -t %2 és %3 közé"; +Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Egy változó értékének korlátozása a megadott zárt intervallumra."; +Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated +Blockly.Msg.MATH_IS_DIVISIBLE_BY = "osztható a(z)"; +Blockly.Msg.MATH_IS_EVEN = "páros szám?"; +Blockly.Msg.MATH_IS_NEGATIVE = "negatív szám?"; +Blockly.Msg.MATH_IS_ODD = "páratlan szám?"; +Blockly.Msg.MATH_IS_POSITIVE = "pozitív szám?"; +Blockly.Msg.MATH_IS_PRIME = "prímszám?"; +Blockly.Msg.MATH_IS_TOOLTIP = "Megadja a számról, hogy páros, páratlan, prím, egész, pozitív vagy negatív szám, illetve osztható-e a másodikkal. Igaz, vagy Hamis értéket ad eredményül."; +Blockly.Msg.MATH_IS_WHOLE = "egész szám?"; +Blockly.Msg.MATH_MODULO_HELPURL = "http://en.wikipedia.org/wiki/Modulo_operation"; // untranslated +Blockly.Msg.MATH_MODULO_TITLE = "Maradék %1 ÷ %2"; +Blockly.Msg.MATH_MODULO_TOOLTIP = "Az egész osztás maradékát adja eredméynül."; +Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated +Blockly.Msg.MATH_NUMBER_HELPURL = "http://en.wikipedia.org/wiki/Number"; // untranslated +Blockly.Msg.MATH_NUMBER_TOOLTIP = "Egy szám."; +Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated +Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "lista átlaga"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "lista maximuma"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "lista mediánja"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "lista minimuma"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "lista módusza"; +Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "lista véletlen eleme"; +Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "lista szórása"; +Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "lista összege"; +Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "A lista elemeinek átlagát adja eredményül."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "A lista elemeinek maximumát adja eredményül."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "A lista elemeinek mediánját adja eredményül."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "A lista elemeinek minimumát adja eredményül."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "A lista elemeinek móduszát adja eredményül."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "A lista elemeinek véletlen elemét adja eredményül."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "A lista elemeinek szórását adja eredményül."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "A lista elemeinek összegét adja eredményül."; +Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated +Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "http://en.wikipedia.org/wiki/Random_number_generation"; // untranslated +Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "Véletlen tört"; +Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Véletlen tört érték 0.0 és 1.0 között."; +Blockly.Msg.MATH_RANDOM_INT_HELPURL = "http://en.wikipedia.org/wiki/Random_number_generation"; // untranslated +Blockly.Msg.MATH_RANDOM_INT_TITLE = "Véletlen egész szám %1 között %2"; +Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Véletlen egész szám a megadott zárt intervallumon belül."; +Blockly.Msg.MATH_ROUND_HELPURL = "http://en.wikipedia.org/wiki/Rounding"; // untranslated +Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "Kerekítés"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "Kerekítés le"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "Kerekítés fel"; +Blockly.Msg.MATH_ROUND_TOOLTIP = "Kerekítés a következő, vagy megelőző egész számra."; +Blockly.Msg.MATH_SINGLE_HELPURL = "http://en.wikipedia.org/wiki/Square_root"; // untranslated +Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "Abszolútérték"; +Blockly.Msg.MATH_SINGLE_OP_ROOT = "Négyzetgyök"; +Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "A szám abszolútértéke."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Az e megadott számú hatványa."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "A szám természetes alapú logaritmusa."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "A szám 10-es alapú logaritmusa."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Return the negation of a number."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "A 10 megadott számú hatványa."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "A szám négyzetgyöke."; +Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated +Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated +Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated +Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated +Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated +Blockly.Msg.MATH_TRIG_HELPURL = "http://en.wikipedia.org/wiki/Trigonometric_functions"; // untranslated +Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated +Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated +Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "A fokban megadott szög arkusz koszinusz értéke."; +Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "A fokban megadott szög arkusz szinusz értéke."; +Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "A fokban megadott szög arkusz tangens értéke."; +Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "A fokban megadott szög koszinusz értéke."; +Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "A fokban megadott szög szinusz értéke."; +Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "A fokban megadott szög tangens értéke."; +Blockly.Msg.NEW_VARIABLE = "Új..."; +Blockly.Msg.NEW_VARIABLE_TITLE = "Az új változó neve:"; +Blockly.Msg.ORDINAL_NUMBER_SUFFIX = "."; +Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "with:"; // untranslated +Blockly.Msg.PROCEDURES_CALLNORETURN_CALL = ""; +Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated +Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Végrehajtja az eljárást."; +Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated +Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Meghívja a függvényt."; +Blockly.Msg.PROCEDURES_CREATE_DO = "Create \"do %1\""; +Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; +Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated +Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "Eljárás"; +Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "to"; // untranslated +Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Eljárás (nem ad vissza eredményt)."; +Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated +Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "eredmény"; +Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Eljárás eredménnyel."; +Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Figyelem: Az eljárásban azonos elnevezésű paramétert adtál meg."; +Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Eljárás kiemelése"; +Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Ha az érték igaz, akkor visszatér a függvény értékével."; +Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Figyelem: Ez a blokk csak eljáráson belül használható."; +Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "változó:"; +Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "paraméterek"; +Blockly.Msg.REMOVE_COMMENT = "Megjegyzés tölése"; +Blockly.Msg.RENAME_VARIABLE = "Átnevezés..."; +Blockly.Msg.RENAME_VARIABLE_TITLE = "\"%1\" változó átnevezése:"; +Blockly.Msg.TEXT_APPEND_APPENDTEXT = "szövegéhez fűzd hozzá"; +Blockly.Msg.TEXT_APPEND_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Text_modification"; // untranslated +Blockly.Msg.TEXT_APPEND_TO = "a"; +Blockly.Msg.TEXT_APPEND_TOOLTIP = "Szöveget fűz a \"%1\" változó értékéhez."; +Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case"; // untranslated +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "kisbetűs"; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "Címként Formázott"; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "NAGYBETŰS"; +Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Return a copy of the text in a different case."; +Blockly.Msg.TEXT_CHARAT_FIRST = "szövegnek az első"; +Blockly.Msg.TEXT_CHARAT_FROM_END = "szövegnek a végétől számított"; +Blockly.Msg.TEXT_CHARAT_FROM_START = "szövegnek az elejétől számított"; +Blockly.Msg.TEXT_CHARAT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Extracting_text"; // untranslated +Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "A"; +Blockly.Msg.TEXT_CHARAT_LAST = "szövegnek az utolsó"; +Blockly.Msg.TEXT_CHARAT_RANDOM = "szövegnek tetszőleges"; +Blockly.Msg.TEXT_CHARAT_TAIL = "karaktere"; +Blockly.Msg.TEXT_CHARAT_TOOLTIP = "A szöveg egy megadott karakterét adja eredményül."; +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Elem hozzáfűzése a szöveghez."; +Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "Összefűz"; +Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Összefűzéssel, törléssel vagy rendezéssel kapcsolato sblokkok szöveg szerkesztéséhez."; +Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "betűtől a hátulról számított"; +Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "betűtől a(z)"; +Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "betűtől az utolsó"; +Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text"; // untranslated +Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "a"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "szövegben válaszd ki az első"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "szövegben válaszd ki a hátulról a(z)"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "szövegben válaszd ki a(z)"; +Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = "betűig tartó betűsort"; +Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "A megadott szövegrészletet adja eredményül."; +Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Finding_text"; // untranslated +Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "A(z)"; +Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "első előfordulásának indexe"; +Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "utolsó előfordulásának indexe"; +Blockly.Msg.TEXT_INDEXOF_TAIL = "szövegnek"; +Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "A keresett szöveg első vagy utolsó előfordulásával tér vissza. 0 esetén a szövegrészlet nem található."; +Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text"; // untranslated +Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 üres sztring?"; +Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Igaz, ha vizsgált sztring üres."; +Blockly.Msg.TEXT_JOIN_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Text_creation"; // untranslated +Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "Összefűz"; +Blockly.Msg.TEXT_JOIN_TOOLTIP = "Tetszőleges számú szövegrészletet fűz össze egybefüggő szöveggé."; +Blockly.Msg.TEXT_LENGTH_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Text_modification"; // untranslated +Blockly.Msg.TEXT_LENGTH_TITLE = "Hossz %1"; +Blockly.Msg.TEXT_LENGTH_TOOLTIP = "A megadott szöveg karaktereinek számát adja eredményül (beleértve a szóközöket)."; +Blockly.Msg.TEXT_PRINT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Printing_text"; // untranslated +Blockly.Msg.TEXT_PRINT_TITLE = "Üzenet %1"; +Blockly.Msg.TEXT_PRINT_TOOLTIP = "Megejelníti a megadott kaakterláncot üzenetként a képernyőn."; +Blockly.Msg.TEXT_PROMPT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user"; // untranslated +Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Számot kér be a felhasználótól."; +Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Szöveget kér be a felhasználótól."; +Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "Kérj be számot"; +Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "Kérj be szöveget"; +Blockly.Msg.TEXT_TEXT_HELPURL = "http://en.wikipedia.org/wiki/String_(computer_science)"; // untranslated +Blockly.Msg.TEXT_TEXT_TOOLTIP = "Egy betű, szó vagy szöveg egy sora."; +Blockly.Msg.TEXT_TRIM_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces"; // untranslated +Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "a végekről"; +Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "az elejéről"; +Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "a végéről"; +Blockly.Msg.TEXT_TRIM_TOOLTIP = "Levágja a megadott szöveg végeiről a szóközöket."; +Blockly.Msg.VARIABLES_DEFAULT_NAME = "item"; // untranslated +Blockly.Msg.VARIABLES_GET_CREATE_SET = "Create \"set %1\""; +Blockly.Msg.VARIABLES_GET_HELPURL = "http://code.google.com/p/blockly/wiki/Variables#Get"; // untranslated +Blockly.Msg.VARIABLES_GET_TAIL = ""; +Blockly.Msg.VARIABLES_GET_TITLE = ""; +Blockly.Msg.VARIABLES_GET_TOOLTIP = "A változó értékét adja eredményül."; +Blockly.Msg.VARIABLES_SET_CREATE_GET = "Create \"get %1\""; +Blockly.Msg.VARIABLES_SET_HELPURL = "http://code.google.com/p/blockly/wiki/Variables#Set"; // untranslated +Blockly.Msg.VARIABLES_SET_TAIL = ""; +Blockly.Msg.VARIABLES_SET_TITLE = ""; +Blockly.Msg.VARIABLES_SET_TOOLTIP = "A változónak adhatunk értéket."; +Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; +Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; +Blockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; +Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL; +Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; +Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; +Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; \ No newline at end of file diff --git a/msg/js/it.js b/msg/js/it.js new file mode 100644 index 000000000..85d6fbc0a --- /dev/null +++ b/msg/js/it.js @@ -0,0 +1,377 @@ +// This file was automatically generated. Do not modify. + +'use strict'; + +goog.provide('Blockly.Msg.it'); + +goog.require('Blockly.Msg'); + +Blockly.Msg.ADD_COMMENT = "Aggiungi commento"; +Blockly.Msg.CHANGE_VALUE_TITLE = "Modifica valore:"; +Blockly.Msg.COLLAPSE_ALL = "Comprimi blocchi"; +Blockly.Msg.COLLAPSE_BLOCK = "Comprimi blocco"; +Blockly.Msg.COLOUR_BLEND_COLOUR1 = "colore 1"; +Blockly.Msg.COLOUR_BLEND_COLOUR2 = "colore 2"; +Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated +Blockly.Msg.COLOUR_BLEND_RATIO = "rapporto"; +Blockly.Msg.COLOUR_BLEND_TITLE = "miscela"; +Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Mescola due colori insieme con un determinato rapporto (0.0 - 1.0)."; +Blockly.Msg.COLOUR_PICKER_HELPURL = "http://it.wikipedia.org/wiki/Colore"; +Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Scegli un colore dalla tavolozza."; +Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated +Blockly.Msg.COLOUR_RANDOM_TITLE = "colore casuale"; +Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Scegli un colore a caso."; +Blockly.Msg.COLOUR_RGB_BLUE = "blu"; +Blockly.Msg.COLOUR_RGB_GREEN = "verde"; +Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated +Blockly.Msg.COLOUR_RGB_RED = "rosso"; +Blockly.Msg.COLOUR_RGB_TITLE = "colora con"; +Blockly.Msg.COLOUR_RGB_TOOLTIP = "Crea un colore con la quantità specificata di rosso, verde e blu. Tutti i valori devono essere compresi tra 0 e 100."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks"; // untranslated +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "esce dal ciclo"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "prosegui con la successiva iterazione del ciclo"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Esce dal ciclo."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Salta il resto di questo ciclo e prosegue con la successiva iterazione."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Attenzioneː Questo blocco può essere usato solo in un ciclo."; +Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#for_each for each block"; // untranslated +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = "nella lista"; +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = ""; // untranslated +Blockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = "per ogni elemento"; +Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Per ogni elemento in una lista, imposta la variabile '%1' pari all'elemento e quindi esegue alcune istruzioni."; +Blockly.Msg.CONTROLS_FOR_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#count_with"; // untranslated +Blockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = "da %1 a %2 per %3"; +Blockly.Msg.CONTROLS_FOR_INPUT_WITH = "conta con"; +Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Fa sì che la variabile %1 prenda tutti i valori a partire dal numero di partenza fino a quello di arrivo, con passo pari all'intervallo specificato, ed esegue il blocco indicato."; +Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Aggiungi una condizione al blocco se."; +Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Aggiungi una condizione finale pigliatutto al blocco se."; +Blockly.Msg.CONTROLS_IF_HELPURL = "http://code.google.com/p/blockly/wiki/If_Then"; // untranslated +Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Aggiungi, elimina o riordina le sezioni per riconfigurare questo blocco se."; +Blockly.Msg.CONTROLS_IF_MSG_ELSE = "altrimenti"; +Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "altrimenti se"; +Blockly.Msg.CONTROLS_IF_MSG_IF = "se"; +Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Se un valore è vero allora esegue alcune istruzioni."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Se un valore è vero allora esegue il primo blocco di istruzioni. Altrimenti esegue il secondo blocco di istruzioni."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Se il primo valore è vero allora esegue un primo blocco di istruzioni. Altrimenti, se il secondo valore è vero, esegue un secondo blocco di istruzioni."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Se il primo valore è vero allora esegue un primo blocco di istruzioni. Altrimenti, se il secondo valore è vero, esegue un secondo blocco di istruzioni. Se nessuno dei valori è vero esegue l'ultimo blocco di istruzioni."; +Blockly.Msg.CONTROLS_REPEAT_HELPURL = "http://it.wikipedia.org/wiki/Ciclo_for"; +Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "fai"; +Blockly.Msg.CONTROLS_REPEAT_TITLE = "ripeti %1 volte"; +Blockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = "ripeti"; +Blockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = "volte"; +Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Esegue alcune istruzione diverse volte."; +Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "http://code.google.com/p/blockly/wiki/Repeat"; // untranslated +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "ripeti fino a che"; +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "ripeti mentre"; +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Finché un valore è falso, esegue alcune istruzioni."; +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Finché un valore è vero, esegue alcune istruzioni."; +Blockly.Msg.DELETE_BLOCK = "Cancella blocco"; +Blockly.Msg.DELETE_X_BLOCKS = "Cancella %1 blocchi"; +Blockly.Msg.DISABLE_BLOCK = "Disattivare blocco"; +Blockly.Msg.DUPLICATE_BLOCK = "Duplica"; +Blockly.Msg.ENABLE_BLOCK = "Attiva blocco"; +Blockly.Msg.EXPAND_ALL = "Espandi blocchi"; +Blockly.Msg.EXPAND_BLOCK = "Espandi blocco"; +Blockly.Msg.EXTERNAL_INPUTS = "Ingressi esterni"; +Blockly.Msg.HELP = "Aiuto"; +Blockly.Msg.INLINE_INPUTS = "Ingressi in linea"; +Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "http://en.wikipedia.org/wiki/Linked_list#Empty_lists"; // untranslated +Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "crea lista vuota"; +Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Restituisce una lista, di lunghezza 0, contenente nessun record di dati"; +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "lista"; +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Aggiungi, rimuovi o riordina le sezioni per riconfigurare il blocco lista."; +Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "crea lista con"; +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Aggiunge un elemento alla lista."; +Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Crea una lista con un certo numero di elementi."; +Blockly.Msg.LISTS_GET_INDEX_FIRST = "primo"; +Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# dalla fine"; +Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated +Blockly.Msg.LISTS_GET_INDEX_GET = "prendi"; +Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "prendi e rimuovi"; +Blockly.Msg.LISTS_GET_INDEX_LAST = "ultimo"; +Blockly.Msg.LISTS_GET_INDEX_RANDOM = "casuale"; +Blockly.Msg.LISTS_GET_INDEX_REMOVE = "rimuovi"; +Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Restituisce il primo elemento in una lista."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = "Restituisce l'elemento nella posizione indicata della lista. 1 corrisponde all'ultimo elemento."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = "Restituisce l'elemento nella posizione indicata della lista. 1 corrisponde al primo elemento della lista."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Restituisce l'ultimo elemento in una lista."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Restituisce un elemento casuale in una lista."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Rimuove e restituisce il primo elemento in una lista."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = "Rimuove e restituisce l'elemento nella posizione indicata in una lista. 1 corrisponde all'ultimo elemento."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = "Rimuove e restituisce l'elemento nella posizione indicata in una lista. 1 corrisponde al primo elemento."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Restituisce e rimuove l'ultimo elemento in una lista."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Restituisce e rimuove un elemento casuale in una lista."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Rimuove il primo elemento in una lista."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = "Rimuove l'elemento nella posizione indicata in una lista. 1 corrisponde all'ultimo elemento."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = "Rimuove l'elemento nella posizione indicata in una lista. 1 corrisponde al primo elemento."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Rimuove l'ultimo elemento in una lista."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Rimuove un elemento casuale in una lista."; +Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "da # dalla fine"; +Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "fino a #"; +Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "dagli ultimi"; +Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist"; // untranslated +Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "prendi sotto-lista dall'inizio"; +Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "prendi sotto-lista da # dalla fine"; +Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "prendi sotto-lista da #"; +Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated +Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Crea una copia della porzione specificata di una lista."; +Blockly.Msg.LISTS_INDEX_OF_FIRST = "trova la prima occorrenza dell'elemento"; +Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List"; // untranslated +Blockly.Msg.LISTS_INDEX_OF_LAST = "trova l'ultima occorrenza dell'elemento"; +Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Restituisce l'indice della prima/ultima occorrenza dell'elemento nella lista. Restituisce 0 se il testo non viene trovato."; +Blockly.Msg.LISTS_INLIST = "nella lista"; +Blockly.Msg.LISTS_IS_EMPTY_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#is_empty"; // untranslated +Blockly.Msg.LISTS_IS_EMPTY_TITLE = "%1 è vuota"; +Blockly.Msg.LISTS_LENGTH_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#length_of"; // untranslated +Blockly.Msg.LISTS_LENGTH_TITLE = "lunghezza di %1"; +Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Restituisce la lunghezza della lista"; +Blockly.Msg.LISTS_REPEAT_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#create_list_with"; // untranslated +Blockly.Msg.LISTS_REPEAT_TITLE = "crea una lista con l'elemento %1 ripetuto %2 volte"; +Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Crea una lista costituita dal valore indicato ripetuto per il numero di volte specificato."; +Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#in_list_..._set"; // untranslated +Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "come"; +Blockly.Msg.LISTS_SET_INDEX_INSERT = "inserisci in"; +Blockly.Msg.LISTS_SET_INDEX_SET = "imposta"; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Inserisci l'elemento all'inizio della lista."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = "Inserisci l'elemento nella posizione indicata in una lista. #1 corrisponde all'ultimo elemento."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = "Inserisci un elemento nella posizione indicata in una lista. #1 corrisponde al primo elemento."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Aggiungi un elemento alla fine di una lista"; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Inserisce l'elemento casualmente in una lista."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Imposta il primo elemento in una lista."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = "Imposta l'elemento nella posizione indicata di una lista. 1 corrisponde all'ultimo elemento."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = "Imposta l'elemento nella posizione indicata di una lista. 1 corrisponde al primo elemento."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Imposta l'ultimo elemento in una lista."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Imposta un elemento casuale in una lista."; +Blockly.Msg.LISTS_TOOLTIP = "Restituisce vero se la lista è vuota."; +Blockly.Msg.LOGIC_BOOLEAN_FALSE = "falso"; +Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "http://code.google.com/p/blockly/wiki/True_False"; // untranslated +Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Restituisce vero o falso."; +Blockly.Msg.LOGIC_BOOLEAN_TRUE = "vero"; +Blockly.Msg.LOGIC_COMPARE_HELPURL = "http://it.wikipedia.org/wiki/Disuguaglianza"; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Restituisce vero se gli input sono uno uguale all'altro."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Restituisce vero se il primo input è maggiore o uguale al secondo."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Restituisce uguale se il primo input è maggiore o uguale al secondo input."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Restituisce vero se il primo input è minore del secondo."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Restituisce vero se il primo input è minore o uguale al secondo."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Restituisce vero se gli input non sono uno uguale all'altro."; +Blockly.Msg.LOGIC_NEGATE_HELPURL = "http://code.google.com/p/blockly/wiki/Not"; // untranslated +Blockly.Msg.LOGIC_NEGATE_TITLE = "non %1"; +Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Restituisce vero se l'input è falso. Restituisce falso se l'input è vero."; +Blockly.Msg.LOGIC_NULL = "nullo"; +Blockly.Msg.LOGIC_NULL_HELPURL = "http://en.wikipedia.org/wiki/Nullable_type"; // untranslated +Blockly.Msg.LOGIC_NULL_TOOLTIP = "Restituisce valore nullo."; +Blockly.Msg.LOGIC_OPERATION_AND = "e"; +Blockly.Msg.LOGIC_OPERATION_HELPURL = "http://code.google.com/p/blockly/wiki/And_Or"; // untranslated +Blockly.Msg.LOGIC_OPERATION_OR = "o"; +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Restituisce vero se entrambi gli input sono veri."; +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Restituisce vero se almeno uno degli input è vero."; +Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; +Blockly.Msg.LOGIC_TERNARY_HELPURL = "http://en.wikipedia.org/wiki/%3F:"; // untranslated +Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "se falso"; +Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "se vero"; +Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Verifica la condizione in 'test'. Se questa è vera restituisce il valore 'se vero' altrimenti restituisce il valore 'se falso'."; +Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated +Blockly.Msg.MATH_ARITHMETIC_HELPURL = "http://it.wikipedia.org/wiki/Aritmetica"; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Restituisce la somma dei due numeri."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Restituisce il quoziente dei due numeri."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Restituisce la differenza dei due numeri."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Restituisce il prodotto dei due numeri."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Restituisce il primo numero elevato alla potenza del secondo numero."; +Blockly.Msg.MATH_CHANGE_HELPURL = "http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; // untranslated +Blockly.Msg.MATH_CHANGE_INPUT_BY = "di"; +Blockly.Msg.MATH_CHANGE_TITLE_CHANGE = "cambia"; +Blockly.Msg.MATH_CHANGE_TOOLTIP = "Aggiunge un numero alla variabile '%1'."; +Blockly.Msg.MATH_CONSTANT_HELPURL = "http://it.wikipedia.org/wiki/Costante_matematica"; +Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Restituisce una delle costanti comuniː π (3.141…), e (2.718…), φ (1.618…), radq(2) (1.414…), radq(½) (0.707…) o ∞ (infinito)."; +Blockly.Msg.MATH_CONSTRAIN_HELPURL = "http://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated +Blockly.Msg.MATH_CONSTRAIN_TITLE = "costringi %1 da %2 a %3"; +Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Costringe un numero all'interno dei limiti indicati (compresi)."; +Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated +Blockly.Msg.MATH_IS_DIVISIBLE_BY = "è divisibile per"; +Blockly.Msg.MATH_IS_EVEN = "è pari"; +Blockly.Msg.MATH_IS_NEGATIVE = "è negativo"; +Blockly.Msg.MATH_IS_ODD = "è dispari"; +Blockly.Msg.MATH_IS_POSITIVE = "è positivo"; +Blockly.Msg.MATH_IS_PRIME = "è primo"; +Blockly.Msg.MATH_IS_TOOLTIP = "Verifica se un numero è pari, dispari, primo, intero, positivo, negativo o se è divisibile per un certo numero. Restituisce vero o falso."; +Blockly.Msg.MATH_IS_WHOLE = "è intero"; +Blockly.Msg.MATH_MODULO_HELPURL = "http://it.wikipedia.org/wiki/Resto"; +Blockly.Msg.MATH_MODULO_TITLE = "resto di %1 ÷ %2"; +Blockly.Msg.MATH_MODULO_TOOLTIP = "Restituisce il resto della divisione di due numeri."; +Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated +Blockly.Msg.MATH_NUMBER_HELPURL = "http://it.wikipedia.org/wiki/Numero"; +Blockly.Msg.MATH_NUMBER_TOOLTIP = "Un numero."; +Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated +Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "media della lista"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "massimo della lista"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "mediana della lista"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "minimo della lista"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "mode della lista"; +Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "elemento casuale della lista"; +Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "deviazione standard della lista"; +Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "somma la lista"; +Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Restituisce la media (media aritmetica) dei valori numerici nella lista."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Restituisce il più grande numero della lista."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Restituisce il valore mediano della lista."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Restituisce il più piccolo numero della lista."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Restituisce una lista degli elementi più frequenti nella lista."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Restituisce un elemento casuale della lista."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Restituisce la deviazione standard della lista."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Restituisce la somma si tutti i numeri nella lista."; +Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated +Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "http://it.wikipedia.org/wiki/Numeri_pseudo-casuali"; +Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "frazione casuale"; +Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Restituisce una frazione compresa fra 0.0 (incluso) e 1.0 (escluso)."; +Blockly.Msg.MATH_RANDOM_INT_HELPURL = "http://it.wikipedia.org/wiki/Numeri_pseudo-casuali"; +Blockly.Msg.MATH_RANDOM_INT_TITLE = "intero casuale da %1 a %2"; +Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Restituisce un numero intero casuale compreso tra i due limiti indicati (inclusi)."; +Blockly.Msg.MATH_ROUND_HELPURL = "http://it.wikipedia.org/wiki/Arrotondamento"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "arrotonda"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "arrotonda verso il basso"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "arrotonda verso l'alto"; +Blockly.Msg.MATH_ROUND_TOOLTIP = "Arrotonda un numero verso l'alto o verso il basso."; +Blockly.Msg.MATH_SINGLE_HELPURL = "http://it.wikipedia.org/wiki/Radice_quadrata"; +Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "assoluto"; +Blockly.Msg.MATH_SINGLE_OP_ROOT = "radice quadrata"; +Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Restituisce il valore assoluto del numero."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Restituisce e elevato alla potenza del numero."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Restituisce il logaritmo naturale del numero."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Restituisce il logaritmo in base 10 del numero."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Restituisce l'opposto del numero."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Restituisce 10 elevato alla potenza del numero."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Restituisce la radice quadrata del numero."; +Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated +Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated +Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated +Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated +Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated +Blockly.Msg.MATH_TRIG_HELPURL = "http://it.wikipedia.org/wiki/Funzione_trigonometrica"; +Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated +Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated +Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Restituisce l'arco-coseno di un numero."; +Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Restituisce l'arco-seno di un numero."; +Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Restituisce l'arco-tangente di un numero."; +Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Restituisce il coseno di un angolo espresso in gradi (non radianti)."; +Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Restituisce il seno di un angolo espresso in gradi (non radianti)."; +Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Restituisce la tangente di un angolo espresso in gradi (non radianti)."; +Blockly.Msg.NEW_VARIABLE = "Nuova variabile..."; +Blockly.Msg.NEW_VARIABLE_TITLE = "Nome della nuova variabile:"; +Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated +Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "conː"; +Blockly.Msg.PROCEDURES_CALLNORETURN_CALL = ""; // untranslated +Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "http://it.wikipedia.org/wiki/Funzione_(informatica)"; +Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Esegue la funzione definita dall'utente '%1'."; +Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "http://it.wikipedia.org/wiki/Funzione_(informatica)"; +Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Esegue la funzione definita dall'utente '%1' ed usa il suo output."; +Blockly.Msg.PROCEDURES_CREATE_DO = "Crea '%1'"; +Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated +Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated +Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "fai qualcosa"; +Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "per"; +Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Crea una funzione senza output."; +Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated +Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "ritorna"; +Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Crea una funzione con un output."; +Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Attenzioneː Questa funzione ha parametri duplicati."; +Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Evidenzia definizione di funzione"; +Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Se un valore è vero allora restituisce un secondo valore."; +Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Attenzioneː Questo blocco può essere usato solo all'interno di una definizione di funzione."; +Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "nome inputː"; +Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "input"; +Blockly.Msg.REMOVE_COMMENT = "Rimuovi commento"; +Blockly.Msg.RENAME_VARIABLE = "Rinomina variabile..."; +Blockly.Msg.RENAME_VARIABLE_TITLE = "Rinomina tutte le variabili '%1' in:"; +Blockly.Msg.TEXT_APPEND_APPENDTEXT = "aggiungi il testo"; +Blockly.Msg.TEXT_APPEND_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Text_modification"; // untranslated +Blockly.Msg.TEXT_APPEND_TO = "a"; +Blockly.Msg.TEXT_APPEND_TOOLTIP = "Aggiunge del testo alla variabile '%1'."; +Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case"; // untranslated +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "in minuscolo"; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "con Iniziali Maiuscole"; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "in MAIUSCOLO"; +Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Restituisce una copia del testo in un diverso formato maiuscole/minuscole."; +Blockly.Msg.TEXT_CHARAT_FIRST = "prendi la prima lettera"; +Blockly.Msg.TEXT_CHARAT_FROM_END = "prendi la lettera # dalla fine"; +Blockly.Msg.TEXT_CHARAT_FROM_START = "prendi la lettera #"; +Blockly.Msg.TEXT_CHARAT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Extracting_text"; // untranslated +Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "nel testo"; +Blockly.Msg.TEXT_CHARAT_LAST = "prendi l'ultima lettera"; +Blockly.Msg.TEXT_CHARAT_RANDOM = "prendi lettera casuale"; +Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated +Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Restituisce la lettera nella posizione indicata."; +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Aggiungi un elemento al testo."; +Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "unisci"; +Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Aggiungi, rimuovi o riordina le sezioni per riconfigurare questo blocco testo."; +Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "alla lettera # dalla fine"; +Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "alla lettera #"; +Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "all'ultima lettera"; +Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text"; // untranslated +Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "nel testo"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "prendi sotto-stringa dalla prima lettera"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "prendi sotto-stringa dalla lettera # dalla fine"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "prendi sotto-stringa dalla lettera #"; +Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated +Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Restituisce la porzione di testo indicata."; +Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Finding_text"; // untranslated +Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "nel testo"; +Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "trova la prima occorrenza del testo"; +Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "trova l'ultima occorrenza del testo"; +Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated +Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Restituisce l'indice della prima occorrenza del primo testo all'interno del secondo testo. Restituisce 0 se il testo non viene trovato."; +Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text"; // untranslated +Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 è vuoto"; +Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Restituisce vero se il testo fornito è vuoto."; +Blockly.Msg.TEXT_JOIN_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Text_creation"; // untranslated +Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "crea testo con"; +Blockly.Msg.TEXT_JOIN_TOOLTIP = "Crea un blocco di testo unendo un certo numero di elementi."; +Blockly.Msg.TEXT_LENGTH_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Text_modification"; // untranslated +Blockly.Msg.TEXT_LENGTH_TITLE = "lunghezza di %1"; +Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Restituisce il numero di lettere (inclusi gli spazi) nel testo fornito."; +Blockly.Msg.TEXT_PRINT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Printing_text"; // untranslated +Blockly.Msg.TEXT_PRINT_TITLE = "scrivi %1"; +Blockly.Msg.TEXT_PRINT_TOOLTIP = "Scrive il testo, numero o altro valore indicato."; +Blockly.Msg.TEXT_PROMPT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user"; // untranslated +Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Richiedi un numero all'utente."; +Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Richiede del testo da parte dell'utente."; +Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "richiedi numero con messaggio"; +Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "richiedi testo con messaggio"; +Blockly.Msg.TEXT_TEXT_HELPURL = "http://it.wikipedia.org/wiki/Stringa_(informatica)"; +Blockly.Msg.TEXT_TEXT_TOOLTIP = "Una lettera, una parola o una linea di testo."; +Blockly.Msg.TEXT_TRIM_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces"; // untranslated +Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "rimuovi spazi da entrambi gli estremi"; +Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "rimuovi spazi a sinistra"; +Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "rimuovi spazi a destra"; +Blockly.Msg.TEXT_TRIM_TOOLTIP = "Restituisce una copia del testo con gli spazi rimossi ad uno o entrambe le estremità."; +Blockly.Msg.VARIABLES_DEFAULT_NAME = "elemento"; +Blockly.Msg.VARIABLES_GET_CREATE_SET = "Crea 'imposta %1'"; +Blockly.Msg.VARIABLES_GET_HELPURL = "http://code.google.com/p/blockly/wiki/Variables#Get"; // untranslated +Blockly.Msg.VARIABLES_GET_TAIL = ""; // untranslated +Blockly.Msg.VARIABLES_GET_TITLE = ""; // untranslated +Blockly.Msg.VARIABLES_GET_TOOLTIP = "Restituisce il valore di una variabile."; +Blockly.Msg.VARIABLES_SET_CREATE_GET = "Crea 'prendi %1'"; +Blockly.Msg.VARIABLES_SET_HELPURL = "http://code.google.com/p/blockly/wiki/Variables#Set"; // untranslated +Blockly.Msg.VARIABLES_SET_TAIL = "a"; +Blockly.Msg.VARIABLES_SET_TITLE = "imposta"; +Blockly.Msg.VARIABLES_SET_TOOLTIP = "Imposta questa variabile ad essere pari all'input."; +Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; +Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; +Blockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; +Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL; +Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; +Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; +Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; \ No newline at end of file diff --git a/msg/js/pt_br.js b/msg/js/pt_br.js new file mode 100644 index 000000000..3e08efa8f --- /dev/null +++ b/msg/js/pt_br.js @@ -0,0 +1,377 @@ +// This file was automatically generated. Do not modify. + +'use strict'; + +goog.provide('Blockly.Msg.pt_br'); + +goog.require('Blockly.Msg'); + +Blockly.Msg.ADD_COMMENT = "Criar Comentário"; +Blockly.Msg.CHANGE_VALUE_TITLE = "Alterar valor:"; +Blockly.Msg.COLLAPSE_ALL = "Recolher Blocos"; +Blockly.Msg.COLLAPSE_BLOCK = "Recolher Bloco"; +Blockly.Msg.COLOUR_BLEND_COLOUR1 = "cor 1"; +Blockly.Msg.COLOUR_BLEND_COLOUR2 = "cor 2"; +Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated +Blockly.Msg.COLOUR_BLEND_RATIO = "razão"; +Blockly.Msg.COLOUR_BLEND_TITLE = "misturar"; +Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Mistura duas cores usando uma razão dada (0.0 - 1.0)."; +Blockly.Msg.COLOUR_PICKER_HELPURL = "http://pt.wikipedia.org/wiki/Cor"; +Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Escolha uma cor da palheta de cores."; +Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated +Blockly.Msg.COLOUR_RANDOM_TITLE = "cor aleatória"; +Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Escolher uma cor aleatoriamente."; +Blockly.Msg.COLOUR_RGB_BLUE = "azul"; +Blockly.Msg.COLOUR_RGB_GREEN = "verde"; +Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated +Blockly.Msg.COLOUR_RGB_RED = "vermelho"; +Blockly.Msg.COLOUR_RGB_TITLE = "cor com"; +Blockly.Msg.COLOUR_RGB_TOOLTIP = "Crie uma cor com os valores especificados de vermelho, verde e azul. Todos os valores devem estar entre 0 e 100."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks"; // untranslated +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "encerra o laço"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "continua com a próxima iteração do laço"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Encerra o laço."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Ignora o resto deste laço, e continua com a próxima iteração."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Atenção: Este bloco só pode ser usado dentro de um laço."; +Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#for_each for each block"; // untranslated +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = "na lista"; +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = ""; +Blockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = "para cada item"; +Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Para cada item em uma lista, define o item para a variável \"%1\", e então realiza alguns passos."; +Blockly.Msg.CONTROLS_FOR_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#count_with"; // untranslated +Blockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = "de %1 ate %2 por %3"; +Blockly.Msg.CONTROLS_FOR_INPUT_WITH = "contar com"; +Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Conta de um número inicial até um número final pelo intervalo especificado. Para cada contagem, define o contador atual para a variável \"%1\", e então realiza alguns passos."; +Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Acrescente uma condição para o bloco se."; +Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Acrescente uma condição final para o bloco se."; +Blockly.Msg.CONTROLS_IF_HELPURL = "http://code.google.com/p/blockly/wiki/If_Then"; // untranslated +Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Acrescente, remova ou reordene seções para reconfigurar este bloco."; +Blockly.Msg.CONTROLS_IF_MSG_ELSE = "senão"; +Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "senão se"; +Blockly.Msg.CONTROLS_IF_MSG_IF = "se"; +Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Se um valor é verdadeiro, então realize alguns passos."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Se um valor é verdadeiro, então realize o primeiro bloco de passos. Senão, realize o segundo bloco de passos."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Se o primeiro valor é verdadeiro, então realize o primeiro bloco de passos. Senão, se o segundo valor é verdadeiro, realize o segundo bloco de passos."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Se o primeiro valor é verdadeiro, então realize o primeiro bloco de passos. Senão, se o segundo valor é verdadeiro, realize o segundo bloco de passos. Se nenhum dos blocos for verdadeiro, realize o último bloco de passos."; +Blockly.Msg.CONTROLS_REPEAT_HELPURL = "http://en.wikipedia.org/wiki/For_loop"; // untranslated +Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "faça"; +Blockly.Msg.CONTROLS_REPEAT_TITLE = "repetir %1 vezes"; +Blockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = "repetir"; +Blockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = "vezes"; +Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Realiza os passos várias vezes."; +Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "http://code.google.com/p/blockly/wiki/Repeat"; // untranslated +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "repita até"; +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "repita enquanto"; +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Enquanto um valor é falso, então realize alguns passos."; +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Enquanto um valor é verdadeiro, então realize alguns passos."; +Blockly.Msg.DELETE_BLOCK = "Excluir Bloco"; +Blockly.Msg.DELETE_X_BLOCKS = "Excluir %1 Blocos"; +Blockly.Msg.DISABLE_BLOCK = "Desabilitar Bloco"; +Blockly.Msg.DUPLICATE_BLOCK = "Duplicado"; +Blockly.Msg.ENABLE_BLOCK = "Habilitar Bloco"; +Blockly.Msg.EXPAND_ALL = "Expandir Blocos"; +Blockly.Msg.EXPAND_BLOCK = "Expandir Bloco"; +Blockly.Msg.EXTERNAL_INPUTS = "Entradas Externas"; +Blockly.Msg.HELP = "Ajuda"; +Blockly.Msg.INLINE_INPUTS = "Entradas Internas"; +Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "http://en.wikipedia.org/wiki/Linked_list#Empty_lists"; // untranslated +Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "criar lista vazia"; +Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Retorna uma lista, de tamanho 0, contendo nenhum registro"; +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "lista"; +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Acrescente, remova ou reordene as seções para reconfigurar este bloco."; +Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "criar lista com"; +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Acrescenta um item à lista."; +Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Cria uma lista com a quantidade de itens informada."; +Blockly.Msg.LISTS_GET_INDEX_FIRST = "primeiro"; +Blockly.Msg.LISTS_GET_INDEX_FROM_END = "nº a partir do final"; +Blockly.Msg.LISTS_GET_INDEX_FROM_START = "nº"; +Blockly.Msg.LISTS_GET_INDEX_GET = "obter"; +Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "obter e remover"; +Blockly.Msg.LISTS_GET_INDEX_LAST = "último"; +Blockly.Msg.LISTS_GET_INDEX_RANDOM = "aleatório"; +Blockly.Msg.LISTS_GET_INDEX_REMOVE = "remover"; +Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Retorna o primeiro item em uma lista."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = "Retorna o item da lista na posição especificada. #1 é o último item."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = "Retorna o item da lista na posição especificada. #1 é o primeiro item."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Retorna o último item em uma lista."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Retorna um item aleatório de uma lista."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Remove e retorna o primeiro item de uma lista."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = "Remove and retorna o item na posição especificada em uma lista. #1 é o último item."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = "Remove and retorna o item na posição especificada em uma lista. #1 é o primeiro item."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Remove e retorna o último item de uma lista."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Remove e retorna um item aleatório de uma lista."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Remove o primeiro item de uma lista."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = "Removes the item at the specified position em uma lista. #1 é o último item."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = "Remove e retorna o item na posição especificada em uma lista. #1 é o primeiro item."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Remove o último item de uma lista."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Remove um item aleatório de uma lista."; +Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "até nº a partir do final"; +Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "até nº"; +Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "até último"; +Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist"; // untranslated +Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "obtem sublista primeiro"; +Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "obtem sublista de nº a partir do final"; +Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "obtem sublista de nº"; +Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated +Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Cria uma cópia da porção especificada de uma lista."; +Blockly.Msg.LISTS_INDEX_OF_FIRST = "encontre a primeira ocorrência do item"; +Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List"; // untranslated +Blockly.Msg.LISTS_INDEX_OF_LAST = "encontre a última ocorrência do item"; +Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Retorna a posição da primeira/última ocorrência do item na lista. Retorna 0 se o texto não for encontrado."; +Blockly.Msg.LISTS_INLIST = "in list"; // untranslated +Blockly.Msg.LISTS_IS_EMPTY_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#is_empty"; // untranslated +Blockly.Msg.LISTS_IS_EMPTY_TITLE = "%1 é vazia"; +Blockly.Msg.LISTS_LENGTH_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#length_of"; // untranslated +Blockly.Msg.LISTS_LENGTH_TITLE = "tamanho de %1"; +Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Retorna o tamanho de uma lista."; +Blockly.Msg.LISTS_REPEAT_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#create_list_with"; // untranslated +Blockly.Msg.LISTS_REPEAT_TITLE = "criar lista com item %1 repetido %2 vezes"; +Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Cria uma lista consistida pelo valor informado repetido o número de vezes especificado."; +Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#in_list_..._set"; // untranslated +Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "como"; +Blockly.Msg.LISTS_SET_INDEX_INSERT = "inserir em"; +Blockly.Msg.LISTS_SET_INDEX_SET = "definir"; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Insere o item no início da lista."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = "Insere o item na posição especificada em uma lista. #1 é o último item."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = "Insere o item na posição especificada em uma lista. #1 é o primeiro item."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Insere o item no final da lista."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Insere o item em uma posição qualquer da lista."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Define o primeiro item de uma lista."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = "Define o item da posição especificada de uma lista. #1 é o último item."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = "Define o item da posição especificada de uma lista. #1 é o primeiro item."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Define o último item de uma lista."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Define um item aleatório de uma lista."; +Blockly.Msg.LISTS_TOOLTIP = "Retona verdadeiro se a lista estiver vazia."; +Blockly.Msg.LOGIC_BOOLEAN_FALSE = "falso"; +Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "http://code.google.com/p/blockly/wiki/True_False"; // untranslated +Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Retorna verdadeiro ou falso."; +Blockly.Msg.LOGIC_BOOLEAN_TRUE = "verdadeiro"; +Blockly.Msg.LOGIC_COMPARE_HELPURL = "http://en.wikipedia.org/wiki/Inequality_(mathematics)"; // untranslated +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Retorna verdadeiro se ambas as entradas forem iguais."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Retorna verdadeiro se a primeira entrada for maior que a segunda entrada."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Retorna verdadeiro se a primeira entrada for maior ou igual à segunda entrada."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Retorna verdadeiro se a primeira entrada for menor que a segunda entrada."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Retorna verdadeiro se a primeira entrada for menor ou igual à segunda entrada."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Retorna verdadeiro se ambas as entradas forem diferentes."; +Blockly.Msg.LOGIC_NEGATE_HELPURL = "http://code.google.com/p/blockly/wiki/Not"; // untranslated +Blockly.Msg.LOGIC_NEGATE_TITLE = "não %1"; +Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Retorna verdadeiro se a entrada for falsa. Retorna false se a entrada for verdadeira."; +Blockly.Msg.LOGIC_NULL = "nulo"; +Blockly.Msg.LOGIC_NULL_HELPURL = "http://en.wikipedia.org/wiki/Nullable_type"; // untranslated +Blockly.Msg.LOGIC_NULL_TOOLTIP = "Retorna nulo."; +Blockly.Msg.LOGIC_OPERATION_AND = "e"; +Blockly.Msg.LOGIC_OPERATION_HELPURL = "http://code.google.com/p/blockly/wiki/And_Or"; // untranslated +Blockly.Msg.LOGIC_OPERATION_OR = "ou"; +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Retorna verdadeiro se ambas as entradas forem verdadeiras."; +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Retorna verdadeiro se uma das estradas for verdadeira."; +Blockly.Msg.LOGIC_TERNARY_CONDITION = "teste"; +Blockly.Msg.LOGIC_TERNARY_HELPURL = "http://en.wikipedia.org/wiki/%3F:"; // untranslated +Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "se falso"; +Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "se verdadeiro"; +Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Avalia a condição em \"teste\". Se a condição for verdadeira retorna o valor \"se verdadeiro\", senão retorna o valor \"se falso\"."; +Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated +Blockly.Msg.MATH_ARITHMETIC_HELPURL = "http://en.wikipedia.org/wiki/Arithmetic"; // untranslated +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Retorna a soma de dois números."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Retorna o quociente da divisão de dois números."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Retorna a diferença de dois números."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Retorna o produto de dois números."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Retorna o primeiro número elevado à potência do segundo número."; +Blockly.Msg.MATH_CHANGE_HELPURL = "http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; // untranslated +Blockly.Msg.MATH_CHANGE_INPUT_BY = "por"; +Blockly.Msg.MATH_CHANGE_TITLE_CHANGE = "alterar"; +Blockly.Msg.MATH_CHANGE_TOOLTIP = "Soma um número à variável \"%1\"."; +Blockly.Msg.MATH_CONSTANT_HELPURL = "http://en.wikipedia.org/wiki/Mathematical_constant"; // untranslated +Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Retorna uma das constantes comuns: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), ou ∞ (infinito)."; +Blockly.Msg.MATH_CONSTRAIN_HELPURL = "http://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated +Blockly.Msg.MATH_CONSTRAIN_TITLE = "restringe %1 inferior %2 superior %3"; +Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Restringe um número entre os limites especificados (inclusive)."; +Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated +Blockly.Msg.MATH_IS_DIVISIBLE_BY = "é divisível por"; +Blockly.Msg.MATH_IS_EVEN = "é par"; +Blockly.Msg.MATH_IS_NEGATIVE = "é negativo"; +Blockly.Msg.MATH_IS_ODD = "é impar"; +Blockly.Msg.MATH_IS_POSITIVE = "é positivo"; +Blockly.Msg.MATH_IS_PRIME = "é primo"; +Blockly.Msg.MATH_IS_TOOLTIP = "Verifica se um número é par, impar, inteiro, positivo, negativo, ou se é divisível por outro número. Retorna verdadeiro ou falso."; +Blockly.Msg.MATH_IS_WHOLE = "é inteiro"; +Blockly.Msg.MATH_MODULO_HELPURL = "http://en.wikipedia.org/wiki/Modulo_operation"; // untranslated +Blockly.Msg.MATH_MODULO_TITLE = "resto da divisão de %1 ÷ %2"; +Blockly.Msg.MATH_MODULO_TOOLTIP = "Retorna o resto da divisão de dois números."; +Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated +Blockly.Msg.MATH_NUMBER_HELPURL = "http://en.wikipedia.org/wiki/Number"; // untranslated +Blockly.Msg.MATH_NUMBER_TOOLTIP = "Um número."; +Blockly.Msg.MATH_ONLIST_HELPURL = ""; +Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "média de uma lista"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "maior de uma lista"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "mediana de uma lista"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "menor de uma lista"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "modo de uma lista"; +Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "item aleatório de uma lista"; +Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "desvio padrão de uma lista"; +Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "soma de uma lista"; +Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Retorna a média aritmética de os números de uma lista."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Retorna o maior número de uma lista."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Retorna a mediana de os números em uma lista."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Retorna o menor número de uma lista."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Retorna a lista de item(ns) mais comum(ns) de uma lista."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Retorna um elemento aleatório de uma lista."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Retorna o desvio padrão de os números de uma lista."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Retorna a soma de todos os números em uma lista."; +Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated +Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "http://en.wikipedia.org/wiki/Random_number_generation"; // untranslated +Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "random fraction"; +Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive)."; +Blockly.Msg.MATH_RANDOM_INT_HELPURL = "http://en.wikipedia.org/wiki/Random_number_generation"; // untranslated +Blockly.Msg.MATH_RANDOM_INT_TITLE = "inteiro aleatório entre %1 ate %2"; +Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Retorna um número inteiro entre os dois limites informados, inclusive."; +Blockly.Msg.MATH_ROUND_HELPURL = "http://en.wikipedia.org/wiki/Rounding"; // untranslated +Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "arredonda"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "arredonda para baixo"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "arredonda para cima"; +Blockly.Msg.MATH_ROUND_TOOLTIP = "Arredonda um número para cima ou para baixo."; +Blockly.Msg.MATH_SINGLE_HELPURL = "http://en.wikipedia.org/wiki/Square_root"; // untranslated +Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "absoluto"; +Blockly.Msg.MATH_SINGLE_OP_ROOT = "raíz quadrada"; +Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Retorna o valor absoluto de um número."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Retorna o número e elevado à potência de um número."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Retorna o logarítmo natural de um número."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Retorna o logarítmo em base 10 de um número."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Retorna o oposto de um número."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Retorna 10 elevado à potência de um número."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Retorna a raiz quadrada de um número."; +Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated +Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated +Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated +Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated +Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated +Blockly.Msg.MATH_TRIG_HELPURL = "http://en.wikipedia.org/wiki/Trigonometric_functions"; // untranslated +Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated +Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated +Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Retorna o arco cosseno de um número."; +Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Retorna o arco seno de um número."; +Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Retorna o arco tangente de um número."; +Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Retorna o cosseno de um grau (não radiano)."; +Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Retorna o seno de um grau (não radiano)."; +Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Retorna a tangente de um grau (não radiano)."; +Blockly.Msg.NEW_VARIABLE = "Nova variável..."; +Blockly.Msg.NEW_VARIABLE_TITLE = "Novo nome de variável:"; +Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated +Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "com:"; +Blockly.Msg.PROCEDURES_CALLNORETURN_CALL = ""; +Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated +Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Executa a função \"%1\"."; +Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated +Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Executa a função \"%1\" e usa seu retorno."; +Blockly.Msg.PROCEDURES_CREATE_DO = "Criar \"%1\""; +Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; +Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated +Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "faça algo"; +Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "para"; +Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Cria uma função que não tem retorno."; +Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated +Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "retorna"; +Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Cria uma função que possui um valor de retorno."; +Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Atenção: Esta função tem parâmetros duplicados."; +Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Destacar definição de procedimento"; +Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Se o valor é verdadeiro, então retorna um valor."; +Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Atenção: Este bloco só pode ser utilizado dentro da definição de uma função."; +Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "nome da entrada:"; +Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "entradas"; +Blockly.Msg.REMOVE_COMMENT = "Remover Comentário"; +Blockly.Msg.RENAME_VARIABLE = "Renomear variável..."; +Blockly.Msg.RENAME_VARIABLE_TITLE = "Renomear todas as \"%1\" variáveis para:"; +Blockly.Msg.TEXT_APPEND_APPENDTEXT = "acrescentar texto"; +Blockly.Msg.TEXT_APPEND_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Text_modification"; // untranslated +Blockly.Msg.TEXT_APPEND_TO = "para"; +Blockly.Msg.TEXT_APPEND_TOOLTIP = "Acrescentar um pedaço de texto à variável \"%1\"."; +Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case"; // untranslated +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "para minúsculas"; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "para Nomes Próprios"; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "para MAIÚSCULAS"; +Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Retorna uma cópia do texto em um formato diferente."; +Blockly.Msg.TEXT_CHARAT_FIRST = "obter primeira letra"; +Blockly.Msg.TEXT_CHARAT_FROM_END = "obter letra nº a partir do final"; +Blockly.Msg.TEXT_CHARAT_FROM_START = "obter letra nº"; +Blockly.Msg.TEXT_CHARAT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Extracting_text"; // untranslated +Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "no texto"; +Blockly.Msg.TEXT_CHARAT_LAST = "obter última letra"; +Blockly.Msg.TEXT_CHARAT_RANDOM = "obter letra aleatória"; +Blockly.Msg.TEXT_CHARAT_TAIL = ""; +Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Retorna a letra na posição especificada."; +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Acrescentar um item ao texto."; +Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "unir"; +Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Acrescenta, remove ou reordena seções para reconfigurar este bloco de texto."; +Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "até letra nº a partir do final"; +Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "até letra nº"; +Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "até última letra"; +Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text"; // untranslated +Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "no texto"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "obter trecho de primeira letra"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "obter trecho de letra nº a partir do final"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "obter trecho de letra nº"; +Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; +Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Retorna o trecho de texto especificado."; +Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Finding_text"; // untranslated +Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "no texto"; +Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "primeira ocorrência do texto"; +Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "última ocorrência do texto"; +Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated +Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Retorna a posição da primeira/última ocorrência do primeiro texto no segundo texto. Retorna 0 se o texto não for encontrado."; +Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text"; // untranslated +Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 é vazio"; +Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Retorna verdadeiro se o texto fornecido for vazio."; +Blockly.Msg.TEXT_JOIN_HELPURL = ""; +Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "criar texto com"; +Blockly.Msg.TEXT_JOIN_TOOLTIP = "Criar um pedaço de texto juntando qualquer número de itens."; +Blockly.Msg.TEXT_LENGTH_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Text_modification"; // untranslated +Blockly.Msg.TEXT_LENGTH_TITLE = "tamanho de %1"; +Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Conta o número de letras (incluindo espaços) no texto fornecido."; +Blockly.Msg.TEXT_PRINT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Printing_text"; // untranslated +Blockly.Msg.TEXT_PRINT_TITLE = "imprime %1"; +Blockly.Msg.TEXT_PRINT_TOOLTIP = "Imprime o texto, número ou valor especificado."; +Blockly.Msg.TEXT_PROMPT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user"; // untranslated +Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Pede ao usuário um número."; +Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Pede ao usuário um texto."; +Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "Pede um número com uma mensagem"; +Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "Pede um texto com uma mensagem"; +Blockly.Msg.TEXT_TEXT_HELPURL = "http://en.wikipedia.org/wiki/String_(computer_science)"; // untranslated +Blockly.Msg.TEXT_TEXT_TOOLTIP = "Uma letra, palavra ou linha de texto."; +Blockly.Msg.TEXT_TRIM_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces"; // untranslated +Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "remover espaços de ambos os lados"; +Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "remover espaços à esquerda"; +Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "remover espaços à direita"; +Blockly.Msg.TEXT_TRIM_TOOLTIP = "Retorna uma cópia do texto com os espaços removidos de uma ou ambas extremidades."; +Blockly.Msg.VARIABLES_DEFAULT_NAME = "item"; // untranslated +Blockly.Msg.VARIABLES_GET_CREATE_SET = "Criar \"definir %1\""; +Blockly.Msg.VARIABLES_GET_HELPURL = "http://code.google.com/p/blockly/wiki/Variables#Get"; // untranslated +Blockly.Msg.VARIABLES_GET_TAIL = ""; +Blockly.Msg.VARIABLES_GET_TITLE = ""; +Blockly.Msg.VARIABLES_GET_TOOLTIP = "Retorna o valor desta variável."; +Blockly.Msg.VARIABLES_SET_CREATE_GET = "Criar \"obter %1\""; +Blockly.Msg.VARIABLES_SET_HELPURL = "http://code.google.com/p/blockly/wiki/Variables#Set"; // untranslated +Blockly.Msg.VARIABLES_SET_TAIL = "para"; +Blockly.Msg.VARIABLES_SET_TITLE = "definir"; +Blockly.Msg.VARIABLES_SET_TOOLTIP = "Define esta variável para o valor informado."; +Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; +Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; +Blockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; +Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL; +Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; +Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; +Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; \ No newline at end of file diff --git a/msg/js/ru.js b/msg/js/ru.js new file mode 100644 index 000000000..cfa205143 --- /dev/null +++ b/msg/js/ru.js @@ -0,0 +1,377 @@ +// This file was automatically generated. Do not modify. + +'use strict'; + +goog.provide('Blockly.Msg.ru'); + +goog.require('Blockly.Msg'); + +Blockly.Msg.ADD_COMMENT = "Добавить комментарий"; +Blockly.Msg.CHANGE_VALUE_TITLE = "Измените значение:"; +Blockly.Msg.COLLAPSE_ALL = "Свернуть блоки"; +Blockly.Msg.COLLAPSE_BLOCK = "Свернуть блок"; +Blockly.Msg.COLOUR_BLEND_COLOUR1 = "цвет 1"; +Blockly.Msg.COLOUR_BLEND_COLOUR2 = "цвет 2"; +Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated +Blockly.Msg.COLOUR_BLEND_RATIO = "отношение"; +Blockly.Msg.COLOUR_BLEND_TITLE = "смешать"; +Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Смешивает два цвета в заданном соотношении (0.0 - 1.0)."; +Blockly.Msg.COLOUR_PICKER_HELPURL = "http://ru.wikipedia.org/wiki/Цвет"; +Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Выберите цвет из палитры."; +Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated +Blockly.Msg.COLOUR_RANDOM_TITLE = "случайный цвет"; +Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Выбирает цвет случайным образом."; +Blockly.Msg.COLOUR_RGB_BLUE = "синий"; +Blockly.Msg.COLOUR_RGB_GREEN = "зелёный"; +Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated +Blockly.Msg.COLOUR_RGB_RED = "красный"; +Blockly.Msg.COLOUR_RGB_TITLE = "цвет из"; +Blockly.Msg.COLOUR_RGB_TOOLTIP = "Создаёт цвет с указанной пропорцией красного, зеленого и синего. Все значения должны быть между 0 и 100."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks"; // untranslated +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "выйти из цикла"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "перейти к следующему шагу цикла"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Прерывает этот цикл."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Пропустить остаток цикла и перейти к следующему шагу"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Предупреждение: этот блок может использоваться только внутри цикла."; +Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#for_each for each block"; // untranslated +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = "в списке"; +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = ""; // untranslated +Blockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = "для каждого элемента"; +Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Для каждого элемента в списке, присвоить переменной '%1' значение элемента и выполнить некоторые команды."; +Blockly.Msg.CONTROLS_FOR_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#count_with"; // untranslated +Blockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = "от %1 до %2 с шагом %3"; +Blockly.Msg.CONTROLS_FOR_INPUT_WITH = "цикл по"; +Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Присваивает переменной %1 значения от начального до конечного с заданным шагом и выполняет указанные блоки."; +Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Добавляет условие к блоку если"; +Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Добавить окончательное, обобщающее условие для блока «если»."; +Blockly.Msg.CONTROLS_IF_HELPURL = "http://code.google.com/p/blockly/wiki/If_Then"; // untranslated +Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Добавьте, удалите, переставьте фрагменты для переделки блока если."; +Blockly.Msg.CONTROLS_IF_MSG_ELSE = "иначе"; +Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "иначе если"; +Blockly.Msg.CONTROLS_IF_MSG_IF = "если"; +Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Если значение равно истина, выполняет команды"; +Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Если значение равно истина, исполняет первый блок команд. Иначе исполняется второй блок команд."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Если первое значение равно истина, то исполняет первый блок команд.Иначе, если второе значение равно истина, исполняет второй блок команд."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Если первое значение равно истина, то выполняет первый блок команд. В противном случае, если второе значение равно истина, выполняет второй блок команд. Если ни одно из значений не равно истина, выполняет последний блок операторов."; +Blockly.Msg.CONTROLS_REPEAT_HELPURL = "http://en.wikipedia.org/wiki/For_loop"; +Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "выполнять"; +Blockly.Msg.CONTROLS_REPEAT_TITLE = "повторить %1 раз"; +Blockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = "повторить"; +Blockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = "раз"; +Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Выполнить некоторые команды несколько раз."; +Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "http://code.google.com/p/blockly/wiki/Repeat"; // untranslated +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "повторять до"; +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "повторять, пока"; +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Пока значение равно ложь, выполняет команды"; +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Пока значение равно истина, выполняет команды"; +Blockly.Msg.DELETE_BLOCK = "Удалить блок"; +Blockly.Msg.DELETE_X_BLOCKS = "Удалить %1 блоков"; +Blockly.Msg.DISABLE_BLOCK = "Отключить блок"; +Blockly.Msg.DUPLICATE_BLOCK = "Скопировать"; +Blockly.Msg.ENABLE_BLOCK = "Включить блок"; +Blockly.Msg.EXPAND_ALL = "Развернуть блоки"; +Blockly.Msg.EXPAND_BLOCK = "Развернуть блок"; +Blockly.Msg.EXTERNAL_INPUTS = "Внешние параметры"; +Blockly.Msg.HELP = "Справка"; +Blockly.Msg.INLINE_INPUTS = "Показать внутренние параметры"; +Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "http://en.wikipedia.org/wiki/Linked_list#Empty_lists"; // untranslated +Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "создать пустой список"; +Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Возвращает список длины 0, не содержащий данных"; +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "список"; +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Добавьте, удалите, переставьте элементы для переделки блока списка."; +Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "создать список из"; +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Добавляет элемент к списку."; +Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Создаёт список с любым числом элементов."; +Blockly.Msg.LISTS_GET_INDEX_FIRST = "первый"; +Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# с конца"; +Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated +Blockly.Msg.LISTS_GET_INDEX_GET = "взять"; +Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "взять и удалить"; +Blockly.Msg.LISTS_GET_INDEX_LAST = "последний"; +Blockly.Msg.LISTS_GET_INDEX_RANDOM = "произвольный"; +Blockly.Msg.LISTS_GET_INDEX_REMOVE = "удалить"; +Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Возвращает первый элемент списка."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = "Возвращает элемент в указанной позиции списка. #1 - последний элемент."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = "Возвращает элемент в указанной позиции списка. #1 - первый элемент."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Возвращает последний элемент списка."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Возвращает случайный элемент списка."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Удаляет и возвращает первый элемент списка."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = "Удаляет и возвращает элемент в указанной позиции списка. #1 - последний элемент."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = "Удаляет и возвращает элемент в указанной позиции списка. #1 - первый элемент."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Удаляет и возвращает последний элемент списка."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Удаляет и возвращает случайный элемент списка."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Удаляет первый элемент списка."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = "Удаляет элемент в указанной позиции списка. #1 - последний элемент."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = "Удаляет элемент в указанной позиции списка. #1 - первый элемент."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Удаляет последний элемент списка."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Удаляет случайный элемент списка."; +Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "по # с конца"; +Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "по #"; +Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "по последний"; +Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist"; // untranslated +Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "взять подсписок с первого"; +Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "взять подсписок с # с конца"; +Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "взять подсписок с #"; +Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated +Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Создаёт копию указанной части списка."; +Blockly.Msg.LISTS_INDEX_OF_FIRST = "найти первое вхождение элемента"; +Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List"; // untranslated +Blockly.Msg.LISTS_INDEX_OF_LAST = "найти последнее вхождение элемента"; +Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Возвращает номер позиции первого/последнего вхождения элемента в списке. Возвращает 0, если текст не найден."; +Blockly.Msg.LISTS_INLIST = "в списке"; +Blockly.Msg.LISTS_IS_EMPTY_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#is_empty"; // untranslated +Blockly.Msg.LISTS_IS_EMPTY_TITLE = "%1 пуст"; +Blockly.Msg.LISTS_LENGTH_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#length_of"; // untranslated +Blockly.Msg.LISTS_LENGTH_TITLE = "длина %1"; +Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Возвращает длину списка."; +Blockly.Msg.LISTS_REPEAT_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#create_list_with"; // untranslated +Blockly.Msg.LISTS_REPEAT_TITLE = "создать список из элемента %1, повторяющегося %2 раз"; +Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Создаёт список, состоящий из заданного числа копий элемента."; +Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#in_list_..._set"; // untranslated +Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "равно"; +Blockly.Msg.LISTS_SET_INDEX_INSERT = "вставить в"; +Blockly.Msg.LISTS_SET_INDEX_SET = "присвоить"; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Вставляет элемент в начало списка."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = "Вставляет элемент в указанной позиции списка. #1 - последний элемент."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = "Вставляет элемент в указанной позиции списка. #1 - первый элемент."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Добавляет элемент в конец списка."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Вставляет элемент в случайное место в списке."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Присваивает значение первому элементу списка."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = "Присваивает значение элементу в указанной позиции списка. #1 - последний элемент."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = "Присваивает значение элементу в указанной позиции списка. #1 - первый элемент."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Присваивает значение последнему элементу списка."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Присваивает значение случайному элементу списка."; +Blockly.Msg.LISTS_TOOLTIP = "Возвращает значение истина, если список пуст."; +Blockly.Msg.LOGIC_BOOLEAN_FALSE = "ложь"; +Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "http://code.google.com/p/blockly/wiki/True_False"; // untranslated +Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Возвращает значение истина или ложь."; +Blockly.Msg.LOGIC_BOOLEAN_TRUE = "истина"; +Blockly.Msg.LOGIC_COMPARE_HELPURL = "http://en.wikipedia.org/wiki/Inequality_(mathematics)"; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Возвращает значение истина, если параметры равны."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Возвращает значение истина, если первый параметр больше второго."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Возвращает значение истина, если первый параметр больше или равен второму."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Возвращает значение истина, если первый параметр меньше второго."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Возвращает значение истина, если первый параметр меньше или равен второму."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Возвращает значение истинв, если параметры не равны."; +Blockly.Msg.LOGIC_NEGATE_HELPURL = "http://code.google.com/p/blockly/wiki/Not"; // untranslated +Blockly.Msg.LOGIC_NEGATE_TITLE = "не %1"; +Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Возвращает значение истина, если параметр имеет значение ложь. Возвращает значение ложь, если параметр имеет значение истина."; +Blockly.Msg.LOGIC_NULL = "ничто"; +Blockly.Msg.LOGIC_NULL_HELPURL = "http://en.wikipedia.org/wiki/Nullable_type"; +Blockly.Msg.LOGIC_NULL_TOOLTIP = "Возвращает ничто."; +Blockly.Msg.LOGIC_OPERATION_AND = "и"; +Blockly.Msg.LOGIC_OPERATION_HELPURL = "http://code.google.com/p/blockly/wiki/And_Or"; // untranslated +Blockly.Msg.LOGIC_OPERATION_OR = "или"; +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Возвращает значение истина, если оба параметра равны истина."; +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Возвращает значение истина, если хотя бы один из параметров имеет значение истина."; +Blockly.Msg.LOGIC_TERNARY_CONDITION = "тест"; +Blockly.Msg.LOGIC_TERNARY_HELPURL = "http://ru.wikipedia.org/wiki/Тернарная_условная_операция"; +Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "если ложь"; +Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "если истина"; +Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Проверить условие в 'test'. Если условие имеет значение «истина», возвращает значение 'если истина'; в противном случае возвращает значение 'если ложь'."; +Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated +Blockly.Msg.MATH_ARITHMETIC_HELPURL = "http://ru.wikipedia.org/wiki/Арифметика"; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Возвращает сумму двух чисел."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Возвращает частное от деления первого числа на второе."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Возвращает разность двух чисел."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Возвращает произведение двух чисел."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Возвращает первое число, возведённое в степень второго числа."; +Blockly.Msg.MATH_CHANGE_HELPURL = "http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; // untranslated +Blockly.Msg.MATH_CHANGE_INPUT_BY = "на"; +Blockly.Msg.MATH_CHANGE_TITLE_CHANGE = "увеличить"; +Blockly.Msg.MATH_CHANGE_TOOLTIP = "Добавляет число к переменной '%1'."; +Blockly.Msg.MATH_CONSTANT_HELPURL = "http://ru.wikipedia.org/wiki/Математическая_константа"; +Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Возвращает одну из распространённых констант: π (3.141...), e (2.718...), φ (1.618...), sqrt(2) (1.414...), sqrt(½) (0.707...) или ∞ (бесконечность)."; +Blockly.Msg.MATH_CONSTRAIN_HELPURL = "http://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated +Blockly.Msg.MATH_CONSTRAIN_TITLE = "ограничить %1 снизу %2 сверху %3"; +Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Ограничивает число нижней и верхней границами (включительно)."; +Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated +Blockly.Msg.MATH_IS_DIVISIBLE_BY = "делится на"; +Blockly.Msg.MATH_IS_EVEN = "чётное"; +Blockly.Msg.MATH_IS_NEGATIVE = "отрицательно"; +Blockly.Msg.MATH_IS_ODD = "нечётное"; +Blockly.Msg.MATH_IS_POSITIVE = "положительно"; +Blockly.Msg.MATH_IS_PRIME = "является простым"; +Blockly.Msg.MATH_IS_TOOLTIP = "Проверяет, является ли число чётным, нечётным, простым, целым, положительным, отрицательным или оно кратно определённому числу. Возвращает значение истина или ложь."; +Blockly.Msg.MATH_IS_WHOLE = "является целым"; +Blockly.Msg.MATH_MODULO_HELPURL = "http://ru.wikipedia.org/wiki/Деление_с_остатком"; +Blockly.Msg.MATH_MODULO_TITLE = "остаток от %1 : %2"; +Blockly.Msg.MATH_MODULO_TOOLTIP = "Возвращает остаток от деления двух чисел."; +Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated +Blockly.Msg.MATH_NUMBER_HELPURL = "http://ru.wikipedia.org/wiki/Число"; +Blockly.Msg.MATH_NUMBER_TOOLTIP = "Число."; +Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated +Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "среднее арифметическое списка"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "наибольшее в списке"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "медиана списка"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "наименьшее в списке"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "моды списка"; +Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "случайный элемент списка"; +Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "стандартное отклонение списка"; +Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "сумма списка"; +Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Возвращает среднее арифметическое списка."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Возвращает наибольшее число списка."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Возвращает медиану списка."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Возвращает наименьшее число списка."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Возвращает список наиболее часто встречающихся элементов списка."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Возвращает случайный элемент списка."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Возвращает стандартное отклонение списка."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Возвращает сумму всех чисел в списке."; +Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated +Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "http://ru.wikipedia.org/wiki/Генератор_псевдослучайных_чисел"; +Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "случайное число от 0 (включительно) до 1"; +Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Возвращает случайную дробную часть между 0.0 (включительно) и 1.0 (не включая)."; +Blockly.Msg.MATH_RANDOM_INT_HELPURL = "http://ru.wikipedia.org/wiki/Генератор_псевдослучайных_чисел"; +Blockly.Msg.MATH_RANDOM_INT_TITLE = "случайное целое число от %1 для %2"; +Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Возвращает случайное число между двумя заданными пределами (включая и их)."; +Blockly.Msg.MATH_ROUND_HELPURL = "http://ru.wikipedia.org/wiki/Округление"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "округлить"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "округлить к меньшему"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "округлить к большему"; +Blockly.Msg.MATH_ROUND_TOOLTIP = "Округление числа до большего или меньшего."; +Blockly.Msg.MATH_SINGLE_HELPURL = "http://ru.wikipedia.org/wiki/Квадратный_корень"; +Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "модуль"; +Blockly.Msg.MATH_SINGLE_OP_ROOT = "квадратный корень"; +Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Возвращает модуль числа"; +Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Возвращает е в указанной степени."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Возвращает натуральный логарифм числа."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Возвращает десятичный логарифм числа."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Возвращает противоположное число."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Возвращает 10 в указанной степени."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Возвращает квадратный корень числа."; +Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated +Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated +Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated +Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated +Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated +Blockly.Msg.MATH_TRIG_HELPURL = "http://ru.wikipedia.org/wiki/Тригонометрические_функции"; +Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated +Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated +Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Возвращает арккосинус (в градусах)."; +Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Возвращает арксинус (в градусах)."; +Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Возвращает арктангенс (в градусах)"; +Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Возвращает косинус угла в градусах."; +Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Возвращает синус угла в градусах."; +Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Возвращает тангенс угла в градусах."; +Blockly.Msg.NEW_VARIABLE = "Новая переменная…"; +Blockly.Msg.NEW_VARIABLE_TITLE = "Имя новой переменной:"; +Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated +Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "с:"; +Blockly.Msg.PROCEDURES_CALLNORETURN_CALL = ""; // untranslated +Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "http://ru.wikipedia.org/wiki/Функция_%28программирование%29"; +Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Исполняет определённую пользователем процедуру '%1'."; +Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "http://ru.wikipedia.org/wiki/Функция_%28программирование%29"; +Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Исполняет определённую пользователем функцию '%1' и использует возвращаемое значение."; +Blockly.Msg.PROCEDURES_CREATE_DO = "Создать '%1'"; +Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated +Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated +Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "выполнить что-то"; +Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "чтобы"; +Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Создаёт процедуру, не возвращающую значение."; +Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated +Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "вернуть"; +Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Создаёт процедуру, возвращающую значение."; +Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Предупреждение: эта функция имеет повторяющиеся параметры."; +Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Выделить определение функции"; +Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Если значение равно истина, возвращает второе значение."; +Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Предупреждение: Этот блок может использоваться только внутри определения функции."; +Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "имя параметра:"; +Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "параметры"; +Blockly.Msg.REMOVE_COMMENT = "Удалить комментарий"; +Blockly.Msg.RENAME_VARIABLE = "Переименовать переменную…"; +Blockly.Msg.RENAME_VARIABLE_TITLE = "Переименовать все переменные '%1' в:"; +Blockly.Msg.TEXT_APPEND_APPENDTEXT = "добавить текст"; +Blockly.Msg.TEXT_APPEND_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Text_modification"; // untranslated +Blockly.Msg.TEXT_APPEND_TO = "к"; +Blockly.Msg.TEXT_APPEND_TOOLTIP = "Добавить текст к переменной «%1»."; +Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case"; // untranslated +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "в нижний регистр"; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "к Капитализации Начальных Букв"; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "в ВЕРХНИЙ РЕГИСТР"; +Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Возвращать копию текста в другом регистре."; +Blockly.Msg.TEXT_CHARAT_FIRST = "взять первую букву"; +Blockly.Msg.TEXT_CHARAT_FROM_END = "взять букву # с конца"; +Blockly.Msg.TEXT_CHARAT_FROM_START = "взять букву #"; +Blockly.Msg.TEXT_CHARAT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Extracting_text"; // untranslated +Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "в тексте"; +Blockly.Msg.TEXT_CHARAT_LAST = "взять последнюю букву"; +Blockly.Msg.TEXT_CHARAT_RANDOM = "взять случайную букву"; +Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated +Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Возвращает букву в указанной позиции."; +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Добавить элемент к тексту."; +Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "соединить"; +Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Добавьте, удалите, переставьте фрагменты для переделки текстового блока."; +Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "по букву # с конца"; +Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "по букву #"; +Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "по последнюю букву"; +Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text"; // untranslated +Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "в тексте"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "взять подстроку с первой буквы"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "взять подстроку с буквы # с конца"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "взять подстроку с буквы #"; +Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated +Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Возвращает указанную часть текста."; +Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Finding_text"; // untranslated +Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "в тексте"; +Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "найти первое вхождение текста"; +Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "найти последнее вхождение текста"; +Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated +Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Возвращает номер позиции первого/последнего вхождения первого текста во втором. Возвращает 0, если текст не найден."; +Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text"; // untranslated +Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 пуст"; +Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Возвращает значение истина, если предоставленный текст пуст."; +Blockly.Msg.TEXT_JOIN_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Text_creation"; // untranslated +Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "создать текст из"; +Blockly.Msg.TEXT_JOIN_TOOLTIP = "Создаёт фрагмент текста, объединяя любое число элементов"; +Blockly.Msg.TEXT_LENGTH_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Text_modification"; // untranslated +Blockly.Msg.TEXT_LENGTH_TITLE = "длина %1"; +Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Возвращает число символов (включая пробелы) в заданном тексте."; +Blockly.Msg.TEXT_PRINT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Printing_text"; // untranslated +Blockly.Msg.TEXT_PRINT_TITLE = "напечатать %1"; +Blockly.Msg.TEXT_PRINT_TOOLTIP = "Печатает текст, число или другой объект."; +Blockly.Msg.TEXT_PROMPT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user"; // untranslated +Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Запросить у пользователя число."; +Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Запросить у пользователя текст."; +Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "запросить число с подсказкой"; +Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "запросить текст с подсказкой"; +Blockly.Msg.TEXT_TEXT_HELPURL = "http://ru.wikipedia.org/wiki/Строковый_тип"; +Blockly.Msg.TEXT_TEXT_TOOLTIP = "Буква, слово или строка текста."; +Blockly.Msg.TEXT_TRIM_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces"; // untranslated +Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "обрезать пробелы с двух сторон"; +Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "обрезать пробелы слева"; +Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "обрезать пробелы справа"; +Blockly.Msg.TEXT_TRIM_TOOLTIP = "Возвращает копию текста с пробелами, удалеными с одного или обоих концов."; +Blockly.Msg.VARIABLES_DEFAULT_NAME = "элемент"; +Blockly.Msg.VARIABLES_GET_CREATE_SET = "Создать 'присвоить значение %1'"; +Blockly.Msg.VARIABLES_GET_HELPURL = "http://code.google.com/p/blockly/wiki/Variables#Get"; // untranslated +Blockly.Msg.VARIABLES_GET_TAIL = ""; // untranslated +Blockly.Msg.VARIABLES_GET_TITLE = ""; // untranslated +Blockly.Msg.VARIABLES_GET_TOOLTIP = "Возвращает значение этой переменной."; +Blockly.Msg.VARIABLES_SET_CREATE_GET = "Создать 'взять %1'"; +Blockly.Msg.VARIABLES_SET_HELPURL = "http://code.google.com/p/blockly/wiki/Variables#Set"; // untranslated +Blockly.Msg.VARIABLES_SET_TAIL = "равно"; +Blockly.Msg.VARIABLES_SET_TITLE = "присвоить"; +Blockly.Msg.VARIABLES_SET_TOOLTIP = "Присваивает переменной значение параметра."; +Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; +Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; +Blockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; +Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL; +Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; +Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; +Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; \ No newline at end of file diff --git a/msg/js/uk.js b/msg/js/uk.js new file mode 100644 index 000000000..c3263df43 --- /dev/null +++ b/msg/js/uk.js @@ -0,0 +1,377 @@ +// This file was automatically generated. Do not modify. + +'use strict'; + +goog.provide('Blockly.Msg.uk'); + +goog.require('Blockly.Msg'); + +Blockly.Msg.ADD_COMMENT = "Додати коментар"; +Blockly.Msg.CHANGE_VALUE_TITLE = "Змінити значення:"; +Blockly.Msg.COLLAPSE_ALL = "Згорнути блоки"; +Blockly.Msg.COLLAPSE_BLOCK = "Згорнути блок"; +Blockly.Msg.COLOUR_BLEND_COLOUR1 = "колір 1"; +Blockly.Msg.COLOUR_BLEND_COLOUR2 = "колір 2"; +Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; +Blockly.Msg.COLOUR_BLEND_RATIO = "співвідношення"; +Blockly.Msg.COLOUR_BLEND_TITLE = "суміш"; +Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Змішує дві барви разом з даним співвідношенням (0.0 - 1.0)."; +Blockly.Msg.COLOUR_PICKER_HELPURL = "http://uk.wikipedia.org/wiki/Колір"; +Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Вибрати колір з палітри."; +Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated +Blockly.Msg.COLOUR_RANDOM_TITLE = "випадковий колір"; +Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Вибрати колір навмання."; +Blockly.Msg.COLOUR_RGB_BLUE = "синій"; +Blockly.Msg.COLOUR_RGB_GREEN = "зелений"; +Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; +Blockly.Msg.COLOUR_RGB_RED = "червоний"; +Blockly.Msg.COLOUR_RGB_TITLE = "колір з"; +Blockly.Msg.COLOUR_RGB_TOOLTIP = "Створити колір з указаного червоного, зеленого та синього. Усі значення мають бути від 0 до 100."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "перервати цикл"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "продовжити з наступної ітерації циклу"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Вирватися з циклічних оточень."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Пропустити залишок цього циклу і перейти до виконання наступної ітерації."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Попередження: цей блок може бути використаний тільки в межах циклу."; +Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#for_each for each block"; +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = "у списку"; +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = "блок тексту"; +Blockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = "для кожного елемента"; +Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Для кожного елемента в списку задайте змінну '%1' для елемента, а потім зробіть деякі заяви."; +Blockly.Msg.CONTROLS_FOR_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#count_with"; +Blockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = "від %1 до %2 через %3"; +Blockly.Msg.CONTROLS_FOR_INPUT_WITH = "рахувати з"; +Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Наявна змінна %1 приймає значення від початкового значення до кінцевого значення, враховуючи заданий інтервал, і зробіть вказані блоки."; +Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Додати умову до якщо блокувати."; +Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Додати остаточну, всеосяжну умова до блоку якщо."; +Blockly.Msg.CONTROLS_IF_HELPURL = "http://code.google.com/p/blockly/wiki/If_Then"; +Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Додати, видалити або змінити порядок розділів переналаштувати це, якщо блокується."; +Blockly.Msg.CONTROLS_IF_MSG_ELSE = "інакше"; +Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "Інакше якщо"; +Blockly.Msg.CONTROLS_IF_MSG_IF = "якщо"; +Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Якщо значення true, зробити деякі заяви."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Якщо значення істина, то виконується перший блок операторів. В іншому випадку виконується другий блок операторів."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Якщо перше значення істина, то виконується перший блок операторів. В іншому випадку, якщо друге значення істина, то виконується другий блок операторів."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Якщо перше значення істина, то виконується перший блок операторів. В іншому випадку, якщо друге значення істина, то виконується другий блок операторів. Якщо жодне із значень не є істинним, то виконується останній блок операторів."; +Blockly.Msg.CONTROLS_REPEAT_HELPURL = "http://en.Wikipedia.org/Wiki/For_loop"; +Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "зробити"; +Blockly.Msg.CONTROLS_REPEAT_TITLE = "повторити %1 разів"; +Blockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = "повторити"; +Blockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = "разів"; +Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Зробити деякі заяви кілька разів."; +Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "http://code.google.com/p/blockly/wiki/Repeat"; +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "повторювати доки"; +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "повторювати поки"; +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Поки значення false, зробити деякі заяви."; +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Поки значення true, зробити деякі заяви."; +Blockly.Msg.DELETE_BLOCK = "Видалити блок"; +Blockly.Msg.DELETE_X_BLOCKS = "Видалити %1 блоків"; +Blockly.Msg.DISABLE_BLOCK = "Вимкнути блок"; +Blockly.Msg.DUPLICATE_BLOCK = "Дублікат"; +Blockly.Msg.ENABLE_BLOCK = "Увімкнути блок"; +Blockly.Msg.EXPAND_ALL = "Розгорнути блоки"; +Blockly.Msg.EXPAND_BLOCK = "Розгорнути блок"; +Blockly.Msg.EXTERNAL_INPUTS = "Зовнішні входи"; +Blockly.Msg.HELP = "Довідка"; +Blockly.Msg.INLINE_INPUTS = "Вбудовані входи"; +Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "http://uk.wikipedia.org/wiki/Зв%27язаний_список"; +Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "створити порожній список"; +Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Повертає список, довжиною 0, що не містить записів даних"; +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "список"; +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Додати, видалити або змінити порядок розділів для переналаштування блокування списку."; +Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "створює список з"; +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Додати елемент до списку."; +Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Створює список з будь-якою кількістю елементів."; +Blockly.Msg.LISTS_GET_INDEX_FIRST = "перший"; +Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# з кінця"; +Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; +Blockly.Msg.LISTS_GET_INDEX_GET = "отримати"; +Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "отримати і видалити"; +Blockly.Msg.LISTS_GET_INDEX_LAST = "останній"; +Blockly.Msg.LISTS_GET_INDEX_RANDOM = "випадковий"; +Blockly.Msg.LISTS_GET_INDEX_REMOVE = "вилучити"; +Blockly.Msg.LISTS_GET_INDEX_TAIL = "-ий."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Повертає перший елемент у списку."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = "Повертає елемент у заданій позиції у списку. #1 - це останній пункт."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = "Повертає елемент у заданій позицію у списку. #1 - це перший пункт."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Повертає останній елемент списку."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Повертає випадковий елемент у списку."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Видаляє і повертає перший елемент у списку."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = "Видаляє і повертає елемент у заданій позиції у списку. #1 - це останній пункт."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = "Видаляє і повертає елемент у заданій позиції у списку. #1 - це перший пункт."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Видаляє і повертає останній елемент списку."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Видаляє і повертає випадковий елемент у список."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Видаляє перший елемент у списку."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = "Вилучає елемент у вказаній позиції списку. #1 - це останній пункт."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = "Вилучає елемент у вказаній позиції списку. #1 - це перший пункт."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Видаляє останній елемент списку."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Видаляє випадковий елемент у списку."; +Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "до # з кінця"; +Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "до #"; +Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "до останнього"; +Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist"; +Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "отримати вкладений список з першого"; +Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "отримати вкладений список від # з кінця"; +Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "отримати вкладений список з #"; +Blockly.Msg.LISTS_GET_SUBLIST_TAIL = "символу."; +Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Створює копію вказаної частини списку."; +Blockly.Msg.LISTS_INDEX_OF_FIRST = "знайти перше входження елемента"; +Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List"; +Blockly.Msg.LISTS_INDEX_OF_LAST = "знайти останнє входження елемента"; +Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Повертає індекс першого/останнього входження першого елементу у списку. Повертає 0, якщо текст не знайдений."; +Blockly.Msg.LISTS_INLIST = "у списку"; +Blockly.Msg.LISTS_IS_EMPTY_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#is_empty"; +Blockly.Msg.LISTS_IS_EMPTY_TITLE = "%1 є порожнім"; +Blockly.Msg.LISTS_LENGTH_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#length_of"; +Blockly.Msg.LISTS_LENGTH_TITLE = "довжина %1"; +Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Повертає довжину списку."; +Blockly.Msg.LISTS_REPEAT_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#create_list_with"; +Blockly.Msg.LISTS_REPEAT_TITLE = "створити список з елемента %1 повтореного %2 разів"; +Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Створює список, що складається з заданого значення повтореного певну кількість разів."; +Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#in_list_..._set"; +Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "як"; +Blockly.Msg.LISTS_SET_INDEX_INSERT = "вставити в"; +Blockly.Msg.LISTS_SET_INDEX_SET = "встановити"; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Вставляє елемент на початок списку."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = "Вставляє елемент у вказану позицію списку. #1 - це останній пункт."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = "Вставка елемента у вказану позицію списку. #1 є першим пунктом."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Додає елемент до кінця списку."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Випадковим чином вставляє елемент у списку."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Задає перший елемент у списку."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = "Задає елемент у вказаній позиції списку. #1 - це останній пункт."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = "Задає елемент у вказаній позиції списку. #1 - це перший пункт."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Задає останній елемент списку."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Задає випадковий елемент у списку."; +Blockly.Msg.LISTS_TOOLTIP = "Повертає істина, якщо список порожній."; +Blockly.Msg.LOGIC_BOOLEAN_FALSE = "хибність"; +Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "http://code.google.com/p/blockly/wiki/True_False"; +Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Повертає значення ІСТИНА або ХИБНІСТЬ."; +Blockly.Msg.LOGIC_BOOLEAN_TRUE = "істина"; +Blockly.Msg.LOGIC_COMPARE_HELPURL = "http://uk.wikipedia.org/wiki/Нерівність"; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Повертає true, якщо обидва входи рівні один одному."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Повертає true, якщо перше вхідне значення більше, ніж другий вхід."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Повертає true, якщо перше вхідне значення більше або дорівнює другому входу."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Повертає true, якщо перше вхідне значення менше, ніж другий вхід."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Повертає true, якщо перше вхідне значення менше або дорівнює другому входу."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Повертає true, якщо обидва входи не дорівнюють один одному."; +Blockly.Msg.LOGIC_NEGATE_HELPURL = "http://code.google.com/p/blockly/wiki/Not"; +Blockly.Msg.LOGIC_NEGATE_TITLE = "не %1"; +Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Повертає істина, якщо вхідне значення хибність. Повертає хибність, якщо вхідна значення істина."; +Blockly.Msg.LOGIC_NULL = "нічого"; +Blockly.Msg.LOGIC_NULL_HELPURL = "http://en.wikipedia.org/wiki/Nullable_type"; +Blockly.Msg.LOGIC_NULL_TOOLTIP = "Повертає null."; +Blockly.Msg.LOGIC_OPERATION_AND = "та"; +Blockly.Msg.LOGIC_OPERATION_HELPURL = "http://code.google.com/p/blockly/wiki/And_Or"; +Blockly.Msg.LOGIC_OPERATION_OR = "або"; +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Повертає true, якщо обидва входи істинні."; +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Повертає true, якщо принаймні один з входів true."; +Blockly.Msg.LOGIC_TERNARY_CONDITION = "тест"; +Blockly.Msg.LOGIC_TERNARY_HELPURL = "http://en.wikipedia.org/wiki/%3F:"; +Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "Якщо хибність"; +Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "якщо істина"; +Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Перевірте умову в 'test'. Якщо умова істинна, то повертає значення типу 'якщо істина'; в іншому випадку повертає значення 'якщо хибність'."; +Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated +Blockly.Msg.MATH_ARITHMETIC_HELPURL = "http://uk.wikipedia.org/wiki/Арифметика"; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Повертає суму двох чисел."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Повертає частку двох чисел."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Повертає різницю двох чисел."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Повертає добуток двох чисел."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Повертає перше число, піднесене до степеня другого числа."; +Blockly.Msg.MATH_CHANGE_HELPURL = "http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; +Blockly.Msg.MATH_CHANGE_INPUT_BY = "від"; +Blockly.Msg.MATH_CHANGE_TITLE_CHANGE = "змінити"; +Blockly.Msg.MATH_CHANGE_TOOLTIP = "Додати число змінній '%1'."; +Blockly.Msg.MATH_CONSTANT_HELPURL = "http://uk.wikipedia.org/wiki/Математична_константа"; +Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Повертає одну з поширених констант: π (3.141...), e (2.718...), φ (1,618...), sqrt(2) (1.414...), sqrt(½) (0.707...) або ∞ (безмежність)."; +Blockly.Msg.MATH_CONSTRAIN_HELPURL = "http://en.wikipedia.org/wiki/Clamping_%28graphics%29"; +Blockly.Msg.MATH_CONSTRAIN_TITLE = "обмежити %1 від %2 до %3"; +Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Обмежує число вказаними межами (включно)."; +Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated +Blockly.Msg.MATH_IS_DIVISIBLE_BY = "ділиться на"; +Blockly.Msg.MATH_IS_EVEN = "парне"; +Blockly.Msg.MATH_IS_NEGATIVE = "від'ємне"; +Blockly.Msg.MATH_IS_ODD = "непарне"; +Blockly.Msg.MATH_IS_POSITIVE = "додатне"; +Blockly.Msg.MATH_IS_PRIME = "просте"; +Blockly.Msg.MATH_IS_TOOLTIP = "Перевіряє, чи число парне, непарне, просте, ціле, додатне, від'ємне або чи воно ділиться на певне число без остачі. Повертає істина або хибність."; +Blockly.Msg.MATH_IS_WHOLE = "ціле"; +Blockly.Msg.MATH_MODULO_HELPURL = "http://uk.wikipedia.org/wiki/Ділення_з_остачею"; +Blockly.Msg.MATH_MODULO_TITLE = "остача від %1 ÷ %2"; +Blockly.Msg.MATH_MODULO_TOOLTIP = "Повертає остачу від ділення двох чисел."; +Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated +Blockly.Msg.MATH_NUMBER_HELPURL = "http://uk.wikipedia.org/wiki/Число"; +Blockly.Msg.MATH_NUMBER_TOOLTIP = "Число."; +Blockly.Msg.MATH_ONLIST_HELPURL = "http://www.mapleprimes.com/questions/100441-Applying-Function-To-List-Of-Numbers"; +Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "середнє списку"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "максимум списку"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "медіана списку"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "мінімум списку"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "моди списку"; +Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "випадковий елемент списку"; +Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "стандартне відхилення списку"; +Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "сума списку"; +Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Повертає середнє (арифметичне) числових значень у списку."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Повертає найбільше число у списку."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Повертає медіану списку."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Повертає найменше число у списку."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Повертає перелік найпоширеніших елементів у списку."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Повертає випадковий елемент зі списку."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Повертає стандартне відхилення списку."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Повертає суму всіх чисел у списку."; +Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated +Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "http://uk.wikipedia.org/wiki/Генерація_випадкових_чисел"; +Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "випадковий дріб"; +Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Повертає випадковий дріб від 0,0 (включно) та 1.0 (не включно)."; +Blockly.Msg.MATH_RANDOM_INT_HELPURL = "http://uk.wikipedia.org/wiki/Генерація_випадкових_чисел"; +Blockly.Msg.MATH_RANDOM_INT_TITLE = "випадкове ціле число від %1 до %2"; +Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Повертає випадкове ціле число між двома заданими межами включно."; +Blockly.Msg.MATH_ROUND_HELPURL = "http://en.wikipedia.org/wiki/Rounding"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "округлити"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "округлити у меншу сторону"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "округлити у більшу сторону"; +Blockly.Msg.MATH_ROUND_TOOLTIP = "Округлення числа у більшу або меншу сторону."; +Blockly.Msg.MATH_SINGLE_HELPURL = "http://uk.wikipedia.org/wiki/Квадратний_корінь"; +Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "модуль"; +Blockly.Msg.MATH_SINGLE_OP_ROOT = "квадратний корінь"; +Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Повертає модуль числа."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Повертає e у степені."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Повертає натуральний логарифм числа."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Повертає десятковий логарифм числа."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Повертає протилежне число."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Повертає 10 у степені."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Повертає квадратний корінь числа."; +Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated +Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated +Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated +Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated +Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated +Blockly.Msg.MATH_TRIG_HELPURL = "http://uk.wikipedia.org/wiki/Тригонометричні_функції"; +Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated +Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated +Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Повертає арккосинус числа."; +Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Повертає арксинус числа."; +Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Повертає арктангенс числа."; +Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Повертає косинус кута у градусах (не у радіанах)."; +Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Повертає синус кута у градусах (не у радіанах)."; +Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Повертає тангенс кута у градусах (не у радіанах)."; +Blockly.Msg.NEW_VARIABLE = "Нова змінна..."; +Blockly.Msg.NEW_VARIABLE_TITLE = "Нове ім'я змінної:"; +Blockly.Msg.ORDINAL_NUMBER_SUFFIX = "-ий."; +Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "з:"; +Blockly.Msg.PROCEDURES_CALLNORETURN_CALL = "блок тексту"; +Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; +Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Запустити користувацьку функцію \"%1\"."; +Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "http://uk.wikipedia.org/wiki/Підпрограма"; +Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Запустити користувацьку функцію \"%1\" і використовувати її вивід."; +Blockly.Msg.PROCEDURES_CREATE_DO = "Створити \"%1\""; +Blockly.Msg.PROCEDURES_DEFNORETURN_DO = "блок тексту"; +Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "http://uk.wikipedia.org/wiki/Підпрограма"; +Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "щось зробити"; +Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "до"; +Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Створює функцію без виводу."; +Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "http://uk.wikipedia.org/wiki/Підпрограма"; +Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "повернути"; +Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Створює функцію з виводу."; +Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Увага: ця функція має дубльовані параметри."; +Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Визначення функції підсвітки"; +Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Якщо значення true, то повернути друге значення."; +Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Попередження: Цей блок може використовуватися лише в межах визначення функції."; +Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "ім'я входу:"; +Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "вхід"; +Blockly.Msg.REMOVE_COMMENT = "Видалити коментар"; +Blockly.Msg.RENAME_VARIABLE = "Перейменувати змінну..."; +Blockly.Msg.RENAME_VARIABLE_TITLE = "Перейменувати усі змінні \"%1\" до:"; +Blockly.Msg.TEXT_APPEND_APPENDTEXT = "додати текст"; +Blockly.Msg.TEXT_APPEND_HELPURL = "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html"; +Blockly.Msg.TEXT_APPEND_TO = "до"; +Blockly.Msg.TEXT_APPEND_TOOLTIP = "Додати який-небудь текст змінній '%1'."; +Blockly.Msg.TEXT_CHANGECASE_HELPURL = "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html"; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "до нижнього регістру"; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "Великі Перші Букви"; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "до ВЕРХНЬОГО регістру"; +Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Повернути копію тексту в іншому випадку."; +Blockly.Msg.TEXT_CHARAT_FIRST = "отримати перший символ"; +Blockly.Msg.TEXT_CHARAT_FROM_END = "отримати символ # з кінця"; +Blockly.Msg.TEXT_CHARAT_FROM_START = "отримати символ"; +Blockly.Msg.TEXT_CHARAT_HELPURL = "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm"; +Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "у тексті"; +Blockly.Msg.TEXT_CHARAT_LAST = "отримати останній символ"; +Blockly.Msg.TEXT_CHARAT_RANDOM = "отримати випадковий символ"; +Blockly.Msg.TEXT_CHARAT_TAIL = "-ий."; +Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Повертає символ у зазначеній позиції."; +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Додати елемент до тексту."; +Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "приєднати"; +Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Додати, видалити або змінити порядок розділів для переналаштування блокування тексту."; +Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "до символу з кінця"; +Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "до символу #"; +Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "до останнього символу"; +Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text"; +Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "у тексті"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "отримати підрядок від першого символу"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "отримати підрядок від символу # з кінця"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "отримати підрядок від символу"; +Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = "-ого."; +Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Повертає заданий фрагмент тексту."; +Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Finding_text"; +Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "у тексті"; +Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "знайти перше входження тексту"; +Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "знайти останнє входження тексту"; +Blockly.Msg.TEXT_INDEXOF_TAIL = "."; +Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Повертає індекс першого/останнього входження першого тексту у другому. Повертає 0, якщо текст не знайдений."; +Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text"; +Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 є порожнім"; +Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Повертає true, якщо вказаний текст порожній."; +Blockly.Msg.TEXT_JOIN_HELPURL = "http://www.chemie.fu-berlin.de/chemnet/use/info/make/make_8.html"; +Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "створити текст з"; +Blockly.Msg.TEXT_JOIN_TOOLTIP = "Створити фрагмент тексту шляхом приєднання будь-якого числа елементів."; +Blockly.Msg.TEXT_LENGTH_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Text_modification"; +Blockly.Msg.TEXT_LENGTH_TITLE = "довжина %1"; +Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Повертає число символів (включаючи пробіли) у даному тексті."; +Blockly.Msg.TEXT_PRINT_HELPURL = "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html"; +Blockly.Msg.TEXT_PRINT_TITLE = "друк %1"; +Blockly.Msg.TEXT_PRINT_TOOLTIP = "Надрукувати заданий текст, числа або інші символи."; +Blockly.Msg.TEXT_PROMPT_HELPURL = "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode92.html"; +Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Запитувати у користувача число."; +Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Запитувати у користувача деякий текст."; +Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "запит на число з повідомлення"; +Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "запит на текст з повідомлення"; +Blockly.Msg.TEXT_TEXT_HELPURL = "http://uk.wikipedia.org/wiki/Рядок_(програмування)"; +Blockly.Msg.TEXT_TEXT_TOOLTIP = "Символ, слово або рядок тексту."; +Blockly.Msg.TEXT_TRIM_HELPURL = "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html"; +Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "викидати крайні пробіли з обох сторін"; +Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "вилучати пробіли з лівого боку"; +Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "вилучати пробіли з правого боку"; +Blockly.Msg.TEXT_TRIM_TOOLTIP = "Повертає копію тексту з пробілами вилученими від одного або обох кінців."; +Blockly.Msg.VARIABLES_DEFAULT_NAME = "елемент"; +Blockly.Msg.VARIABLES_GET_CREATE_SET = "Створити 'set %1'"; +Blockly.Msg.VARIABLES_GET_HELPURL = "http://code.google.com/p/blockly/wiki/Variables#Get"; +Blockly.Msg.VARIABLES_GET_TAIL = "значення"; +Blockly.Msg.VARIABLES_GET_TITLE = "значення"; +Blockly.Msg.VARIABLES_GET_TOOLTIP = "Повертає значення цієї змінної."; +Blockly.Msg.VARIABLES_SET_CREATE_GET = "Створити 'get %1'"; +Blockly.Msg.VARIABLES_SET_HELPURL = "http://code.google.com/p/blockly/wiki/Variables#Set"; +Blockly.Msg.VARIABLES_SET_TAIL = "до"; +Blockly.Msg.VARIABLES_SET_TITLE = "встановити"; +Blockly.Msg.VARIABLES_SET_TOOLTIP = "Задає цю змінну рівною вводу."; +Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; +Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; +Blockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; +Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL; +Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; +Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; +Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; \ No newline at end of file diff --git a/msg/js/vi.js b/msg/js/vi.js new file mode 100644 index 000000000..9db80dc99 --- /dev/null +++ b/msg/js/vi.js @@ -0,0 +1,377 @@ +// This file was automatically generated. Do not modify. + +'use strict'; + +goog.provide('Blockly.Msg.vi'); + +goog.require('Blockly.Msg'); + +Blockly.Msg.ADD_COMMENT = "Thêm Chú Giải"; +Blockly.Msg.CHANGE_VALUE_TITLE = "Thay giá trị thành:"; +Blockly.Msg.COLLAPSE_ALL = "Thu Nhỏ Mọi Mảnh"; +Blockly.Msg.COLLAPSE_BLOCK = "Thu Nhỏ Mảnh"; +Blockly.Msg.COLOUR_BLEND_COLOUR1 = "màu 1"; +Blockly.Msg.COLOUR_BLEND_COLOUR2 = "màu 2"; +Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated +Blockly.Msg.COLOUR_BLEND_RATIO = "tỉ lệ"; +Blockly.Msg.COLOUR_BLEND_TITLE = "pha"; +Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Pha hai màu với nhau theo tỉ lệ (0 - 100)."; +Blockly.Msg.COLOUR_PICKER_HELPURL = "http://vi.wikipedia.org/wiki/M%C3%A0u_s%E1%BA%AFc"; +Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Chọn một màu từ bảng màu."; +Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated +Blockly.Msg.COLOUR_RANDOM_TITLE = "màu bất kỳ"; +Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "chọn một màu bất kỳ."; +Blockly.Msg.COLOUR_RGB_BLUE = "màu xanh dương"; +Blockly.Msg.COLOUR_RGB_GREEN = "màu xanh lá cây"; +Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated +Blockly.Msg.COLOUR_RGB_RED = "màu đỏ"; +Blockly.Msg.COLOUR_RGB_TITLE = "Tạo màu từ"; +Blockly.Msg.COLOUR_RGB_TOOLTIP = "Tạo màu từ ba màu: đỏ, xanh lá cây, xanh dương với số lượng cụ thể. Mỗi số phải có giá trị từ 0 đến 100."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks"; // untranslated +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "thoát"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "sang lần lặp tiếp theo"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Thoát khỏi vòng lặp hiện tại."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Bỏ qua phần còn lại trong vòng lặp này, và sang lần lặp tiếp theo."; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Chú ý: Mảnh này chỉ có thế dùng trong các vòng lặp."; +Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#for_each for each block"; // untranslated +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = "trong danh sách"; +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = ""; +Blockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = "với mỗi thành phần"; +Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Trong một danh sách, lấy từng thành phần, gán vào biến \"%1\", rồi thực hiện một số lệnh."; +Blockly.Msg.CONTROLS_FOR_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#count_with"; // untranslated +Blockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = "từ %1 đến %2 mỗi lần thêm %3"; +Blockly.Msg.CONTROLS_FOR_INPUT_WITH = "đếm theo"; +Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Đếm từ số đầu đến số cuối. Khi đến mỗi số, gán số vào biến \"%1\" rồi thực hiện các lệnh."; +Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Thêm một điều kiện vào mảnh nếu."; +Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Cuối cùng, khi không điều kiện nào đúng."; +Blockly.Msg.CONTROLS_IF_HELPURL = "http://code.google.com/p/blockly/wiki/If_Then"; // untranslated +Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Thêm, bỏ, hoặc đổi thứ tự các mảnh con để tạo cấu trúc mới cho mảnh nếu."; +Blockly.Msg.CONTROLS_IF_MSG_ELSE = "nếu không"; +Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "nếu không nếu"; +Blockly.Msg.CONTROLS_IF_MSG_IF = "nếu"; +Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Nếu điều kiện đúng, thực hiện các lệnh."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Nếu điều kiện đúng, thực hiện các lệnh đầu. Nếu sai, thực hiện các lệnh sau."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Nếu điều kiện đúng, thực hiện các lệnh đầu. Nếu không, nếu điều kiện thứ hai đúng, thực hiện các lệnh thứ hai."; +Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Nếu điều kiện đúng, thực hiện các lệnh đầu. Nếu không, nếu điều kiện thứ hai đúng, thực hiện các lệnh thứ hai. Nếu không điều kiện nào đúng, thực hiện các lệnh cuối cùng."; +Blockly.Msg.CONTROLS_REPEAT_HELPURL = "http://en.wikipedia.org/wiki/For_loop"; +Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "thực hiện"; +Blockly.Msg.CONTROLS_REPEAT_TITLE = "lặp lại %1 lần"; +Blockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = "lặp lại"; +Blockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = "lần"; +Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Thực hiện các lệnh vài lần."; +Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "http://code.google.com/p/blockly/wiki/Repeat"; // untranslated +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "lặp lại cho đến khi"; +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "lặp lại trong khi"; +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Miễn là điều kiện còn sai, thì thực hiện các lệnh. Khi điều kiện đúng thì ngưng."; +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Miễn là điều kiện còn đúng, thì thực hiện các lệnh."; +Blockly.Msg.DELETE_BLOCK = "Xóa Mảnh Này"; +Blockly.Msg.DELETE_X_BLOCKS = "Xóa %1 Mảnh"; +Blockly.Msg.DISABLE_BLOCK = "Ngưng Tác Dụng"; +Blockly.Msg.DUPLICATE_BLOCK = "Tạo Bản Sao"; +Blockly.Msg.ENABLE_BLOCK = "Phục Hồi Tác Dụng"; +Blockly.Msg.EXPAND_ALL = "Mở Lớn Mọi Mảnh"; +Blockly.Msg.EXPAND_BLOCK = "Mở Lớn Mảnh"; +Blockly.Msg.EXTERNAL_INPUTS = "Chỗ Gắn Bên Ngoài"; +Blockly.Msg.HELP = "Trợ Giúp"; +Blockly.Msg.INLINE_INPUTS = "Chỗ Gắn Cùng Dòng"; +Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "http://en.wikipedia.org/wiki/Linked_list#Empty_lists"; // untranslated +Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "tạo danh sách trống"; +Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Hoàn trả một danh sách, với độ dài 0, không có thành tố nào cả"; +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "danh sách"; +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Thêm, bỏ, hoặc sắp xếp lại các thành phần để tạo dựng mảnh danh sách này."; +Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "tạo danh sách gồm"; +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Thêm vật vào danh sách."; +Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Tạo một danh sách bao gồm nhiều vậts, với một số lượng bất kỳ."; +Blockly.Msg.LISTS_GET_INDEX_FIRST = "đầu tiên"; +Blockly.Msg.LISTS_GET_INDEX_FROM_END = "(đếm từ cuối) thứ"; +Blockly.Msg.LISTS_GET_INDEX_FROM_START = "thứ"; +Blockly.Msg.LISTS_GET_INDEX_GET = "lấy thành tố"; +Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "lấy và xóa thành tố"; +Blockly.Msg.LISTS_GET_INDEX_LAST = "cuối cùng"; +Blockly.Msg.LISTS_GET_INDEX_RANDOM = "bất kỳ"; +Blockly.Msg.LISTS_GET_INDEX_REMOVE = "xóa thành tố"; +Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Hoàn trả thành tố đầu tiên trong danh sách."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = "Hoàn trả thành tố trong danh sách ở vị trí ấn định. Số 1 là thành tố cuối cùng."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = "Hoàn trả thành tố trong danh sách ở vị trí ấn định. Số 1 là thành tố đầu tiên."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Hoàn trả thành tố cuối cùng trong danh sách."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Hoàn trả một thành tố bất kỳ trong danh sách."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Hoàn trả và xóa thành tố đầu tiên trong danh sách."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = "Hoàn trả và xóa thành tố trong danh sách ở vị trí ấn định. Số 1 là thành tố cuối cùng."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = "Hoàn trả và xóa thành tố trong danh sách ở vị trí ấn định. Số 1 là thành tố đầu tiên."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Hoàn trả và xóa thành tố cuối cùng trong danh sách."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Hoàn trả và xóa mộtthành tố bất kỳ trong danh sách."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Xóa thành tố đầu tiên trong danh sách."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = "Xóa thành tố trong danh sách ở vị trí ấn định. Số 1 là thành tố cuối cùng."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = "Xóa thành tố trong danh sách ở vị trí ấn định. Số 1 là thành tố đầu tiên."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Xóa thành tố cuối cùng trong danh sách."; +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Xóa thành tố bất kỳ trong danh sách."; +Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "đến (đếm từ cuối) thứ"; +Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "đến thứ"; +Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "đến cuối cùng"; +Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist"; // untranslated +Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "lấy một danh sách con từ đầu tiên"; +Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "lấy một danh sách con từ (đếm từ cuối) thứ"; +Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "lấy một danh sách con từ thứ"; +Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated +Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Lấy một mảng của danh sách này để tạo danh sách con."; +Blockly.Msg.LISTS_INDEX_OF_FIRST = "tìm sự có mặt đầu tiên của vật"; +Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List"; // untranslated +Blockly.Msg.LISTS_INDEX_OF_LAST = "tìm sự có mặt cuối cùng của vật"; +Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Hoàn trả vị trí xuất hiện đầu/cuối của vật trong danh sách. Nếu không tìm thấy thì hoàn trả số 0."; +Blockly.Msg.LISTS_INLIST = "trong dánh sách"; +Blockly.Msg.LISTS_IS_EMPTY_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#is_empty"; // untranslated +Blockly.Msg.LISTS_IS_EMPTY_TITLE = "%1 trống rỗng"; +Blockly.Msg.LISTS_LENGTH_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#length_of"; // untranslated +Blockly.Msg.LISTS_LENGTH_TITLE = "độ dài của %1"; +Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Hoàn trả độ dài của một danh sách."; +Blockly.Msg.LISTS_REPEAT_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#create_list_with"; // untranslated +Blockly.Msg.LISTS_REPEAT_TITLE = "tạo danh sách gồm một vật %1 lặp lại %2 lần"; +Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Tạo danh sách gồm một số lượng vật nhất định với mỗi vật đều giống nhau."; +Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#in_list_..._set"; // untranslated +Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "giá trị"; +Blockly.Msg.LISTS_SET_INDEX_INSERT = "gắn chèn vào vị trí"; +Blockly.Msg.LISTS_SET_INDEX_SET = "đặt thành tố"; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Gắn chèn vật vào đầu danh sách."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = "Gắn chèn vật vào danh sách theo vị trí ấn định từ phía cuối. #1 là thành tố cuối cùng."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = "Gắn chèn vật vào danh sách theo vị trí ấn định. #1 là thành tố đầu tiên."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Gắn thêm vật vào cuối danh sách."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Gắn chèn vật vào danh sách ở vị trí ngẫu nhiên."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Đặt giá trị của thành tố đầu tiên trong danh sách."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = "Đặt giá trị của thành tố trong một danh sách ở vị trí ấn định từ phía cuối. #1 là thành tố cuối cùng."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = "Đặt giá trị của thành tố ở vị trí ấn định trong một danh sách. #1 là thành tố đầu tiên."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Đặt giá trị của thành tố cuối cùng trong danh sách."; +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Đặt giá trị của thành tố ngẫu nhiên trong danh sách."; +Blockly.Msg.LISTS_TOOLTIP = "Hoàn trả “đúng\" nếu danh sách không có thành tử nào."; +Blockly.Msg.LOGIC_BOOLEAN_FALSE = "sai"; +Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "http://code.google.com/p/blockly/wiki/True_False"; // untranslated +Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Hoàn trả \"đúng\" hoặc \"sai\"."; +Blockly.Msg.LOGIC_BOOLEAN_TRUE = "đúng"; +Blockly.Msg.LOGIC_COMPARE_HELPURL = "http://vi.wikipedia.org/wiki/B%E1%BA%A5t_%C4%91%E1%BA%B3ng_th%E1%BB%A9c"; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Hoàn trả giá trị \"đúng\" (true) nếu giá trị hai đầu vào bằng nhau."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Hoàn trả giá trị \"đúng\" (true) nếu đầu vào thứ nhất lớn hơn đầu vào thứ hai."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Hoàn trả giá trị \"đúng\" (true) nếu đầu vào thứ nhất lớn hơn hoặc bằng đầu vào thứ hai."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Hoàn trả giá trị \"đúng\" (true) nếu đầu vào thứ nhất nhỏ hơn đầu vào thứ hai."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Hoàn trả giá trị \"đúng\" (true) nếu đầu vào thứ nhất nhỏ hơn hoặc bằng đầu vào thứ hai."; +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Hoàn trả giá trị \"đúng\" (true) nếu giá trị hai đầu vào không bằng nhau."; +Blockly.Msg.LOGIC_NEGATE_HELPURL = "http://code.google.com/p/blockly/wiki/Not"; // untranslated +Blockly.Msg.LOGIC_NEGATE_TITLE = "không %1"; +Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Hoàn trả \"đúng\" (true) nếu đầu vào sai. Hoàn trả \"sai\" (false) nếu đầu vào đúng."; +Blockly.Msg.LOGIC_NULL = "trống không"; +Blockly.Msg.LOGIC_NULL_HELPURL = "http://en.wikipedia.org/wiki/Nullable_type"; // untranslated +Blockly.Msg.LOGIC_NULL_TOOLTIP = "Hoàn trả trống không."; +Blockly.Msg.LOGIC_OPERATION_AND = "và"; +Blockly.Msg.LOGIC_OPERATION_HELPURL = "http://code.google.com/p/blockly/wiki/And_Or"; // untranslated +Blockly.Msg.LOGIC_OPERATION_OR = "hoặc"; +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Hoàn trả \"đúng\" (true) nếu cả hai đầu vào đều đúng."; +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Hoàn trả \"đúng\" (true) nếu ít nhất một trong hai đầu vào đúng."; +Blockly.Msg.LOGIC_TERNARY_CONDITION = "kiểm tra"; +Blockly.Msg.LOGIC_TERNARY_HELPURL = "http://en.wikipedia.org/wiki/%3F:"; // untranslated +Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "nếu sai"; +Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "nếu đúng"; +Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Kiểm tra điều kiện. Nếu điều kiện đúng, hoàn trả giá trị từ mệnh đề \"nếu đúng\" nếu không đúng, hoàn trả giá trị từ mệnh đề \"nếu sai\"."; +Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated +Blockly.Msg.MATH_ARITHMETIC_HELPURL = "http://vi.wikipedia.org/wiki/S%E1%BB%91_h%E1%BB%8Dc"; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Hoàn trả tổng của hai con số."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Hoàn trả thương của hai con số."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Hoàn trả hiệu của hai con số."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Hoàn trả tích của hai con số."; +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Hoàn trả số lũy thừa với số thứ nhất là cơ số và số thứ hai là số mũ."; +Blockly.Msg.MATH_CHANGE_HELPURL = "http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; // untranslated +Blockly.Msg.MATH_CHANGE_INPUT_BY = "giá trị"; +Blockly.Msg.MATH_CHANGE_TITLE_CHANGE = "cộng vào"; +Blockly.Msg.MATH_CHANGE_TOOLTIP = "Cộng số đầu vào vào biến \"%1\"."; +Blockly.Msg.MATH_CONSTANT_HELPURL = "http://en.wikipedia.org/wiki/Mathematical_constant"; +Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Hoàn trả các đẳng số thường gặp: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (vô cực)."; +Blockly.Msg.MATH_CONSTRAIN_HELPURL = "http://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated +Blockly.Msg.MATH_CONSTRAIN_TITLE = "giới hạn %1 không dưới %2 không hơn %3"; +Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Giới hạn số đầu vào để không dưới số thứ nhất và không hơn số thứ hai."; +Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated +Blockly.Msg.MATH_IS_DIVISIBLE_BY = "chia hết cho"; +Blockly.Msg.MATH_IS_EVEN = "chẵn"; +Blockly.Msg.MATH_IS_NEGATIVE = "là số âm"; +Blockly.Msg.MATH_IS_ODD = "lẻ"; +Blockly.Msg.MATH_IS_POSITIVE = "là số dương"; +Blockly.Msg.MATH_IS_PRIME = "là số nguyên tố"; +Blockly.Msg.MATH_IS_TOOLTIP = "Kiểm tra con số xem nó có phải là số chẵn, lẻ, nguyên tố, nguyên, dương, âm, hay xem nó có chia hết cho số đầu vào hay không. Hoàn trả đúng hay sai."; +Blockly.Msg.MATH_IS_WHOLE = "là số nguyên"; +Blockly.Msg.MATH_MODULO_HELPURL = "http://en.wikipedia.org/wiki/Modulo_operation"; +Blockly.Msg.MATH_MODULO_TITLE = "số dư của %1 ÷ %2"; +Blockly.Msg.MATH_MODULO_TOOLTIP = "Chia số thứ nhất cho số thứ hai rồi hoàn trả số dư từ."; +Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated +Blockly.Msg.MATH_NUMBER_HELPURL = "http://vi.wikipedia.org/wiki/S%E1%BB%91"; +Blockly.Msg.MATH_NUMBER_TOOLTIP = "Một con số."; +Blockly.Msg.MATH_ONLIST_HELPURL = ""; +Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "giá trị trung bình của một danh sách"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "số lớn nhât của một danh sách"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "số trung vị của một danh sách"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "số nhỏ nhất của một danh sách"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "các mode của một danh sách"; +Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "một số bất kỳ của một danh sách"; +Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "độ lệch chuẩn của một danh sách"; +Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "tổng của một danh sách"; +Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Hoàn trả giá trị trung bình từ của danh sách số."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Hoàn trả số lớn nhất trong tất cả các số trong danh sách."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Hoàn trả số trung vị của danh sách số."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Hoàn trả số nhỏ nhất trong tất cả các số trong danh sách."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Hoàn trả các số có mặt nhiều nhất trong danh sách."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Hoàn trả một số bất kỳ từ các số trong danh sách."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Hoàn trả độ lệch chuẩn của danh sách số."; +Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Hoàn trả tổng số của tất cả các số trong danh sách."; +Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated +Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "http://en.wikipedia.org/wiki/Random_number_generation"; +Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "phân số bất kỳ"; +Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Hoàn trả một phân số bất kỳ không nhỏ hơn 0.0 và không lớn hơn 1.0."; +Blockly.Msg.MATH_RANDOM_INT_HELPURL = "http://en.wikipedia.org/wiki/Random_number_generation"; +Blockly.Msg.MATH_RANDOM_INT_TITLE = "Một số nguyên bất kỳ từ %1 đến %2"; +Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Hoàn trả một số nguyên bất kỳ lớn hơn hoặc bằng số đầu và nhỏ hơn hoặc bằng số sau."; +Blockly.Msg.MATH_ROUND_HELPURL = "http://en.wikipedia.org/wiki/Rounding"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "làm tròn"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "làm tròn xuống"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "làm tròn lên"; +Blockly.Msg.MATH_ROUND_TOOLTIP = "Làm tròn lên hoặc tròn xuống số đầu vào."; +Blockly.Msg.MATH_SINGLE_HELPURL = "http://vi.wikipedia.org/wiki/C%C4%83n_b%E1%BA%ADc_hai"; +Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "giá trị tuyệt đối"; +Blockly.Msg.MATH_SINGLE_OP_ROOT = "căn bật hai"; +Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Hoàn trả giá trị tuyệt đối của số đầu vào."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Hoàn trả lũy thừa của số e với số mũ đầu vào."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Hoàn trả lôgarit tự nhiên của số đầu vào."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Hoàn trả lôgarit cơ số 10 của số đầu vào."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Đổi dấu của số đầu vào: âm thành dương và dương thành âm, và hoàn trả số mới."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Hoàn trả lũy thừa của số 10 với số mũ đầu vào."; +Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Hoàn trả căn bật hai của số đầu vào."; +Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated +Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated +Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated +Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated +Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated +Blockly.Msg.MATH_TRIG_HELPURL = "http://vi.wikipedia.org/wiki/H%C3%A0m_l%C6%B0%E1%BB%A3ng_gi%C3%A1c"; +Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated +Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated +Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Hoàn trả Arccos của một góc (theo độ)."; +Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Hoàn trả Arcsin của một góc (theo độ)."; +Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Hoàn trả Arctang của một góc (theo độ)."; +Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Hoàn trả Cos của một góc (theo độ)."; +Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Hoàn trả Sin của một góc (theo độ)."; +Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Hoàn trả Tang của một góc (theo độ)."; +Blockly.Msg.NEW_VARIABLE = "Biến mới..."; +Blockly.Msg.NEW_VARIABLE_TITLE = "Tên của biến mới:"; +Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated +Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "với:"; +Blockly.Msg.PROCEDURES_CALLNORETURN_CALL = "thực hiện"; +Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "http://en.wikipedia.org/wiki/procedure _ %28computer_science% 29"; +Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Chạy một thủ tục không có giá trị hoàn trả."; +Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "http://en.wikipedia.org/wiki/procedure _ %28computer_science% 29"; +Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Chạy một thủ tục có giá trị hoàn trả."; +Blockly.Msg.PROCEDURES_CREATE_DO = "Tạo mảnh \"thực hiện %1\""; +Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; +Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated +Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "thủ tục"; +Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = ""; +Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Một thủ tục không có giá trị hoàn trả."; +Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated +Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "hoàn trả"; +Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Một thủ tục có giá trị hoàn trả."; +Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Chú ý: Thủ tục này có lặp lại tên các tham số."; +Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Làm nổi bật thủ tục"; +Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Khi điều kiện đúng thì hoàn trả một giá trị."; +Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Chú ý: Mảnh này chỉ có thể dùng trong một thủ tục."; +Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "biến:"; +Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "các tham số"; +Blockly.Msg.REMOVE_COMMENT = "Xóa Chú Giải"; +Blockly.Msg.RENAME_VARIABLE = "Thay tên biến..."; +Blockly.Msg.RENAME_VARIABLE_TITLE = "Thay tên tất cả \"%1\" biến này thành:"; +Blockly.Msg.TEXT_APPEND_APPENDTEXT = "thêm văn bản"; +Blockly.Msg.TEXT_APPEND_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Text_modification"; // untranslated +Blockly.Msg.TEXT_APPEND_TO = "ở cuối"; +Blockly.Msg.TEXT_APPEND_TOOLTIP = "Thêm một mảng văn bản vào biến \"%1\"."; +Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case"; // untranslated +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "thành chữ thường"; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "thành Chữ In Đầu Mỗi Từ"; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "thành CHỮ IN HOA"; +Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Hoàn trả văn bản sau khi chuyển đổi chữ in hoa hay thường."; +Blockly.Msg.TEXT_CHARAT_FIRST = "lấy ký tự đầu tiên"; +Blockly.Msg.TEXT_CHARAT_FROM_END = "lấy từ phía cuối, ký tự thứ"; +Blockly.Msg.TEXT_CHARAT_FROM_START = "lấy ký tự thứ"; +Blockly.Msg.TEXT_CHARAT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Extracting_text"; // untranslated +Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "trong văn bản"; +Blockly.Msg.TEXT_CHARAT_LAST = "lấy ký tự cuối cùng"; +Blockly.Msg.TEXT_CHARAT_RANDOM = "lấy ký tự bất kỳ"; +Blockly.Msg.TEXT_CHARAT_TAIL = ""; +Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Hoàn trả ký tự ở vị trí đặt ra."; +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "thêm vật mới vào văn bản."; +Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "kết nối"; +Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Thêm, bỏ, hoặc sắp xếp lại các thành phần để tạo dựng mảnh văn bản này."; +Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "đến từ phía cuối, ký tự thứ"; +Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "đến ký tự thứ"; +Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "đến ký tự cuối cùng"; +Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text"; // untranslated +Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "trong văn bản"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "lấy từ ký tự đầu tiên"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "lấy từ phía cuối, ký tự thứ"; +Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "lấy từ ký tự thứ"; +Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; +Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Hoàn trả một mảng ký tự ấn định từ trong văn bản."; +Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Finding_text"; // untranslated +Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "trong văn bản"; +Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "tìm sự có mặt đầu tiên của"; +Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "tìm sự có mặt cuối cùng của"; +Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated +Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Hoàn trả vị trí xuất hiện đầu/cuối của văn bản thứ nhất trong văn bản thứ hai. Nếu không tìm thấy thì hoàn trả số 0."; +Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text"; // untranslated +Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 trống không"; +Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Hoàn trả “đúng nếu văn bản không có ký tự nào."; +Blockly.Msg.TEXT_JOIN_HELPURL = ""; +Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "tạo văn bản từ"; +Blockly.Msg.TEXT_JOIN_TOOLTIP = "Tạo một văn bản từ các thành phần."; +Blockly.Msg.TEXT_LENGTH_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Text_modification"; // untranslated +Blockly.Msg.TEXT_LENGTH_TITLE = "độ dài của %1"; +Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Hoàn trả số lượng ký tự (kể cả khoảng trắng) trong văn bản đầu vào."; +Blockly.Msg.TEXT_PRINT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Printing_text"; // untranslated +Blockly.Msg.TEXT_PRINT_TITLE = "in lên màng hình %1"; +Blockly.Msg.TEXT_PRINT_TOOLTIP = "In ra màng hình một văn bản, con số, hay một giá trị đầu vào khác."; +Blockly.Msg.TEXT_PROMPT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user"; // untranslated +Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Xin người dùng nhập vào một con số."; +Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Xin người dùng nhập vào một văn bản."; +Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "Xin người dùng nhập vào con số với dòng hướng dẫn"; +Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "Xin người dùng nhập vào văn bản với dòng hướng dẫn"; +Blockly.Msg.TEXT_TEXT_HELPURL = "http://en.wikipedia.org/wiki/string _(computer_science)"; +Blockly.Msg.TEXT_TEXT_TOOLTIP = "Một ký tự, một từ, hay một dòng."; +Blockly.Msg.TEXT_TRIM_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces"; // untranslated +Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "xóa khoảng trắng từ bên trái và phải"; +Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "xóa khoảng trắng từ bên trái"; +Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "xóa khoảng trắng từ bên phải"; +Blockly.Msg.TEXT_TRIM_TOOLTIP = "Hoàn trả bản sao của văn bản sau khi xóa khoảng trắng từ một hoặc hai bên."; +Blockly.Msg.VARIABLES_DEFAULT_NAME = "vật"; +Blockly.Msg.VARIABLES_GET_CREATE_SET = "Tạo mảnh \"đặt vào %1\""; +Blockly.Msg.VARIABLES_GET_HELPURL = "http://code.google.com/p/blockly/wiki/Variables#Get"; // untranslated +Blockly.Msg.VARIABLES_GET_TAIL = ""; +Blockly.Msg.VARIABLES_GET_TITLE = ""; +Blockly.Msg.VARIABLES_GET_TOOLTIP = "Hoàn trả giá trị của."; +Blockly.Msg.VARIABLES_SET_CREATE_GET = "Tạo mảnh \"lấy %1\""; +Blockly.Msg.VARIABLES_SET_HELPURL = "http://code.google.com/p/blockly/wiki/Variables#Set"; // untranslated +Blockly.Msg.VARIABLES_SET_TAIL = "bằng"; +Blockly.Msg.VARIABLES_SET_TITLE = "cho"; +Blockly.Msg.VARIABLES_SET_TOOLTIP = "Đặt giá trị của biến này thành..."; +Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; +Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; +Blockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; +Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL; +Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; +Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; +Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; \ No newline at end of file diff --git a/msg/js/zh_tw.js b/msg/js/zh_tw.js new file mode 100644 index 000000000..2bbe4bd24 --- /dev/null +++ b/msg/js/zh_tw.js @@ -0,0 +1,377 @@ +// This file was automatically generated. Do not modify. + +'use strict'; + +goog.provide('Blockly.Msg.zh_tw'); + +goog.require('Blockly.Msg'); + +Blockly.Msg.ADD_COMMENT = "加入註解"; +Blockly.Msg.CHANGE_VALUE_TITLE = "修改值:"; +Blockly.Msg.COLLAPSE_ALL = "Collapse Blocks"; // untranslated +Blockly.Msg.COLLAPSE_BLOCK = "收合積木"; +Blockly.Msg.COLOUR_BLEND_COLOUR1 = "colour 1"; // untranslated +Blockly.Msg.COLOUR_BLEND_COLOUR2 = "colour 2"; // untranslated +Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated +Blockly.Msg.COLOUR_BLEND_RATIO = "ratio"; // untranslated +Blockly.Msg.COLOUR_BLEND_TITLE = "blend"; // untranslated +Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Blends two colours together with a given ratio (0.0 - 1.0)."; // untranslated +Blockly.Msg.COLOUR_PICKER_HELPURL = "http://en.wikipedia.org/wiki/Color"; // untranslated +Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Choose a colour from the palette."; // untranslated +Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated +Blockly.Msg.COLOUR_RANDOM_TITLE = "random colour"; // untranslated +Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Choose a colour at random."; // untranslated +Blockly.Msg.COLOUR_RGB_BLUE = "blue"; // untranslated +Blockly.Msg.COLOUR_RGB_GREEN = "green"; // untranslated +Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated +Blockly.Msg.COLOUR_RGB_RED = "red"; // untranslated +Blockly.Msg.COLOUR_RGB_TITLE = "colour with"; // untranslated +Blockly.Msg.COLOUR_RGB_TOOLTIP = "Create a colour with the specified amount of red, green, and blue. All values must be between 0 and 100."; // untranslated +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks"; // untranslated +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "停止 迴圈"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "繼續下一個 迴圈"; +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Break out of the containing loop."; // untranslated +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Skip the rest of this loop, and continue with the next iteration."; // untranslated +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Warning: This block may only be used within a loop."; // untranslated +Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#for_each for each block"; // untranslated +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = "自列表"; +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = ""; +Blockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = "取出每個"; +Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "For each item in a list, set the variable '%1' to the item, and then do some statements."; // untranslated +Blockly.Msg.CONTROLS_FOR_HELPURL = "https://code.google.com/p/blockly/wiki/Loops#count_with"; // untranslated +Blockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = "從範圍 %1 到 %2 每隔 %3"; +Blockly.Msg.CONTROLS_FOR_INPUT_WITH = "使用"; +Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Have the variable %1 take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks."; // untranslated +Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Add a condition to the if block."; // untranslated +Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Add a final, catch-all condition to the if block."; // untranslated +Blockly.Msg.CONTROLS_IF_HELPURL = "http://code.google.com/p/blockly/wiki/If_Then"; // untranslated +Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Add, remove, or reorder sections to reconfigure this if block."; // untranslated +Blockly.Msg.CONTROLS_IF_MSG_ELSE = "否則"; +Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "否則如果"; +Blockly.Msg.CONTROLS_IF_MSG_IF = "if"; // untranslated +Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "If a value is true, then do some statements."; // untranslated +Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "If a value is true, then do the first block of statements. Otherwise, do the second block of statements."; // untranslated +Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements."; // untranslated +Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements. If none of the values are true, do the last block of statements."; // untranslated +Blockly.Msg.CONTROLS_REPEAT_HELPURL = "http://en.wikipedia.org/wiki/For_loop"; // untranslated +Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "執行"; +Blockly.Msg.CONTROLS_REPEAT_TITLE = "重複 %1 次數"; +Blockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = "重複"; +Blockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = "次數"; +Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Do some statements several times."; // untranslated +Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "http://code.google.com/p/blockly/wiki/Repeat"; // untranslated +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "重複 直到"; +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "重複 當"; +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "While a value is false, then do some statements."; // untranslated +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "While a value is true, then do some statements."; // untranslated +Blockly.Msg.DELETE_BLOCK = "刪除積木"; +Blockly.Msg.DELETE_X_BLOCKS = "刪除 %1 塊積木"; +Blockly.Msg.DISABLE_BLOCK = "停用積木"; +Blockly.Msg.DUPLICATE_BLOCK = "複製"; +Blockly.Msg.ENABLE_BLOCK = "啟用積木"; +Blockly.Msg.EXPAND_ALL = "Expand Blocks"; // untranslated +Blockly.Msg.EXPAND_BLOCK = "展開積木"; +Blockly.Msg.EXTERNAL_INPUTS = "多行輸入"; +Blockly.Msg.HELP = "說明"; +Blockly.Msg.INLINE_INPUTS = "單行輸入"; +Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "http://en.wikipedia.org/wiki/Linked_list#Empty_lists"; // untranslated +Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "建立空列表"; +Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Returns a list, of length 0, containing no data records"; // untranslated +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "加入"; +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Add, remove, or reorder sections to reconfigure this list block."; // untranslated +Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "使用這些值建立列表"; +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Add an item to the list."; // untranslated +Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Create a list with any number of items."; // untranslated +Blockly.Msg.LISTS_GET_INDEX_FIRST = "first"; // untranslated +Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# from end"; // untranslated +Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated +Blockly.Msg.LISTS_GET_INDEX_GET = "get"; // untranslated +Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "get and remove"; // untranslated +Blockly.Msg.LISTS_GET_INDEX_LAST = "last"; // untranslated +Blockly.Msg.LISTS_GET_INDEX_RANDOM = "random"; // untranslated +Blockly.Msg.LISTS_GET_INDEX_REMOVE = "remove"; // untranslated +Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Returns the first item in a list."; // untranslated +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = "Returns the item at the specified position in a list. #1 is the last item."; // untranslated +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = "Returns the item at the specified position in a list. #1 is the first item."; // untranslated +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Returns the last item in a list."; // untranslated +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Returns a random item in a list."; // untranslated +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Removes and returns the first item in a list."; // untranslated +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = "Removes and returns the item at the specified position in a list. #1 is the last item."; // untranslated +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = "Removes and returns the item at the specified position in a list. #1 is the first item."; // untranslated +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Removes and returns the last item in a list."; // untranslated +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Removes and returns a random item in a list."; // untranslated +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Removes the first item in a list."; // untranslated +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = "Removes the item at the specified position in a list. #1 is the last item."; // untranslated +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = "Removes the item at the specified position in a list. #1 is the first item."; // untranslated +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Removes the last item in a list."; // untranslated +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Removes a random item in a list."; // untranslated +Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "to # from end"; // untranslated +Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "to #"; // untranslated +Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "to last"; // untranslated +Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist"; // untranslated +Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "get sub-list from first"; // untranslated +Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "get sub-list from # from end"; // untranslated +Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "get sub-list from #"; // untranslated +Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated +Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Creates a copy of the specified portion of a list."; // untranslated +Blockly.Msg.LISTS_INDEX_OF_FIRST = "找出 第一個 項目出現"; +Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List"; // untranslated +Blockly.Msg.LISTS_INDEX_OF_LAST = "找出 最後一個 項目出現"; +Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Returns the index of the first/last occurrence of the item in the list. Returns 0 if text is not found."; // untranslated +Blockly.Msg.LISTS_INLIST = "in list"; // untranslated +Blockly.Msg.LISTS_IS_EMPTY_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#is_empty"; // untranslated +Blockly.Msg.LISTS_IS_EMPTY_TITLE = "%1 值為空"; +Blockly.Msg.LISTS_LENGTH_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#length_of"; // untranslated +Blockly.Msg.LISTS_LENGTH_TITLE = "長度 %1"; +Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Returns the length of a list."; // untranslated +Blockly.Msg.LISTS_REPEAT_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#create_list_with"; // untranslated +Blockly.Msg.LISTS_REPEAT_TITLE = "建立列表使用項目 %1 重複 %2 次數"; +Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Creates a list consisting of the given value repeated the specified number of times."; // untranslated +Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://code.google.com/p/blockly/wiki/Lists#in_list_..._set"; // untranslated +Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "as"; // untranslated +Blockly.Msg.LISTS_SET_INDEX_INSERT = "insert at"; // untranslated +Blockly.Msg.LISTS_SET_INDEX_SET = "set"; // untranslated +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Inserts the item at the start of a list."; // untranslated +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = "Inserts the item at the specified position in a list. #1 is the last item."; // untranslated +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = "Inserts the item at the specified position in a list. #1 is the first item."; // untranslated +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Append the item to the end of a list."; // untranslated +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Inserts the item randomly in a list."; // untranslated +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Sets the first item in a list."; // untranslated +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = "Sets the item at the specified position in a list. #1 is the last item."; // untranslated +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = "Sets the item at the specified position in a list. #1 is the first item."; // untranslated +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Sets the last item in a list."; // untranslated +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Sets a random item in a list."; // untranslated +Blockly.Msg.LISTS_TOOLTIP = "Returns true if the list is empty."; // untranslated +Blockly.Msg.LOGIC_BOOLEAN_FALSE = "否"; +Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "http://code.google.com/p/blockly/wiki/True_False"; // untranslated +Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Returns either true or false."; // untranslated +Blockly.Msg.LOGIC_BOOLEAN_TRUE = "是"; +Blockly.Msg.LOGIC_COMPARE_HELPURL = "http://en.wikipedia.org/wiki/Inequality_(mathematics)"; // untranslated +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Return true if both inputs equal each other."; // untranslated +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Return true if the first input is greater than the second input."; // untranslated +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Return true if the first input is greater than or equal to the second input."; // untranslated +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Return true if the first input is smaller than the second input."; // untranslated +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Return true if the first input is smaller than or equal to the second input."; // untranslated +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Return true if both inputs are not equal to each other."; // untranslated +Blockly.Msg.LOGIC_NEGATE_HELPURL = "http://code.google.com/p/blockly/wiki/Not"; // untranslated +Blockly.Msg.LOGIC_NEGATE_TITLE = "非 %1"; +Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Returns true if the input is false. Returns false if the input is true."; // untranslated +Blockly.Msg.LOGIC_NULL = "空"; +Blockly.Msg.LOGIC_NULL_HELPURL = "http://en.wikipedia.org/wiki/Nullable_type"; // untranslated +Blockly.Msg.LOGIC_NULL_TOOLTIP = "Returns null."; // untranslated +Blockly.Msg.LOGIC_OPERATION_AND = "且"; +Blockly.Msg.LOGIC_OPERATION_HELPURL = "http://code.google.com/p/blockly/wiki/And_Or"; // untranslated +Blockly.Msg.LOGIC_OPERATION_OR = "或"; +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Return true if both inputs are true."; // untranslated +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Return true if at least one of the inputs is true."; // untranslated +Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; // untranslated +Blockly.Msg.LOGIC_TERNARY_HELPURL = "http://en.wikipedia.org/wiki/%3F:"; // untranslated +Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "if false"; // untranslated +Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "if true"; // untranslated +Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value."; // untranslated +Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated +Blockly.Msg.MATH_ARITHMETIC_HELPURL = "http://en.wikipedia.org/wiki/Arithmetic"; // untranslated +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Return the sum of the two numbers."; // untranslated +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Return the quotient of the two numbers."; // untranslated +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Return the difference of the two numbers."; // untranslated +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Return the product of the two numbers."; // untranslated +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Return the first number raised to the power of the second number."; // untranslated +Blockly.Msg.MATH_CHANGE_HELPURL = "http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; // untranslated +Blockly.Msg.MATH_CHANGE_INPUT_BY = "自"; +Blockly.Msg.MATH_CHANGE_TITLE_CHANGE = "修改"; +Blockly.Msg.MATH_CHANGE_TOOLTIP = "Add a number to variable '%1'."; // untranslated +Blockly.Msg.MATH_CONSTANT_HELPURL = "http://en.wikipedia.org/wiki/Mathematical_constant"; // untranslated +Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity)."; // untranslated +Blockly.Msg.MATH_CONSTRAIN_HELPURL = "http://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated +Blockly.Msg.MATH_CONSTRAIN_TITLE = "限制數字 %1 介於 (低) %2 到 (高) %3"; +Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Constrain a number to be between the specified limits (inclusive)."; // untranslated +Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated +Blockly.Msg.MATH_IS_DIVISIBLE_BY = "is divisible by"; // untranslated +Blockly.Msg.MATH_IS_EVEN = "is even"; // untranslated +Blockly.Msg.MATH_IS_NEGATIVE = "is negative"; // untranslated +Blockly.Msg.MATH_IS_ODD = "is odd"; // untranslated +Blockly.Msg.MATH_IS_POSITIVE = "is positive"; // untranslated +Blockly.Msg.MATH_IS_PRIME = "is prime"; // untranslated +Blockly.Msg.MATH_IS_TOOLTIP = "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false."; // untranslated +Blockly.Msg.MATH_IS_WHOLE = "is whole"; // untranslated +Blockly.Msg.MATH_MODULO_HELPURL = "http://en.wikipedia.org/wiki/Modulo_operation"; // untranslated +Blockly.Msg.MATH_MODULO_TITLE = "取餘數自 %1 ÷ %2"; +Blockly.Msg.MATH_MODULO_TOOLTIP = "Return the remainder from dividing the two numbers."; // untranslated +Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated +Blockly.Msg.MATH_NUMBER_HELPURL = "http://en.wikipedia.org/wiki/Number"; // untranslated +Blockly.Msg.MATH_NUMBER_TOOLTIP = "A number."; // untranslated +Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated +Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "平均值 自列表"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "最大值 自列表"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "中位數 自列表"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "最小值 自列表"; +Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "比較眾數 自列表"; +Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "隨機抽取 自列表"; +Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "標準差 自列表"; +Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "總和 自列表"; +Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Return the average (arithmetic mean) of the numeric values in the list."; // untranslated +Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Return the largest number in the list."; // untranslated +Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Return the median number in the list."; // untranslated +Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Return the smallest number in the list."; // untranslated +Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Return a list of the most common item(s) in the list."; // untranslated +Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Return a random element from the list."; // untranslated +Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Return the standard deviation of the list."; // untranslated +Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Return the sum of all the numbers in the list."; // untranslated +Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated +Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "http://en.wikipedia.org/wiki/Random_number_generation"; // untranslated +Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "取隨機分數"; +Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive)."; // untranslated +Blockly.Msg.MATH_RANDOM_INT_HELPURL = "http://en.wikipedia.org/wiki/Random_number_generation"; // untranslated +Blockly.Msg.MATH_RANDOM_INT_TITLE = "取隨機整數介於 (低) %1 到 %2"; +Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Return a random integer between the two specified limits, inclusive."; // untranslated +Blockly.Msg.MATH_ROUND_HELPURL = "http://en.wikipedia.org/wiki/Rounding"; // untranslated +Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "四捨五入"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "無條件捨去"; +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "無條件進位"; +Blockly.Msg.MATH_ROUND_TOOLTIP = "Round a number up or down."; // untranslated +Blockly.Msg.MATH_SINGLE_HELPURL = "http://en.wikipedia.org/wiki/Square_root"; // untranslated +Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "絕對值"; +Blockly.Msg.MATH_SINGLE_OP_ROOT = "開根號"; +Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Return the absolute value of a number."; // untranslated +Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Return e to the power of a number."; // untranslated +Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Return the natural logarithm of a number."; // untranslated +Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Return the base 10 logarithm of a number."; // untranslated +Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Return the negation of a number."; // untranslated +Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Return 10 to the power of a number."; // untranslated +Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Return the square root of a number."; // untranslated +Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated +Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated +Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated +Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated +Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated +Blockly.Msg.MATH_TRIG_HELPURL = "http://en.wikipedia.org/wiki/Trigonometric_functions"; // untranslated +Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated +Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated +Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Return the arccosine of a number."; // untranslated +Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Return the arcsine of a number."; // untranslated +Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Return the arctangent of a number."; // untranslated +Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Return the cosine of a degree (not radian)."; // untranslated +Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Return the sine of a degree (not radian)."; // untranslated +Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Return the tangent of a degree (not radian)."; // untranslated +Blockly.Msg.NEW_VARIABLE = "新變量..."; +Blockly.Msg.NEW_VARIABLE_TITLE = "新變量名稱:"; +Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated +Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "with:"; // untranslated +Blockly.Msg.PROCEDURES_CALLNORETURN_CALL = "呼叫"; +Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated +Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Run the user-defined function '%1'."; // untranslated +Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated +Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Run the user-defined function '%1' and use its output."; // untranslated +Blockly.Msg.PROCEDURES_CREATE_DO = "Create '%1'"; // untranslated +Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated +Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated +Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "流程"; +Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "to"; // untranslated +Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Creates a function with no output."; // untranslated +Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated +Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "回傳"; +Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Creates a function with an output."; // untranslated +Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Warning: This function has duplicate parameters."; // untranslated +Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Highlight function definition"; // untranslated +Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "If a value is true, then return a second value."; // untranslated +Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Warning: This block may be used only within a function definition."; // untranslated +Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "變量:"; +Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "參數"; +Blockly.Msg.REMOVE_COMMENT = "移除註解"; +Blockly.Msg.RENAME_VARIABLE = "重新命名變量..."; +Blockly.Msg.RENAME_VARIABLE_TITLE = "將所有 \"%1\" 變量重新命名為:"; +Blockly.Msg.TEXT_APPEND_APPENDTEXT = "後加入文字"; +Blockly.Msg.TEXT_APPEND_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Text_modification"; // untranslated +Blockly.Msg.TEXT_APPEND_TO = "在"; +Blockly.Msg.TEXT_APPEND_TOOLTIP = "Append some text to variable '%1'."; // untranslated +Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case"; // untranslated +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "改成 轉小寫"; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "改成 頭字母大寫"; +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "改成 轉大寫"; +Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Return a copy of the text in a different case."; // untranslated +Blockly.Msg.TEXT_CHARAT_FIRST = "get first letter"; // untranslated +Blockly.Msg.TEXT_CHARAT_FROM_END = "get letter # from end"; // untranslated +Blockly.Msg.TEXT_CHARAT_FROM_START = "get letter #"; // untranslated +Blockly.Msg.TEXT_CHARAT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Extracting_text"; // untranslated +Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "的字元在字串"; +Blockly.Msg.TEXT_CHARAT_LAST = "get last letter"; // untranslated +Blockly.Msg.TEXT_CHARAT_RANDOM = "get random letter"; // untranslated +Blockly.Msg.TEXT_CHARAT_TAIL = ""; +Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Returns the letter at the specified position."; // untranslated +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Add an item to the text."; // untranslated +Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "加入"; +Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Add, remove, or reorder sections to reconfigure this text block."; // untranslated +Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "to letter # from end"; // untranslated +Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "to letter #"; // untranslated +Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "to last letter"; // untranslated +Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text"; // untranslated +Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "in text"; // untranslated +Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "get substring from first letter"; // untranslated +Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "get substring from letter # from end"; // untranslated +Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "get substring from letter #"; // untranslated +Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated +Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Returns a specified portion of the text."; // untranslated +Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Finding_text"; // untranslated +Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "在字串"; +Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "尋找 第一個 出現的字串"; +Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "尋找 最後一個 出現的字串"; +Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated +Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Returns the index of the first/last occurrence of first text in the second text. Returns 0 if text is not found."; // untranslated +Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text"; // untranslated +Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 為空"; +Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Returns true if the provided text is empty."; // untranslated +Blockly.Msg.TEXT_JOIN_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Text_creation"; // untranslated +Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "建立字串使用"; +Blockly.Msg.TEXT_JOIN_TOOLTIP = "Create a piece of text by joining together any number of items."; // untranslated +Blockly.Msg.TEXT_LENGTH_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Text_modification"; // untranslated +Blockly.Msg.TEXT_LENGTH_TITLE = "長度 %1"; +Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Returns the number of letters (including spaces) in the provided text."; // untranslated +Blockly.Msg.TEXT_PRINT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Printing_text"; // untranslated +Blockly.Msg.TEXT_PRINT_TITLE = "印出 %1"; +Blockly.Msg.TEXT_PRINT_TOOLTIP = "Print the specified text, number or other value."; // untranslated +Blockly.Msg.TEXT_PROMPT_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user"; // untranslated +Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Prompt for user for a number."; // untranslated +Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Prompt for user for some text."; // untranslated +Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "輸入 數字 並顯示提示訊息"; +Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "輸入 文字 並顯示提示訊息"; +Blockly.Msg.TEXT_TEXT_HELPURL = "http://en.wikipedia.org/wiki/String_(computer_science)"; // untranslated +Blockly.Msg.TEXT_TEXT_TOOLTIP = "A letter, word, or line of text."; // untranslated +Blockly.Msg.TEXT_TRIM_HELPURL = "https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces"; // untranslated +Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "從 兩側 消除空格"; +Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "從 左側 消除空格"; +Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "從 右側 消除空格"; +Blockly.Msg.TEXT_TRIM_TOOLTIP = "Return a copy of the text with spaces removed from one or both ends."; // untranslated +Blockly.Msg.VARIABLES_DEFAULT_NAME = "變量"; +Blockly.Msg.VARIABLES_GET_CREATE_SET = "Create 'set %1'"; // untranslated +Blockly.Msg.VARIABLES_GET_HELPURL = "http://code.google.com/p/blockly/wiki/Variables#Get"; // untranslated +Blockly.Msg.VARIABLES_GET_TAIL = ""; +Blockly.Msg.VARIABLES_GET_TITLE = ""; +Blockly.Msg.VARIABLES_GET_TOOLTIP = "Returns the value of this variable."; // untranslated +Blockly.Msg.VARIABLES_SET_CREATE_GET = "Create 'get %1'"; // untranslated +Blockly.Msg.VARIABLES_SET_HELPURL = "http://code.google.com/p/blockly/wiki/Variables#Set"; // untranslated +Blockly.Msg.VARIABLES_SET_TAIL = ""; +Blockly.Msg.VARIABLES_SET_TITLE = "賦值"; +Blockly.Msg.VARIABLES_SET_TOOLTIP = "Sets this variable to be equal to the input."; // untranslated +Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; +Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; +Blockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; +Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL; +Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; +Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; +Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; +Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; \ No newline at end of file diff --git a/msg/json/de.json b/msg/json/de.json new file mode 100644 index 000000000..2078cf17e --- /dev/null +++ b/msg/json/de.json @@ -0,0 +1,342 @@ +{ + "@metadata": { + "authors": [ + "Metalhead64" + ] + }, + "VARIABLES_DEFAULT_NAME": "Element", + "DUPLICATE_BLOCK": "Kopieren", + "ADD_COMMENT": "Kommentar hinzuf\u00fcgen", + "REMOVE_COMMENT": "Kommentar entfernen", + "EXTERNAL_INPUTS": "externe Eing\u00e4nge", + "INLINE_INPUTS": "interne Eing\u00e4nge", + "DELETE_BLOCK": "Block l\u00f6schen", + "DELETE_X_BLOCKS": "Block %1 l\u00f6schen", + "COLLAPSE_BLOCK": "Block zusammenfalten", + "COLLAPSE_ALL": "Collapse Blocks", + "EXPAND_BLOCK": "Block entfalten", + "EXPAND_ALL": "Expand Blocks", + "DISABLE_BLOCK": "Block deaktivieren", + "ENABLE_BLOCK": "Block aktivieren", + "HELP": "Hilfe", + "CHANGE_VALUE_TITLE": "Wert \u00e4ndern:", + "NEW_VARIABLE": "Neue Variable...", + "NEW_VARIABLE_TITLE": "Name der neuen Variable:", + "RENAME_VARIABLE": "Variable umbenennen...", + "RENAME_VARIABLE_TITLE": "Alle \"%1\" Variablen umbenennen in:", + "COLOUR_PICKER_HELPURL": "http://de.wikipedia.org/wiki/Farbe", + "COLOUR_PICKER_TOOLTIP": "W\u00e4hlen eine Farbe von der Palette.", + "COLOUR_RANDOM_TITLE": "random colour", + "COLOUR_RANDOM_TOOLTIP": "Choose a colour at random.", + "COLOUR_RGB_HELPURL": "http://de.wikipedia.org/wiki/RGB-Farbraum", + "COLOUR_RGB_TITLE": "Farbe mit", + "COLOUR_RGB_RED": "rot", + "COLOUR_RGB_GREEN": "gr\u00fcn", + "COLOUR_RGB_BLUE": "blau", + "COLOUR_RGB_TOOLTIP": "Kreiere eine Farbe mit selbst definierten rot, gr\u00fcn und blau Werten. Alle Werte m\u00fcssen zwischen 0 und 100 liegen.", + "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", + "COLOUR_BLEND_TITLE": "mische", + "COLOUR_BLEND_COLOUR1": "Farbe 1", + "COLOUR_BLEND_COLOUR2": "mit Farbe 2", + "COLOUR_BLEND_RATIO": "im Verh\u00e4ltniss", + "COLOUR_BLEND_TOOLTIP": "Vermische 2 Farbe mit konfigurierbaren Farbverh\u00e4ltniss (0.0 - 1.0).", + "CONTROLS_REPEAT_HELPURL": "http://de.wikipedia.org/wiki/For-Schleife", + "CONTROLS_REPEAT_TITLE": "wiederhole %1 mal", + "CONTROLS_REPEAT_TITLE_REPEAT": "wiederhole", + "CONTROLS_REPEAT_TITLE_TIMES": "mal", + "CONTROLS_REPEAT_INPUT_DO": "mache", + "CONTROLS_REPEAT_TOOLTIP": "Eine Anweisung mehrfach ausf\u00fchren.", + "CONTROLS_WHILEUNTIL_HELPURL": "http://de.wikipedia.org/wiki/Schleife_%28Programmierung%29", + "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "Wiederhole solange", + "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "Wiederhole bis", + "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "F\u00fchre die Anweisung solange aus wie die Bedingung wahr (true) ist.", + "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "F\u00fchre die Anweisung solange aus wie die Bedingung falsch (false) ist.", + "CONTROLS_FOR_HELPURL": "http://de.wikipedia.org/wiki/For-Schleif", + "CONTROLS_FOR_TOOLTIP": "Z\u00e4hle die Variable \"%1\" von einem Startwert bis zu einem Zielwert und f\u00fchre f\u00fcr jeden Wert eine Anweisung aus.", + "CONTROLS_FOR_INPUT_WITH": "Z\u00e4hle", + "CONTROLS_FOR_INPUT_FROM_TO_BY": "von %1 bis %2 mit %3", + "CONTROLS_FOREACH_HELPURL": "http://de.wikipedia.org/wiki/For-Schleif", + "CONTROLS_FOREACH_INPUT_ITEM": "F\u00fcr Wert", + "CONTROLS_FOREACH_INPUT_INLIST": "aus der Liste", + "CONTROLS_FOREACH_INPUT_INLIST_TAIL": "", + "CONTROLS_FOREACH_TOOLTIP": "F\u00fchre eine Anweisung f\u00fcr jeden Wert in der Liste aus und setzte dabei die Variable \"%1\" auf den aktuellen Listen Wert.", + "CONTROLS_FLOW_STATEMENTS_HELPURL": "http://de.wikipedia.org/wiki/Kontrollstruktur", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "ausbrechen aus der Schleife", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "mit der n\u00e4chsten Iteration fortfahren aus der Schleife", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Die umgebene Schleife beenden.", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Diese Anweisung abbrechen und mit der n\u00e4chsten Schleifeniteration fortfahren.", + "CONTROLS_FLOW_STATEMENTS_WARNING": "Warnung: Diese block sollte nur in einer Schleife verwendet werden.", + "CONTROLS_IF_HELPURL": "http://code.google.com/p/blockly/wiki/If_Then", + "CONTROLS_IF_TOOLTIP_1": "Wenn eine Bedingung wahr (true) ist, dann f\u00fchre eine Anweisung aus.", + "CONTROLS_IF_TOOLTIP_2": "Wenn eine Bedingung wahr (true) ist, dann f\u00fchre die erste Anweisung aus. Ansonsten f\u00fchre die zweite Anweisung aus.", + "CONTROLS_IF_TOOLTIP_3": "Wenn der erste Bedingung wahr (true) ist, dann f\u00fchre die erste Anweisung aus. Oder wenn die zweite Bedingung wahr (true) ist, dann f\u00fchre die zweite Anweisung aus.", + "CONTROLS_IF_TOOLTIP_4": "Wenn der erste Bedingung wahr (true) ist, dann f\u00fchre die erste Anweisung aus. Oder wenn die zweite Bedingung wahr (true) ist, dann f\u00fchre die zweite Anweisung aus. Falls keine der beiden Bedingungen wahr (true) ist, dann f\u00fchre die dritte Anweisung aus.", + "CONTROLS_IF_MSG_IF": "wenn", + "CONTROLS_IF_MSG_ELSEIF": "oder wenn", + "CONTROLS_IF_MSG_ELSE": "oder", + "CONTROLS_IF_IF_TOOLTIP": "Hinzuf\u00fcgen, entfernen oder sortieren von Sektionen", + "CONTROLS_IF_ELSEIF_TOOLTIP": "Eine weitere Bedingung hinzuf\u00fcgen.", + "CONTROLS_IF_ELSE_TOOLTIP": "Eine oder Bedingung hinzuf\u00fcgen, f\u00fchrt eine Anweisung aus falls keine Bedingung zutrifft.", + "LOGIC_COMPARE_HELPURL": "http://de.wikipedia.org/wiki/Vergleich_%28Zahlen%29", + "LOGIC_COMPARE_TOOLTIP_EQ": "Ist wahr (true) wenn beide Werte identisch sind.", + "LOGIC_COMPARE_TOOLTIP_NEQ": "Ist wahr (true) wenn beide Werte unterschiedlich sind.", + "LOGIC_COMPARE_TOOLTIP_LT": "Ist wahr (true) wenn der erste Wert kleiner als der zweite Wert ist.", + "LOGIC_COMPARE_TOOLTIP_LTE": "Ist wahr (true) wenn der erste Wert kleiner als oder gleich gross wie zweite Wert ist.", + "LOGIC_COMPARE_TOOLTIP_GT": "Ist wahr (true) wenn der erste Wert gr\u00f6sser als der zweite Wert ist.", + "LOGIC_COMPARE_TOOLTIP_GTE": "Ist wahr (true) wenn der erste Wert gr\u00f6sser als oder gleich gross wie zweite Wert ist.", + "LOGIC_OPERATION_HELPURL": "http://code.google.com/p/blockly/wiki/And_Or", + "LOGIC_OPERATION_TOOLTIP_AND": "Ist wahr (true) wenn beide Werte wahr (true) sind.", + "LOGIC_OPERATION_AND": "und", + "LOGIC_OPERATION_TOOLTIP_OR": "Ist wahr (true) wenn einer der beiden Werte wahr (true) ist.", + "LOGIC_OPERATION_OR": "oder", + "LOGIC_NEGATE_HELPURL": "http://code.google.com/p/blockly/wiki/Not", + "LOGIC_NEGATE_TITLE": "nicht %1", + "LOGIC_NEGATE_TOOLTIP": "Ist wahr (true) wenn der Eingabewert falsch (false) ist. Ist falsch (false) wenn der Eingabewert wahr (true) ist.", + "LOGIC_BOOLEAN_HELPURL": "http://code.google.com/p/blockly/wiki/True_False", + "LOGIC_BOOLEAN_TRUE": "wahr", + "LOGIC_BOOLEAN_FALSE": "falsch", + "LOGIC_BOOLEAN_TOOLTIP": "Ist entweder wahr (true) oder falsch (false)", + "LOGIC_NULL_HELPURL": "http://de.wikipedia.org/wiki/Nullwert", + "LOGIC_NULL": "null", + "LOGIC_NULL_TOOLTIP": "Ist NULL.", + "LOGIC_TERNARY_HELPURL": "http://de.wikipedia.org/wiki/%3F:#Auswahloperator", + "LOGIC_TERNARY_CONDITION": "test", + "LOGIC_TERNARY_IF_TRUE": "wenn wahr", + "LOGIC_TERNARY_IF_FALSE": "wenn falsch", + "LOGIC_TERNARY_TOOLTIP": "\u00dcberpr\u00fcft eine Bedingung \"test\". Wenn die Bedingung wahr ist wird der \"wenn wahr\" Wert zur\u00fcckgegeben, andernfalls der \"wenn falsch\" Wert", + "MATH_NUMBER_HELPURL": "http://de.wikipedia.org/wiki/Zahl", + "MATH_NUMBER_TOOLTIP": "Eine Zahl.", + "MATH_ARITHMETIC_HELPURL": "http://de.wikipedia.org/wiki/Grundrechenart", + "MATH_ARITHMETIC_TOOLTIP_ADD": "Ist die Summe zweier Werte.", + "MATH_ARITHMETIC_TOOLTIP_MINUS": "Ist die Differenz zweier Werte.", + "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Ist das Produkt zweier Werte.", + "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Ist der Quotient zweier Werte.", + "MATH_ARITHMETIC_TOOLTIP_POWER": "Ist der erste Wert potenziert mit dem zweiten Wert.", + "MATH_SINGLE_HELPURL": "http://de.wikipedia.org/wiki/Quadratwurzel", + "MATH_SINGLE_OP_ROOT": "Quadratwurzel", + "MATH_SINGLE_TOOLTIP_ROOT": "Ist die Qudratwurzel eines Wertes.", + "MATH_SINGLE_OP_ABSOLUTE": "Absolutwert", + "MATH_SINGLE_TOOLTIP_ABS": "Ist der Absolutwert eines Wertes.", + "MATH_SINGLE_TOOLTIP_NEG": "Negiert einen Wert.", + "MATH_SINGLE_TOOLTIP_LN": "Ist der nat\u00fcrliche Logarithmus eines Wertes.", + "MATH_SINGLE_TOOLTIP_LOG10": "Ist der dekadische Logarithmus eines Wertes.", + "MATH_SINGLE_TOOLTIP_EXP": "Ist Wert der Exponentialfunktion eines Wertes.", + "MATH_SINGLE_TOOLTIP_POW10": "Rechnet 10 hoch Eingabewert.", + "MATH_TRIG_HELPURL": "http://de.wikipedia.org/wiki/Trigonometrie", + "MATH_TRIG_TOOLTIP_SIN": "Ist der Sinus eins Winkels.", + "MATH_TRIG_TOOLTIP_COS": "Ist der Cosinus eins Winkels.", + "MATH_TRIG_TOOLTIP_TAN": "Ist der Tangens eins Winkels.", + "MATH_TRIG_TOOLTIP_ASIN": "Ist der Arcussinus des Eingabewertes.", + "MATH_TRIG_TOOLTIP_ACOS": "Ist der Arcuscosinus des Eingabewertes.", + "MATH_TRIG_TOOLTIP_ATAN": "Ist der Arcustangens des Eingabewertes.", + "MATH_CONSTANT_HELPURL": "http://de.wikipedia.org/wiki/Mathematische_Konstante", + "MATH_CONSTANT_TOOLTIP": "Mathematische Konstanten wie: \u03c0 (3.141\u2026), e (2.718\u2026), \u03c6 (1.618\u2026), sqrt(2) (1.414\u2026), sqrt(\u00bd) (0.707\u2026) oder \u221e (unendlich).", + "MATH_IS_EVEN": "ist gerade", + "MATH_IS_ODD": "ist ungerade", + "MATH_IS_PRIME": "ist eine Primenzahl", + "MATH_IS_WHOLE": "ganze Zahl", + "MATH_IS_POSITIVE": "ist positiv", + "MATH_IS_NEGATIVE": "ist negativ", + "MATH_IS_DIVISIBLE_BY": "ist teilbar durch", + "MATH_IS_TOOLTIP": "\u00dcberpr\u00fcft ob eine Zahl gerade, ungerade, eine Primenzahl, ganzzahlig, positiv, negativ oder durch eine zweite Zahl teilbar ist. Gibt wahr (true) oder falsch (false) zur\u00fcck.", + "MATH_CHANGE_HELPURL": "http://de.wikipedia.org/wiki/Inkrement_und_Dekrement", + "MATH_CHANGE_TITLE_CHANGE": "erh\u00f6he", + "MATH_CHANGE_INPUT_BY": "um", + "MATH_CHANGE_TOOLTIP": "Addiert einen Wert zur Variable \"%1\" hinzu.", + "MATH_ROUND_HELPURL": "http://de.wikipedia.org/wiki/Runden", + "MATH_ROUND_TOOLTIP": "Eine Zahl auf oder ab runden.", + "MATH_ROUND_OPERATOR_ROUND": "runden", + "MATH_ROUND_OPERATOR_ROUNDUP": "auf runden", + "MATH_ROUND_OPERATOR_ROUNDDOWN": "ab runden", + "MATH_ONLIST_HELPURL": "http://www.sysplus.ch/einstieg.php?links=menu\u0026seite=4125\u0026grad=Crash\u0026prog=Excel", + "MATH_ONLIST_OPERATOR_SUM": "Summme einer Liste", + "MATH_ONLIST_TOOLTIP_SUM": "Ist die Summe aller Werte in einer Liste.", + "MATH_ONLIST_OPERATOR_MIN": "Minimalwert einer Liste", + "MATH_ONLIST_TOOLTIP_MIN": "Ist der kleinste Wert in einer Liste.", + "MATH_ONLIST_OPERATOR_MAX": "Maximalwert einer Liste", + "MATH_ONLIST_TOOLTIP_MAX": "Ist der gr\u00f6sste Wert in einer Liste.", + "MATH_ONLIST_OPERATOR_AVERAGE": "Mittelwert einer Liste", + "MATH_ONLIST_TOOLTIP_AVERAGE": "Ist der Durchschnittswert aller Werte in einer Liste.", + "MATH_ONLIST_OPERATOR_MEDIAN": "Median einer Liste", + "MATH_ONLIST_TOOLTIP_MEDIAN": "Ist der Zentralwert aller Werte in einer Liste.", + "MATH_ONLIST_OPERATOR_MODE": "Modulo / Restwert einer Liste", + "MATH_ONLIST_TOOLTIP_MODE": "Findet den am h\u00e4ufigsten vorkommenden Wert in einer Liste. Falls kein Wert \u00f6fter vorkomme als alle anderen, wird die originale Liste zur\u00fcckgegen", + "MATH_ONLIST_OPERATOR_STD_DEV": "Standart Abweichung einer Liste", + "MATH_ONLIST_TOOLTIP_STD_DEV": "Ist die standartiesierte Standartabweichung aller Werte in der Liste", + "MATH_ONLIST_OPERATOR_RANDOM": "Zufallswert einer Liste", + "MATH_ONLIST_TOOLTIP_RANDOM": "Gebe einen Zufallswert aus der Liste zur\u00fcck.", + "MATH_MODULO_HELPURL": "http://de.wikipedia.org/wiki/Modulo", + "MATH_MODULO_TITLE": "Rest von %1 \u00f7 %2", + "MATH_MODULO_TOOLTIP": "Der Rest nach einer Division.", + "MATH_CONSTRAIN_HELPURL": "http://en.wikipedia.org/wiki/Clamping_%28graphics%29", + "MATH_CONSTRAIN_TITLE": "begrenzen %1 von %2 bis %3", + "MATH_CONSTRAIN_TOOLTIP": "Begrenzt den Wertebereich mittels von / bis Werte. (inklusiv)", + "MATH_RANDOM_INT_HELPURL": "http://de.wikipedia.org/wiki/Zufallszahlen", + "MATH_RANDOM_INT_TITLE": "ganzahliger Zufallswerte zwischen %1 bis %2", + "MATH_RANDOM_INT_TOOLTIP": "Erzeuge eine ganzahligen Zufallswert zwischen zwei Werten (inklusiv).", + "MATH_RANDOM_FLOAT_HELPURL": "http://de.wikipedia.org/wiki/Zufallszahlen", + "MATH_RANDOM_FLOAT_TITLE_RANDOM": "Zufallszahl (0.0 -1.0)", + "MATH_RANDOM_FLOAT_TOOLTIP": "Erzeuge eine Zufallszahl zwischen 0.0 (inklusiv) und 1.0 (exklusiv).", + "TEXT_TEXT_HELPURL": "http://de.wikipedia.org/wiki/Zeichenkette", + "TEXT_TEXT_TOOLTIP": "Ein Buchstabe, Text oder Satz.", + "TEXT_JOIN_HELPURL": "", + "TEXT_JOIN_TITLE_CREATEWITH": "Erstelle Text aus", + "TEXT_JOIN_TOOLTIP": "Erstellt einen Text durch das verbinden von mehreren Textelementen.", + "TEXT_CREATE_JOIN_TITLE_JOIN": "verbinden", + "TEXT_CREATE_JOIN_TOOLTIP": "Hinzuf\u00fcgen, entfernen und sortieren von Elementen.", + "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Ein Element zum Text hinzuf\u00fcgen.", + "TEXT_APPEND_HELPURL": "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html", + "TEXT_APPEND_TO": "An", + "TEXT_APPEND_APPENDTEXT": "Text anh\u00e4ngen", + "TEXT_APPEND_TOOLTIP": "Text an die Variable \"%1\" anh\u00e4ngen.", + "TEXT_LENGTH_HELPURL": "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html", + "TEXT_LENGTH_TITLE": "l\u00e4nge %1", + "TEXT_LENGTH_TOOLTIP": "Die Anzahl von Zeichen in einem Textes. (inkl. Leerzeichen)", + "TEXT_ISEMPTY_HELPURL": "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html", + "TEXT_ISEMPTY_TITLE": "%1 ist leer?", + "TEXT_ISEMPTY_TOOLTIP": "Ist wahr (true), wenn der Text leer ist.", + "TEXT_INDEXOF_HELPURL": "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm", + "TEXT_INDEXOF_TOOLTIP": "Findest das erste / letzte Vorkommniss eines cuchbegriffes in einem Text. Gibt die Position des Begriffes oder 0 zur\u00fcck.", + "TEXT_INDEXOF_INPUT_INTEXT": "im Text", + "TEXT_INDEXOF_OPERATOR_FIRST": "Suche erstes Vorkommniss des Begriff", + "TEXT_INDEXOF_OPERATOR_LAST": "Suche letztes Vorkommniss des Begriff", + "TEXT_INDEXOF_TAIL": "", + "TEXT_CHARAT_HELPURL": "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm", + "TEXT_CHARAT_INPUT_INTEXT": "vom Text", + "TEXT_CHARAT_FROM_START": "Nehme Buchstabe #ten", + "TEXT_CHARAT_FROM_END": "Nehme #te Buchstabe von hinten", + "TEXT_CHARAT_FIRST": "Nehme ersten Buchstabe", + "TEXT_CHARAT_LAST": "Nehme letzten Buchstabe", + "TEXT_CHARAT_RANDOM": "Nehme zuf\u00e4lligen Buchstabe", + "TEXT_CHARAT_TAIL": "", + "TEXT_CHARAT_TOOLTIP": "Extrahiere einen Buchstaben von einer spezifizierten Position.", + "TEXT_GET_SUBSTRING_TOOLTIP": "Returns a specified portion of the text.", + "TEXT_GET_SUBSTRING_HELPURL": "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm", + "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "in Text", + "TEXT_GET_SUBSTRING_START_FROM_START": "Buchstabe #ten", + "TEXT_GET_SUBSTRING_START_FROM_END": "#te Buchstabe von hinten", + "TEXT_GET_SUBSTRING_START_FIRST": "ersten Buchstabe", + "TEXT_GET_SUBSTRING_END_FROM_START": "bis Buchstabe #ten", + "TEXT_GET_SUBSTRING_END_FROM_END": "bis #te Buchstabe von hinten", + "TEXT_GET_SUBSTRING_END_LAST": "bis letzten Buchstabe", + "TEXT_GET_SUBSTRING_TAIL": "", + "TEXT_CHANGECASE_HELPURL": "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html", + "TEXT_CHANGECASE_TOOLTIP": "Wandelt Schreibweise von Texten um, in Grossbuchstaben, Kleinbuchstaben oder den ersten Buchstaben jedes Wortes gross und die anderen klein.", + "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "umwandeln in GROSSBUCHSTABEN", + "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "umwandeln in kleinbuchstaben", + "TEXT_CHANGECASE_OPERATOR_TITLECASE": "umwandeln in W\u00f6rter", + "TEXT_TRIM_HELPURL": "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html", + "TEXT_TRIM_TOOLTIP": "Entfernt Leerzeichen vom Anfang und / oder Ende eines Textes.", + "TEXT_TRIM_OPERATOR_BOTH": "entferne Leerzeichen von Anfang und Ende Seiten", + "TEXT_TRIM_OPERATOR_LEFT": "entferne Leerzeichen von Anfang Seite", + "TEXT_TRIM_OPERATOR_RIGHT": "entferne Leerzeichen von Ende Seite", + "TEXT_PRINT_HELPURL": "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html", + "TEXT_PRINT_TITLE": "Ausgabe %1", + "TEXT_PRINT_TOOLTIP": "Gib den Inhalt einer Variable aus.", + "TEXT_PROMPT_HELPURL": "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode92.html", + "TEXT_PROMPT_TYPE_TEXT": "Fragt nach Text mit Hinweis", + "TEXT_PROMPT_TYPE_NUMBER": "Fragt nach Zahl mit Hinweis", + "TEXT_PROMPT_TOOLTIP_NUMBER": "Fragt den Benutzer nach ein Zahl.", + "TEXT_PROMPT_TOOLTIP_TEXT": "Fragt den Benutzer nach einem Text.", + "LISTS_CREATE_EMPTY_HELPURL": "http://en.wikipedia.org/wiki/Linked_list#Empty_lists", + "LISTS_CREATE_EMPTY_TITLE": "Erzeuge eine leere Liste", + "LISTS_CREATE_EMPTY_TOOLTIP": "Erzeugt eine leere Liste ohne Inhalt.", + "LISTS_CREATE_WITH_TOOLTIP": "Erzeugt eine List mit konfigurierten Elementen.", + "LISTS_CREATE_WITH_INPUT_WITH": "Erzeuge Liste mit", + "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "Liste", + "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Hinzuf\u00fcgen, entfernen und sortieren von Elementen.", + "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Ein Element zur Liste hinzuf\u00fcgen.", + "LISTS_REPEAT_HELPURL": "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm", + "LISTS_REPEAT_TOOLTIP": "Erzeugt eine Liste mit einer variablen Anzahl von Elementen", + "LISTS_REPEAT_TITLE": "Erzeuge Liste mit Element %1 wiederhole es %2 mal", + "LISTS_LENGTH_HELPURL": "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html", + "LISTS_LENGTH_TITLE": "l\u00e4nge %1", + "LISTS_LENGTH_TOOLTIP": "Die Anzahl von Elementen in der Liste.", + "LISTS_IS_EMPTY_HELPURL": "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html", + "LISTS_IS_EMPTY_TITLE": "%1 ist leer?", + "LISTS_TOOLTIP": "Ist wahr (true), wenn die Liste leer ist.", + "LISTS_INLIST": "in der Liste", + "LISTS_INDEX_OF_HELPURL": "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm", + "LISTS_INDEX_OF_FIRST": "Suche erstes Vorkommniss", + "LISTS_INDEX_OF_LAST": "Suche letztes Vorkommniss", + "LISTS_INDEX_OF_TOOLTIP": "Sucht die Position (index) eines Elementes in der Liste Gibt 0 zur\u00fcck wenn nichts gefunden wurde.", + "LISTS_GET_INDEX_GET": "Nehme", + "LISTS_GET_INDEX_GET_REMOVE": "Nehme und entferne", + "LISTS_GET_INDEX_REMOVE": "Entferne", + "LISTS_GET_INDEX_FROM_START": "#te", + "LISTS_GET_INDEX_FROM_END": "#te von hinten", + "LISTS_GET_INDEX_FIRST": "erste", + "LISTS_GET_INDEX_LAST": "letzte", + "LISTS_GET_INDEX_RANDOM": "zuf\u00e4lliges", + "LISTS_GET_INDEX_TAIL": "", + "LISTS_GET_INDEX_TOOLTIP_GET_FROM_START": "Extrahiere das #1te Element von der Liste.", + "LISTS_GET_INDEX_TOOLTIP_GET_FROM_END": "Extrahiere das #1te Element vom Ende der Liste.", + "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Extrahiere das erste Element von der Liste.", + "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Extrahiere das letzte Element von der Liste.", + "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Extrahiere ein zuf\u00e4lliges Element von der Liste.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START": "Extrahiere und entfernt das #1te Element von der Liste.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END": "Extrahiere und entfernt das #1te Element vom Ende der Liste.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Extrahiere und entfernt das erste Element von der Liste.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Extrahiere und entfernt das letzte Element von der Liste.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Extrahiere und entfernt ein zuf\u00e4lliges Element von der Liste.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START": "Entfernt das #1te Element von der Liste.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END": "Entfernt das #1te Element vom Ende der Liste.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Entfernt das erste Element von der Liste.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Entfernt das letzte Element von der Liste.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Entfernt ein zuf\u00e4lliges Element von der Liste.", + "LISTS_SET_INDEX_HELPURL": "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm", + "LISTS_SET_INDEX_SET": "set", + "LISTS_SET_INDEX_INSERT": "insert", + "LISTS_SET_INDEX_INPUT_TO": "auf", + "LISTS_SET_INDEX_TOOLTIP_SET_FROM_START": "Sets the item at the specified position in a list. #1 is the first item.", + "LISTS_SET_INDEX_TOOLTIP_SET_FROM_END": "Sets the item at the specified position in a list. #1 is the last item.", + "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Sets the first item in a list.", + "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Sets the last item in a list.", + "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Sets a random item in a list.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START": "Inserts the item at the specified position in a list. #1 is the first item.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END": "Inserts the item at the specified position in a list. #1 is the last item.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Inserts the item at the start of a list.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Append the item to the end of a list.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Inserts the item randomly in a list.", + "LISTS_GET_SUBLIST_HELPURL": "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm", + "LISTS_GET_SUBLIST_START_FROM_START": "erhalte Unterliste von #", + "LISTS_GET_SUBLIST_START_FROM_END": "erhalte Unterliste von # vom Ende", + "LISTS_GET_SUBLIST_START_FIRST": "erhalte Unterliste vom Ersten", + "LISTS_GET_SUBLIST_END_FROM_START": "zu #", + "LISTS_GET_SUBLIST_END_FROM_END": "zu # vom Ende", + "LISTS_GET_SUBLIST_END_LAST": "zum Letzten", + "LISTS_GET_SUBLIST_TAIL": "", + "LISTS_GET_SUBLIST_TOOLTIP": "Creates a copy of the specified portion of a list.", + "ORDINAL_NUMBER_SUFFIX": "", + "VARIABLES_GET_HELPURL": "http://de.wikipedia.org/wiki/Variable_%28Programmierung%29", + "VARIABLES_GET_TITLE": "", + "VARIABLES_GET_TAIL": "", + "VARIABLES_GET_TOOLTIP": "Gibt den Wert der Variable zur\u00fcck.", + "VARIABLES_GET_CREATE_SET": "Erzeuge \"Schreibe %1\"", + "VARIABLES_SET_HELPURL": "http://de.wikipedia.org/wiki/Variable_%28Programmierung%29", + "VARIABLES_SET_TITLE": "Schreibe", + "VARIABLES_SET_TAIL": "", + "VARIABLES_SET_TOOLTIP": "Setzt den Wert einer Variable.", + "VARIABLES_SET_CREATE_GET": "Erzeuge \"Lese %1\"", + "PROCEDURES_DEFNORETURN_HELPURL": "http://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29", + "PROCEDURES_DEFNORETURN_TITLE": "to", + "PROCEDURES_DEFNORETURN_PROCEDURE": "Funktionsblock", + "PROCEDURES_BEFORE_PARAMS": "mit:", + "PROCEDURES_DEFNORETURN_DO": "", + "PROCEDURES_DEFNORETURN_TOOLTIP": "Ein Funktionsblock ohne R\u00fcckgabewert.", + "PROCEDURES_DEFRETURN_HELPURL": "http://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29", + "PROCEDURES_DEFRETURN_RETURN": "gebe zur\u00fcck", + "PROCEDURES_DEFRETURN_TOOLTIP": "Ein Funktionsblock mit R\u00fcckgabewert.", + "PROCEDURES_DEF_DUPLICATE_WARNING": "Warnung: dieser Funktionsblock hat doppelte Parameter.", + "PROCEDURES_CALLNORETURN_HELPURL": "http://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29", + "PROCEDURES_CALLNORETURN_CALL": "", + "PROCEDURES_CALLNORETURN_TOOLTIP": "Rufe einen Funktionsblock ohne R\u00fcckgabewert auf.", + "PROCEDURES_CALLRETURN_HELPURL": "http://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29", + "PROCEDURES_CALLRETURN_TOOLTIP": "Rufe einen Funktionsblock mit R\u00fcckgabewert auf.", + "PROCEDURES_MUTATORCONTAINER_TITLE": "Parameter", + "PROCEDURES_MUTATORARG_TITLE": "Variable:", + "PROCEDURES_HIGHLIGHT_DEF": "Markiere Funktionsblock", + "PROCEDURES_CREATE_DO": "Erzeuge \"Aufruf %1\"", + "PROCEDURES_IFRETURN_TOOLTIP": "Wenn der erste Wert wahr (true) ist, Gebe den zweiten Wert zur\u00fcck.", + "PROCEDURES_IFRETURN_WARNING": "Warnung: Dieser Block darf nur innerhalb eines Funktionsblock genutzt werden." +} \ No newline at end of file diff --git a/msg/json/en.json b/msg/json/en.json new file mode 100644 index 000000000..91db9e3d8 --- /dev/null +++ b/msg/json/en.json @@ -0,0 +1,355 @@ +{ + "@metadata": { + "author": "Ellen Spertus ", + "lastupdated": "2013-10-29 15:38:17.903692", + "locale": "en", + "messagedocumentation" : "qqq" + }, + "VARIABLES_DEFAULT_NAME": "item", + "DUPLICATE_BLOCK": "Duplicate", + "ADD_COMMENT": "Add Comment", + "REMOVE_COMMENT": "Remove Comment", + "EXTERNAL_INPUTS": "External Inputs", + "INLINE_INPUTS": "Inline Inputs", + "DELETE_BLOCK": "Delete Block", + "DELETE_X_BLOCKS": "Delete %1 Blocks", + "COLLAPSE_BLOCK": "Collapse Block", + "COLLAPSE_ALL": "Collapse Blocks", + "EXPAND_BLOCK": "Expand Block", + "EXPAND_ALL": "Expand Blocks", + "DISABLE_BLOCK": "Disable Block", + "ENABLE_BLOCK": "Enable Block", + "HELP": "Help", + "CHANGE_VALUE_TITLE": "Change value:", + "NEW_VARIABLE": "New variable...", + "NEW_VARIABLE_TITLE": "New variable name:", + "RENAME_VARIABLE": "Rename variable...", + "RENAME_VARIABLE_TITLE": "Rename all '%1' variables to:", + "COLOUR_PICKER_HELPURL": "http://en.wikipedia.org/wiki/Color", + "COLOUR_PICKER_TOOLTIP": "Choose a colour from the palette.", + "COLOUR_RANDOM_HELPURL": "http://randomcolour.com", + "COLOUR_RANDOM_TITLE": "random colour", + "COLOUR_RANDOM_TOOLTIP": "Choose a colour at random.", + "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", + "COLOUR_RGB_TITLE": "colour with", + "COLOUR_RGB_RED": "red", + "COLOUR_RGB_GREEN": "green", + "COLOUR_RGB_BLUE": "blue", + "COLOUR_RGB_TOOLTIP": "Create a colour with the specified amount of red, green, and blue. All values must be between 0 and 100.", + "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", + "COLOUR_BLEND_TITLE": "blend", + "COLOUR_BLEND_COLOUR1": "colour 1", + "COLOUR_BLEND_COLOUR2": "colour 2", + "COLOUR_BLEND_RATIO": "ratio", + "COLOUR_BLEND_TOOLTIP": "Blends two colours together with a given ratio (0.0 - 1.0).", + "CONTROLS_REPEAT_HELPURL": "http://en.wikipedia.org/wiki/For_loop", + "CONTROLS_REPEAT_TITLE": "repeat %1 times", + "CONTROLS_REPEAT_TITLE_REPEAT": "repeat", + "CONTROLS_REPEAT_TITLE_TIMES": "times", + "CONTROLS_REPEAT_INPUT_DO": "do", + "CONTROLS_REPEAT_TOOLTIP": "Do some statements several times.", + "CONTROLS_WHILEUNTIL_HELPURL": "http://code.google.com/p/blockly/wiki/Repeat", + "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "repeat while", + "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "repeat until", + "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "While a value is true, then do some statements.", + "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "While a value is false, then do some statements.", + "CONTROLS_FOR_HELPURL": "https://code.google.com/p/blockly/wiki/Loops#count_with", + "CONTROLS_FOR_TOOLTIP": "Have the variable %1 take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks.", + "CONTROLS_FOR_INPUT_WITH": "count with", + "CONTROLS_FOR_INPUT_FROM_TO_BY": "from %1 to %2 by %3", + "CONTROLS_FOREACH_HELPURL": "https://code.google.com/p/blockly/wiki/Loops#for_each for each block", + "CONTROLS_FOREACH_INPUT_ITEM": "for each item", + "CONTROLS_FOREACH_INPUT_INLIST": "in list", + "CONTROLS_FOREACH_INPUT_INLIST_TAIL": "", + "CONTROLS_FOREACH_TOOLTIP": "For each item in a list, set the variable '%1' to the item, and then do some statements.", + "CONTROLS_FLOW_STATEMENTS_HELPURL": "https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "break out of loop", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "continue with next iteration of loop", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Break out of the containing loop.", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Skip the rest of this loop, and continue with the next iteration.", + "CONTROLS_FLOW_STATEMENTS_WARNING": "Warning: This block may only be used within a loop.", + "CONTROLS_IF_HELPURL": "http://code.google.com/p/blockly/wiki/If_Then", + "CONTROLS_IF_TOOLTIP_1": "If a value is true, then do some statements.", + "CONTROLS_IF_TOOLTIP_2": "If a value is true, then do the first block of statements. Otherwise, do the second block of statements.", + "CONTROLS_IF_TOOLTIP_3": "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements.", + "CONTROLS_IF_TOOLTIP_4": "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements. If none of the values are true, do the last block of statements.", + "CONTROLS_IF_MSG_IF": "if", + "CONTROLS_IF_MSG_ELSEIF": "else if", + "CONTROLS_IF_MSG_ELSE": "else", + "CONTROLS_IF_IF_TOOLTIP": "Add, remove, or reorder sections to reconfigure this if block.", + "CONTROLS_IF_ELSEIF_TOOLTIP": "Add a condition to the if block.", + "CONTROLS_IF_ELSE_TOOLTIP": "Add a final, catch-all condition to the if block.", + "LOGIC_COMPARE_HELPURL": "http://en.wikipedia.org/wiki/Inequality_(mathematics)", + "LOGIC_COMPARE_TOOLTIP_EQ": "Return true if both inputs equal each other.", + "LOGIC_COMPARE_TOOLTIP_NEQ": "Return true if both inputs are not equal to each other.", + "LOGIC_COMPARE_TOOLTIP_LT": "Return true if the first input is smaller than the second input.", + "LOGIC_COMPARE_TOOLTIP_LTE": "Return true if the first input is smaller than or equal to the second input.", + "LOGIC_COMPARE_TOOLTIP_GT": "Return true if the first input is greater than the second input.", + "LOGIC_COMPARE_TOOLTIP_GTE": "Return true if the first input is greater than or equal to the second input.", + "LOGIC_OPERATION_HELPURL": "http://code.google.com/p/blockly/wiki/And_Or", + "LOGIC_OPERATION_TOOLTIP_AND": "Return true if both inputs are true.", + "LOGIC_OPERATION_AND": "and", + "LOGIC_OPERATION_TOOLTIP_OR": "Return true if at least one of the inputs is true.", + "LOGIC_OPERATION_OR": "or", + "LOGIC_NEGATE_HELPURL": "http://code.google.com/p/blockly/wiki/Not", + "LOGIC_NEGATE_TITLE": "not %1", + "LOGIC_NEGATE_TOOLTIP": "Returns true if the input is false. Returns false if the input is true.", + "LOGIC_BOOLEAN_HELPURL": "http://code.google.com/p/blockly/wiki/True_False", + "LOGIC_BOOLEAN_TRUE": "true", + "LOGIC_BOOLEAN_FALSE": "false", + "LOGIC_BOOLEAN_TOOLTIP": "Returns either true or false.", + "LOGIC_NULL_HELPURL": "http://en.wikipedia.org/wiki/Nullable_type", + "LOGIC_NULL": "null", + "LOGIC_NULL_TOOLTIP": "Returns null.", + "LOGIC_TERNARY_HELPURL": "http://en.wikipedia.org/wiki/%3F:", + "LOGIC_TERNARY_CONDITION": "test", + "LOGIC_TERNARY_IF_TRUE": "if true", + "LOGIC_TERNARY_IF_FALSE": "if false", + "LOGIC_TERNARY_TOOLTIP": "Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value.", + "MATH_NUMBER_HELPURL": "http://en.wikipedia.org/wiki/Number", + "MATH_NUMBER_TOOLTIP": "A number.", + "MATH_ADDITION_SYMBOL": "+", + "MATH_SUBTRACTION_SYMBOL": "-", + "MATH_DIVISION_SYMBOL": "\u00F7", + "MATH_MULTIPLICATION_SYMBOL": "\u00D7", + "MATH_POWER_SYMBOL": "^", + "MATH_TRIG_SIN": "sin", + "MATH_TRIG_COS": "cos", + "MATH_TRIG_TAN": "tan", + "MATH_TRIG_ASIN": "asin", + "MATH_TRIG_ACOS": "acos", + "MATH_TRIG_ATAN": "atan", + "MATH_ARITHMETIC_HELPURL": "http://en.wikipedia.org/wiki/Arithmetic", + "MATH_ARITHMETIC_TOOLTIP_ADD": "Return the sum of the two numbers.", + "MATH_ARITHMETIC_TOOLTIP_MINUS": "Return the difference of the two numbers.", + "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Return the product of the two numbers.", + "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Return the quotient of the two numbers.", + "MATH_ARITHMETIC_TOOLTIP_POWER": "Return the first number raised to the power of the second number.", + "MATH_SINGLE_HELPURL": "http://en.wikipedia.org/wiki/Square_root", + "MATH_SINGLE_OP_ROOT": "square root", + "MATH_SINGLE_TOOLTIP_ROOT": "Return the square root of a number.", + "MATH_SINGLE_OP_ABSOLUTE": "absolute", + "MATH_SINGLE_TOOLTIP_ABS": "Return the absolute value of a number.", + "MATH_SINGLE_TOOLTIP_NEG": "Return the negation of a number.", + "MATH_SINGLE_TOOLTIP_LN": "Return the natural logarithm of a number.", + "MATH_SINGLE_TOOLTIP_LOG10": "Return the base 10 logarithm of a number.", + "MATH_SINGLE_TOOLTIP_EXP": "Return e to the power of a number.", + "MATH_SINGLE_TOOLTIP_POW10": "Return 10 to the power of a number.", + "MATH_TRIG_HELPURL": "http://en.wikipedia.org/wiki/Trigonometric_functions", + "MATH_TRIG_TOOLTIP_SIN": "Return the sine of a degree (not radian).", + "MATH_TRIG_TOOLTIP_COS": "Return the cosine of a degree (not radian).", + "MATH_TRIG_TOOLTIP_TAN": "Return the tangent of a degree (not radian).", + "MATH_TRIG_TOOLTIP_ASIN": "Return the arcsine of a number.", + "MATH_TRIG_TOOLTIP_ACOS": "Return the arccosine of a number.", + "MATH_TRIG_TOOLTIP_ATAN": "Return the arctangent of a number.", + "MATH_CONSTANT_HELPURL": "http://en.wikipedia.org/wiki/Mathematical_constant", + "MATH_CONSTANT_TOOLTIP": "Return one of the common constants: \u03c0 (3.141\u2026), e (2.718\u2026), \u03c6 (1.618\u2026), sqrt(2) (1.414\u2026), sqrt(\u00bd) (0.707\u2026), or \u221e (infinity).", + "MATH_IS_EVEN": "is even", + "MATH_IS_ODD": "is odd", + "MATH_IS_PRIME": "is prime", + "MATH_IS_WHOLE": "is whole", + "MATH_IS_POSITIVE": "is positive", + "MATH_IS_NEGATIVE": "is negative", + "MATH_IS_DIVISIBLE_BY": "is divisible by", + "MATH_IS_TOOLTIP": "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false.", + "MATH_CHANGE_HELPURL": "http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", + "MATH_CHANGE_TITLE_CHANGE": "change", + "MATH_CHANGE_INPUT_BY": "by", + "MATH_CHANGE_TOOLTIP": "Add a number to variable '%1'.", + "MATH_ROUND_HELPURL": "http://en.wikipedia.org/wiki/Rounding", + "MATH_ROUND_TOOLTIP": "Round a number up or down.", + "MATH_ROUND_OPERATOR_ROUND": "round", + "MATH_ROUND_OPERATOR_ROUNDUP": "round up", + "MATH_ROUND_OPERATOR_ROUNDDOWN": "round down", + "MATH_ONLIST_HELPURL": "", + "MATH_ONLIST_OPERATOR_SUM": "sum of list", + "MATH_ONLIST_TOOLTIP_SUM": "Return the sum of all the numbers in the list.", + "MATH_ONLIST_OPERATOR_MIN": "min of list", + "MATH_ONLIST_TOOLTIP_MIN": "Return the smallest number in the list.", + "MATH_ONLIST_OPERATOR_MAX": "max of list", + "MATH_ONLIST_TOOLTIP_MAX": "Return the largest number in the list.", + "MATH_ONLIST_OPERATOR_AVERAGE": "average of list", + "MATH_ONLIST_TOOLTIP_AVERAGE": "Return the average (arithmetic mean) of the numeric values in the list.", + "MATH_ONLIST_OPERATOR_MEDIAN": "median of list", + "MATH_ONLIST_TOOLTIP_MEDIAN": "Return the median number in the list.", + "MATH_ONLIST_OPERATOR_MODE": "modes of list", + "MATH_ONLIST_TOOLTIP_MODE": "Return a list of the most common item(s) in the list.", + "MATH_ONLIST_OPERATOR_STD_DEV": "standard deviation of list", + "MATH_ONLIST_TOOLTIP_STD_DEV": "Return the standard deviation of the list.", + "MATH_ONLIST_OPERATOR_RANDOM": "random item of list", + "MATH_ONLIST_TOOLTIP_RANDOM": "Return a random element from the list.", + "MATH_MODULO_HELPURL": "http://en.wikipedia.org/wiki/Modulo_operation", + "MATH_MODULO_TITLE": "remainder of %1 ÷ %2", + "MATH_MODULO_TOOLTIP": "Return the remainder from dividing the two numbers.", + "MATH_CONSTRAIN_HELPURL": "http://en.wikipedia.org/wiki/Clamping_%28graphics%29", + "MATH_CONSTRAIN_TITLE": "constrain %1 low %2 high %3", + "MATH_CONSTRAIN_TOOLTIP": "Constrain a number to be between the specified limits (inclusive).", + "MATH_RANDOM_INT_HELPURL": "http://en.wikipedia.org/wiki/Random_number_generation", + "MATH_RANDOM_INT_TITLE": "random integer from %1 to %2", + "MATH_RANDOM_INT_TOOLTIP": "Return a random integer between the two specified limits, inclusive.", + "MATH_RANDOM_FLOAT_HELPURL": "http://en.wikipedia.org/wiki/Random_number_generation", + "MATH_RANDOM_FLOAT_TITLE_RANDOM": "random fraction", + "MATH_RANDOM_FLOAT_TOOLTIP": "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive).", + "TEXT_TEXT_HELPURL": "http://en.wikipedia.org/wiki/String_(computer_science)", + "TEXT_TEXT_TOOLTIP": "A letter, word, or line of text.", + "TEXT_JOIN_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Text_creation", + "TEXT_JOIN_TITLE_CREATEWITH": "create text with", + "TEXT_JOIN_TOOLTIP": "Create a piece of text by joining together any number of items.", + "TEXT_CREATE_JOIN_TITLE_JOIN": "join", + "TEXT_CREATE_JOIN_TOOLTIP": "Add, remove, or reorder sections to reconfigure this text block.", + "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Add an item to the text.", + "TEXT_APPEND_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Text_modification", + "TEXT_APPEND_TO": "to", + "TEXT_APPEND_APPENDTEXT": "append text", + "TEXT_APPEND_TOOLTIP": "Append some text to variable '%1'.", + "TEXT_LENGTH_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Text_modification", + "TEXT_LENGTH_TITLE": "length of %1", + "TEXT_LENGTH_TOOLTIP": "Returns the number of letters (including spaces) in the provided text.", + "TEXT_ISEMPTY_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text", + "TEXT_ISEMPTY_TITLE": "%1 is empty", + "TEXT_ISEMPTY_TOOLTIP": "Returns true if the provided text is empty.", + "TEXT_INDEXOF_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Finding_text", + "TEXT_INDEXOF_TOOLTIP": "Returns the index of the first/last occurrence of first text in the second text. Returns 0 if text is not found.", + "TEXT_INDEXOF_INPUT_INTEXT": "in text", + "TEXT_INDEXOF_OPERATOR_FIRST": "find first occurrence of text", + "TEXT_INDEXOF_OPERATOR_LAST": "find last occurrence of text", + "TEXT_INDEXOF_TAIL": "", + "TEXT_CHARAT_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Extracting_text", + "TEXT_CHARAT_INPUT_INTEXT": "in text", + "TEXT_CHARAT_FROM_START": "get letter #", + "TEXT_CHARAT_FROM_END": "get letter # from end", + "TEXT_CHARAT_FIRST": "get first letter", + "TEXT_CHARAT_LAST": "get last letter", + "TEXT_CHARAT_RANDOM": "get random letter", + "TEXT_CHARAT_TAIL": "", + "TEXT_CHARAT_TOOLTIP": "Returns the letter at the specified position.", + "TEXT_GET_SUBSTRING_TOOLTIP": "Returns a specified portion of the text.", + "TEXT_GET_SUBSTRING_HELPURL": "http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text", + "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "in text", + "TEXT_GET_SUBSTRING_START_FROM_START": "get substring from letter #", + "TEXT_GET_SUBSTRING_START_FROM_END": "get substring from letter # from end", + "TEXT_GET_SUBSTRING_START_FIRST": "get substring from first letter", + "TEXT_GET_SUBSTRING_END_FROM_START": "to letter #", + "TEXT_GET_SUBSTRING_END_FROM_END": "to letter # from end", + "TEXT_GET_SUBSTRING_END_LAST": "to last letter", + "TEXT_GET_SUBSTRING_TAIL": "", + "TEXT_CHANGECASE_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case", + "TEXT_CHANGECASE_TOOLTIP": "Return a copy of the text in a different case.", + "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "to UPPER CASE", + "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "to lower case", + "TEXT_CHANGECASE_OPERATOR_TITLECASE": "to Title Case", + "TEXT_TRIM_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces", + "TEXT_TRIM_TOOLTIP": "Return a copy of the text with spaces removed from one or both ends.", + "TEXT_TRIM_OPERATOR_BOTH": "trim spaces from both sides", + "TEXT_TRIM_OPERATOR_LEFT": "trim spaces from left side", + "TEXT_TRIM_OPERATOR_RIGHT": "trim spaces from right side", + "TEXT_PRINT_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Printing_text", + "TEXT_PRINT_TITLE": "print %1", + "TEXT_PRINT_TOOLTIP": "Print the specified text, number or other value.", + "TEXT_PROMPT_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user", + "TEXT_PROMPT_TYPE_TEXT": "prompt for text with message", + "TEXT_PROMPT_TYPE_NUMBER": "prompt for number with message", + "TEXT_PROMPT_TOOLTIP_NUMBER": "Prompt for user for a number.", + "TEXT_PROMPT_TOOLTIP_TEXT": "Prompt for user for some text.", + "LISTS_CREATE_EMPTY_HELPURL": "http://en.wikipedia.org/wiki/Linked_list#Empty_lists", + "LISTS_CREATE_EMPTY_TITLE": "create empty list", + "LISTS_CREATE_EMPTY_TOOLTIP": "Returns a list, of length 0, containing no data records", + "LISTS_CREATE_WITH_TOOLTIP": "Create a list with any number of items.", + "LISTS_CREATE_WITH_INPUT_WITH": "create list with", + "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "list", + "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Add, remove, or reorder sections to reconfigure this list block.", + "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Add an item to the list.", + "LISTS_REPEAT_HELPURL": "https://code.google.com/p/blockly/wiki/Lists#create_list_with", + "LISTS_REPEAT_TOOLTIP": "Creates a list consisting of the given value repeated the specified number of times.", + "LISTS_REPEAT_TITLE": "create list with item %1 repeated %2 times", + "LISTS_LENGTH_HELPURL": "https://code.google.com/p/blockly/wiki/Lists#length_of", + "LISTS_LENGTH_TITLE": "length of %1", + "LISTS_LENGTH_TOOLTIP": "Returns the length of a list.", + "LISTS_IS_EMPTY_HELPURL": "https://code.google.com/p/blockly/wiki/Lists#is_empty", + "LISTS_IS_EMPTY_TITLE": "%1 is empty", + "LISTS_TOOLTIP": "Returns true if the list is empty.", + "LISTS_INLIST": "in list", + "LISTS_INDEX_OF_HELPURL": "https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List", + "LISTS_INDEX_OF_FIRST": "find first occurrence of item", + "LISTS_INDEX_OF_LAST": "find last occurrence of item", + "LISTS_INDEX_OF_TOOLTIP": "Returns the index of the first/last occurrence of the item in the list. Returns 0 if text is not found.", + "LISTS_GET_INDEX_GET": "get", + "LISTS_GET_INDEX_GET_REMOVE": "get and remove", + "LISTS_GET_INDEX_REMOVE": "remove", + "LISTS_GET_INDEX_FROM_START": "#", + "LISTS_GET_INDEX_FROM_END": "# from end", + "LISTS_GET_INDEX_FIRST": "first", + "LISTS_GET_INDEX_LAST": "last", + "LISTS_GET_INDEX_RANDOM": "random", + "LISTS_GET_INDEX_TAIL": "", + "LISTS_GET_INDEX_TOOLTIP_GET_FROM_START": "Returns the item at the specified position in a list. #1 is the first item.", + "LISTS_GET_INDEX_TOOLTIP_GET_FROM_END": "Returns the item at the specified position in a list. #1 is the last item.", + "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Returns the first item in a list.", + "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Returns the last item in a list.", + "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Returns a random item in a list.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START": "Removes and returns the item at the specified position in a list. #1 is the first item.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END": "Removes and returns the item at the specified position in a list. #1 is the last item.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Removes and returns the first item in a list.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Removes and returns the last item in a list.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Removes and returns a random item in a list.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START": "Removes the item at the specified position in a list. #1 is the first item.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END": "Removes the item at the specified position in a list. #1 is the last item.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Removes the first item in a list.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Removes the last item in a list.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Removes a random item in a list.", + "LISTS_SET_INDEX_HELPURL": "https://code.google.com/p/blockly/wiki/Lists#in_list_..._set", + "LISTS_SET_INDEX_SET": "set", + "LISTS_SET_INDEX_INSERT": "insert at", + "LISTS_SET_INDEX_INPUT_TO": "as", + "LISTS_SET_INDEX_TOOLTIP_SET_FROM_START": "Sets the item at the specified position in a list. #1 is the first item.", + "LISTS_SET_INDEX_TOOLTIP_SET_FROM_END": "Sets the item at the specified position in a list. #1 is the last item.", + "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Sets the first item in a list.", + "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Sets the last item in a list.", + "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Sets a random item in a list.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START": "Inserts the item at the specified position in a list. #1 is the first item.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END": "Inserts the item at the specified position in a list. #1 is the last item.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Inserts the item at the start of a list.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Append the item to the end of a list.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Inserts the item randomly in a list.", + "LISTS_GET_SUBLIST_HELPURL": "https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist", + "LISTS_GET_SUBLIST_START_FROM_START": "get sub-list from #", + "LISTS_GET_SUBLIST_START_FROM_END": "get sub-list from # from end", + "LISTS_GET_SUBLIST_START_FIRST": "get sub-list from first", + "LISTS_GET_SUBLIST_END_FROM_START": "to #", + "LISTS_GET_SUBLIST_END_FROM_END": "to # from end", + "LISTS_GET_SUBLIST_END_LAST": "to last", + "LISTS_GET_SUBLIST_TAIL": "", + "LISTS_GET_SUBLIST_TOOLTIP": "Creates a copy of the specified portion of a list.", + "ORDINAL_NUMBER_SUFFIX": "", + "VARIABLES_GET_HELPURL": "http://code.google.com/p/blockly/wiki/Variables#Get", + "VARIABLES_GET_TITLE": "", + "VARIABLES_GET_TAIL": "", + "VARIABLES_GET_TOOLTIP": "Returns the value of this variable.", + "VARIABLES_GET_CREATE_SET": "Create 'set %1'", + "VARIABLES_SET_HELPURL": "http://code.google.com/p/blockly/wiki/Variables#Set", + "VARIABLES_SET_TITLE": "set", + "VARIABLES_SET_TAIL": "to", + "VARIABLES_SET_TOOLTIP": "Sets this variable to be equal to the input.", + "VARIABLES_SET_CREATE_GET": "Create 'get %1'", + "PROCEDURES_DEFNORETURN_HELPURL": "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29", + "PROCEDURES_DEFNORETURN_TITLE": "to", + "PROCEDURES_DEFNORETURN_PROCEDURE": "do something", + "PROCEDURES_BEFORE_PARAMS": "with:", + "PROCEDURES_DEFNORETURN_DO": "", + "PROCEDURES_DEFNORETURN_TOOLTIP": "Creates a function with no output.", + "PROCEDURES_DEFRETURN_HELPURL": "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29", + "PROCEDURES_DEFRETURN_RETURN": "return", + "PROCEDURES_DEFRETURN_TOOLTIP": "Creates a function with an output.", + "PROCEDURES_DEF_DUPLICATE_WARNING": "Warning: This function has duplicate parameters.", + "PROCEDURES_CALLNORETURN_HELPURL": "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29", + "PROCEDURES_CALLNORETURN_CALL": "", + "PROCEDURES_CALLNORETURN_TOOLTIP": "Run the user-defined function '%1'.", + "PROCEDURES_CALLRETURN_HELPURL": "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29", + "PROCEDURES_CALLRETURN_TOOLTIP": "Run the user-defined function '%1' and use its output.", + "PROCEDURES_MUTATORCONTAINER_TITLE": "inputs", + "PROCEDURES_MUTATORARG_TITLE": "input name:", + "PROCEDURES_HIGHLIGHT_DEF": "Highlight function definition", + "PROCEDURES_CREATE_DO": "Create '%1'", + "PROCEDURES_IFRETURN_TOOLTIP": "If a value is true, then return a second value.", + "PROCEDURES_IFRETURN_WARNING": "Warning: This block may be used only within a function definition." +} diff --git a/msg/json/es.json b/msg/json/es.json new file mode 100644 index 000000000..d9dbb34ac --- /dev/null +++ b/msg/json/es.json @@ -0,0 +1,294 @@ +{ + "@metadata": { + "authors": [ + "Fitoschido", + "VegaDark" + ] + }, + "VARIABLES_DEFAULT_NAME": "elemento", + "DUPLICATE_BLOCK": "Duplicar", + "ADD_COMMENT": "A\u00f1adir comentario", + "REMOVE_COMMENT": "Eliminar comentario", + "EXTERNAL_INPUTS": "Entradas externas", + "INLINE_INPUTS": "Entradas en l\u00ednea", + "DELETE_BLOCK": "Eliminar bloque", + "DELETE_X_BLOCKS": "Eliminar %1 bloques", + "COLLAPSE_BLOCK": "Contraer bloque", + "COLLAPSE_ALL": "Contraer bloques", + "EXPAND_BLOCK": "Expandir bloque", + "EXPAND_ALL": "Expandir bloques", + "DISABLE_BLOCK": "Desactivr bloque", + "ENABLE_BLOCK": "Activar bloque", + "HELP": "Ayuda", + "CHANGE_VALUE_TITLE": "Cambiar el valor:", + "NEW_VARIABLE": "Variable nueva\u2026", + "NEW_VARIABLE_TITLE": "Nombre de variable nueva:", + "RENAME_VARIABLE": "Renombrar la variable\u2026", + "RENAME_VARIABLE_TITLE": "Renombrar todas las variables \u00ab%1\u00bb a:", + "COLOUR_PICKER_HELPURL": "http://es.wikipedia.org/wiki/Color", + "COLOUR_PICKER_TOOLTIP": "Elige un color de la paleta.", + "COLOUR_RANDOM_TITLE": "color aleatorio", + "COLOUR_RANDOM_TOOLTIP": "Elige un color al azar.", + "COLOUR_RGB_TITLE": "color con", + "COLOUR_RGB_RED": "rojo", + "COLOUR_RGB_GREEN": "verde", + "COLOUR_RGB_BLUE": "azul", + "COLOUR_RGB_TOOLTIP": "Crea un color con cantidades espec\u00edficas de rojo, verde y azul. Todos los valores deben encontrarse entre 0 y 100.", + "COLOUR_BLEND_TITLE": "combinar", + "COLOUR_BLEND_COLOUR1": "color 1", + "COLOUR_BLEND_COLOUR2": "color 2", + "COLOUR_BLEND_RATIO": "raz\u00f3n", + "COLOUR_BLEND_TOOLTIP": "Combina dos colores con una proporci\u00f3n determinada (0,0\u20131,0).", + "CONTROLS_REPEAT_HELPURL": "http://es.wikipedia.org/wiki/Bucle_for", + "CONTROLS_REPEAT_TITLE": "repetir %1 veces", + "CONTROLS_REPEAT_TITLE_REPEAT": "repetir", + "CONTROLS_REPEAT_TITLE_TIMES": "veces", + "CONTROLS_REPEAT_INPUT_DO": "haz", + "CONTROLS_REPEAT_TOOLTIP": "Hacer algunas declaraciones varias veces.", + "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "repetir mientras", + "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "repetir hasta", + "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Mientras que un valor es verdadero, entonces hacer algunas declaraciones.", + "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Mientras que un valor es falso, entonces hacer algunas declaraciones.", + "CONTROLS_FOR_TOOLTIP": "Tiene la variable %1 que toma los valores desde el n\u00famero de inicio hasta el n\u00famero final, contando por el intervalo especificado, y hacer los bloques especificados.", + "CONTROLS_FOR_INPUT_WITH": "contar con", + "CONTROLS_FOR_INPUT_FROM_TO_BY": "de %1 a %2 por %3", + "CONTROLS_FOREACH_INPUT_ITEM": "para cada elemento", + "CONTROLS_FOREACH_INPUT_INLIST": "en la lista", + "CONTROLS_FOREACH_TOOLTIP": "Para cada elemento en una lista, establece la variable '%1' en el elemento y luego hacer algunas declaraciones.", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "romper el bucle", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "continuar con la siguiente iteraci\u00f3n del bucle", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Rompe el que contiene el bucle.", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Saltar el resto de este bucle, y continuar con la siguiente iteraci\u00f3n.", + "CONTROLS_FLOW_STATEMENTS_WARNING": "ADVERTENCIA: Este bloque puede usarse s\u00f3lo dentro de un bucle.", + "CONTROLS_IF_TOOLTIP_1": "Si un valor es verdadero, entonces hacer algunas declaraciones.", + "CONTROLS_IF_TOOLTIP_2": "Si un valor es verdadero, entonces hacer el primer bloque de declaraciones. De lo contrario, hacer el segundo bloque de declaraciones.", + "CONTROLS_IF_TOOLTIP_3": "Si el primer valor es verdadero, entonces hacer el primer bloque de declaraciones. De lo contrario, si el segundo valor es verdadero, hacer el segundo bloque de declaraciones.", + "CONTROLS_IF_TOOLTIP_4": "Si el primer valor es verdadero, entonces hacer el primer bloque de declaraciones. De lo contrario, si el segundo valor es verdadero, hacer el segundo bloque de declaraciones. Si ninguno de los valores son verdaderos, hacer el \u00faltimo bloque de declaraciones.", + "CONTROLS_IF_MSG_IF": "si", + "CONTROLS_IF_MSG_ELSEIF": "o si", + "CONTROLS_IF_MSG_ELSE": "sino", + "CONTROLS_IF_IF_TOOLTIP": "Agregar, eliminar o reordenar las secciones para reconfigurar este bloque.", + "CONTROLS_IF_ELSEIF_TOOLTIP": "Agregar una condici\u00f3n a este bloque.", + "CONTROLS_IF_ELSE_TOOLTIP": "Agregar una condici\u00f3n general final a este bloque.", + "LOGIC_COMPARE_HELPURL": "http://es.wikipedia.org/wiki/Desigualdad_matem\u00e1tica", + "LOGIC_COMPARE_TOOLTIP_EQ": "Devolver verdadero si ambas entradas igualan unas a otras.", + "LOGIC_COMPARE_TOOLTIP_NEQ": "Devolver verdadero si ambas entradas no son iguales entre s\u00ed.", + "LOGIC_COMPARE_TOOLTIP_LT": "Devolver verdadero si la primera entrada es menor que la segunda entrada.", + "LOGIC_COMPARE_TOOLTIP_LTE": "Devolver verdadero si la primera entrada es menor que o igual a la segunda entrada.", + "LOGIC_COMPARE_TOOLTIP_GT": "Devolver verdadero si la primera entrada es mayor que la segunda entrada.", + "LOGIC_COMPARE_TOOLTIP_GTE": "Devolver verdadero si la primera entrada es mayor o igual a la segunda entrada.", + "LOGIC_OPERATION_TOOLTIP_AND": "Devolver verdadero si ambas entradas son verdaderas.", + "LOGIC_OPERATION_AND": "y", + "LOGIC_OPERATION_TOOLTIP_OR": "Devolver verdadero si al menos una de las entradas es verdadera.", + "LOGIC_OPERATION_OR": "o", + "LOGIC_NEGATE_TITLE": "no %1", + "LOGIC_NEGATE_TOOLTIP": "Devolver verdadero si la entrada es falsa. Devolver falso si la entrada es verdadera.", + "LOGIC_BOOLEAN_TRUE": "verdadero", + "LOGIC_BOOLEAN_FALSE": "falso", + "LOGIC_BOOLEAN_TOOLTIP": "Devuelve \u00abverdadero\u00bb o \u00abfalso\u00bb.", + "LOGIC_NULL": "nulo", + "LOGIC_NULL_TOOLTIP": "Devuelve \u00abnulo\u00bb.", + "LOGIC_TERNARY_CONDITION": "prueba", + "LOGIC_TERNARY_IF_TRUE": "si es verdadero", + "LOGIC_TERNARY_IF_FALSE": "si es falso", + "LOGIC_TERNARY_TOOLTIP": "Comprobar la condici\u00f3n en \"probar\". Si la condici\u00f3n es verdadera, devolver el valor \"si es cierto\"; de lo contrario, devolver el valor \"si es falso\".", + "MATH_NUMBER_HELPURL": "http://es.wikipedia.org/wiki/N\u00famero", + "MATH_NUMBER_TOOLTIP": "Un n\u00famero.", + "MATH_ARITHMETIC_HELPURL": "http://es.wikipedia.org/wiki/Aritm\u00e9tica", + "MATH_ARITHMETIC_TOOLTIP_ADD": "Devuelve la suma de ambos numeros.", + "MATH_ARITHMETIC_TOOLTIP_MINUS": "Devuelve la diferencia de ambos n\u00fameros.", + "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Devuelve el producto de ambos n\u00fameros.", + "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Devuelve el cociente de ambos n\u00fameros.", + "MATH_ARITHMETIC_TOOLTIP_POWER": "Devuelve el primer n\u00famero elevado a la potencia del segundo.", + "MATH_SINGLE_HELPURL": "https://es.wikipedia.org/wiki/Ra%C3%ADz_cuadrada", + "MATH_SINGLE_OP_ROOT": "ra\u00edz cuadrada", + "MATH_SINGLE_TOOLTIP_ROOT": "Devuelve la ra\u00edz cuadrada de un n\u00famero.", + "MATH_SINGLE_OP_ABSOLUTE": "absoluto", + "MATH_SINGLE_TOOLTIP_ABS": "Devuelve el valor absoluto de un n\u00famero.", + "MATH_SINGLE_TOOLTIP_NEG": "Devolver la negaci\u00f3n de un n\u00famero.", + "MATH_SINGLE_TOOLTIP_LN": "Devuelve el logaritmo natural de un n\u00famero.", + "MATH_SINGLE_TOOLTIP_LOG10": "Devuelve el logaritmo base 10 de un n\u00famero.", + "MATH_SINGLE_TOOLTIP_EXP": "Devuelve e a la potencia de un n\u00famero.", + "MATH_SINGLE_TOOLTIP_POW10": "Devuelve 10 a la potencia de un n\u00famero.", + "MATH_TRIG_HELPURL": "http://es.wikipedia.org/wiki/Funci\u00f3n_trigonom\u00e9trica", + "MATH_TRIG_TOOLTIP_SIN": "Devolver el seno de un grado (no radi\u00e1n).", + "MATH_TRIG_TOOLTIP_COS": "Devolver el coseno de un grado (no radi\u00e1n).", + "MATH_TRIG_TOOLTIP_TAN": "Devolver la tangente de un grado (no radi\u00e1n).", + "MATH_TRIG_TOOLTIP_ASIN": "Devolver el arcoseno de un n\u00famero.", + "MATH_TRIG_TOOLTIP_ACOS": "Devolver el arcocoseno de un n\u00famero.", + "MATH_TRIG_TOOLTIP_ATAN": "Devolver el arcotangente de un n\u00famero.", + "MATH_CONSTANT_HELPURL": "http://es.wikipedia.org/wiki/Anexo:Constantes_matem\u00e1ticas", + "MATH_CONSTANT_TOOLTIP": "Devolver una de las constantes comunes: \u03c0 (3.141\u2026), e (2.718\u2026), \u03c6 (1.618\u2026), sqrt(2) (1.414\u2026), sqrt(\u00bd) (0.707\u2026), o \u221e (infinito).", + "MATH_IS_EVEN": "es par", + "MATH_IS_ODD": "es impar", + "MATH_IS_PRIME": "es primo", + "MATH_IS_WHOLE": "es entero", + "MATH_IS_POSITIVE": "es positivo", + "MATH_IS_NEGATIVE": "es negativo", + "MATH_IS_DIVISIBLE_BY": "es divisible por", + "MATH_IS_TOOLTIP": "Comprobar si un n\u00famero es par, impar, primo, entero, positivo, negativo, o si es divisible por un n\u00famero determinado. Devuelve verdadero o falso.", + "MATH_CHANGE_TITLE_CHANGE": "cambiar", + "MATH_CHANGE_INPUT_BY": "por", + "MATH_CHANGE_TOOLTIP": "A\u00f1adir un n\u00famero a la variable \u00ab%1\u00bb.", + "MATH_ROUND_HELPURL": "http://es.wikipedia.org/wiki/Redondeo", + "MATH_ROUND_TOOLTIP": "Redondear un n\u00famero hacia arriba o hacia abajo.", + "MATH_ROUND_OPERATOR_ROUND": "redondear", + "MATH_ROUND_OPERATOR_ROUNDUP": "redondear m\u00e1s", + "MATH_ROUND_OPERATOR_ROUNDDOWN": "redondear menos", + "MATH_ONLIST_OPERATOR_SUM": "suma de la lista", + "MATH_ONLIST_TOOLTIP_SUM": "Devolver la suma de todos los n\u00fameros en la lista.", + "MATH_ONLIST_OPERATOR_MIN": "min de la lista", + "MATH_ONLIST_TOOLTIP_MIN": "Devolver el n\u00famero m\u00e1s peque\u00f1o en la lista.", + "MATH_ONLIST_OPERATOR_MAX": "max de la lista", + "MATH_ONLIST_TOOLTIP_MAX": "Devolver el n\u00famero m\u00e1s grande en la lista.", + "MATH_ONLIST_OPERATOR_AVERAGE": "promedio de la lista", + "MATH_ONLIST_TOOLTIP_AVERAGE": "Devolver el promedio (media aritm\u00e9tica) de los valores num\u00e9ricos en la lista.", + "MATH_ONLIST_OPERATOR_MEDIAN": "mediana de lista", + "MATH_ONLIST_TOOLTIP_MEDIAN": "Devolver la mediana en la lista.", + "MATH_ONLIST_OPERATOR_MODE": "modos de la lista", + "MATH_ONLIST_TOOLTIP_MODE": "Devolver una lista de los elementos m\u00e1s comunes en la lista.", + "MATH_ONLIST_OPERATOR_STD_DEV": "desviaci\u00f3n est\u00e1ndar de la lista", + "MATH_ONLIST_TOOLTIP_STD_DEV": "Devolver la desviaci\u00f3n est\u00e1ndar de la lista.", + "MATH_ONLIST_OPERATOR_RANDOM": "elemento aleatorio de la lista", + "MATH_ONLIST_TOOLTIP_RANDOM": "Devolver un elemento aleatorio de la lista.", + "MATH_MODULO_HELPURL": "http://en.wikipedia.org/wiki/Modulo_operation", + "MATH_MODULO_TITLE": "resultado de %1 \u00f7 %2", + "MATH_MODULO_TOOLTIP": "Devolver el resultado al dividir los dos n\u00fameros.", + "MATH_CONSTRAIN_TITLE": "limitar %1 bajo %2 alto %3", + "MATH_CONSTRAIN_TOOLTIP": "Limitar un n\u00famero entre los l\u00edmites especificados (inclusive).", + "MATH_RANDOM_INT_HELPURL": "http://es.wikipedia.org/wiki/Generador_de_n\u00fameros_aleatorios", + "MATH_RANDOM_INT_TITLE": "entero aleatorio de %1 a %2", + "MATH_RANDOM_INT_TOOLTIP": "Devolver un entero aleatorio entre los dos l\u00edmites especificados, inclusive.", + "MATH_RANDOM_FLOAT_HELPURL": "http://es.wikipedia.org/wiki/Generador_de_n\u00fameros_aleatorios", + "MATH_RANDOM_FLOAT_TITLE_RANDOM": "fracci\u00f3n aleatoria", + "MATH_RANDOM_FLOAT_TOOLTIP": "Devolver una fracci\u00f3n aleatoria entre 0,0 (ambos inclusive) y 1.0 (exclusivo).", + "TEXT_TEXT_HELPURL": "http://es.wikipedia.org/wiki/Cadena_de_caracteres", + "TEXT_TEXT_TOOLTIP": "Una letra, palabra o l\u00ednea de texto.", + "TEXT_JOIN_TITLE_CREATEWITH": "crear texto con", + "TEXT_JOIN_TOOLTIP": "Crear un fragmento de texto al unir cualquier n\u00famero de elementos.", + "TEXT_CREATE_JOIN_TITLE_JOIN": "unir", + "TEXT_CREATE_JOIN_TOOLTIP": "Agregar, eliminar o reordenar las secciones para reconfigurar este bloque de texto.", + "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Agregar un elemento al texto.", + "TEXT_APPEND_TO": "a", + "TEXT_APPEND_APPENDTEXT": "a\u00f1adir texto", + "TEXT_APPEND_TOOLTIP": "A\u00f1adir texto a la variable '%1'.", + "TEXT_LENGTH_TITLE": "longitud de %1", + "TEXT_LENGTH_TOOLTIP": "Devuelve el n\u00famero de letras (incluyendo espacios) en el texto proporcionado.", + "TEXT_ISEMPTY_TITLE": "%1 est\u00e1 vac\u00edo", + "TEXT_ISEMPTY_TOOLTIP": "Devuelve verdadero si el texto proporcionado est\u00e1 vac\u00edo.", + "TEXT_INDEXOF_TOOLTIP": "Devuelve el \u00edndice de la primera/\u00faltima aparici\u00f3n del primer texto en el segundo texto. Devuelve 0 si el texto no se encuentra.", + "TEXT_INDEXOF_INPUT_INTEXT": "en el texto", + "TEXT_INDEXOF_OPERATOR_FIRST": "encontrar la primera aparici\u00f3n del texto", + "TEXT_INDEXOF_OPERATOR_LAST": "encontrar la \u00faltima aparici\u00f3n del texto", + "TEXT_CHARAT_INPUT_INTEXT": "en el texto", + "TEXT_CHARAT_FROM_START": "obtener la letra #", + "TEXT_CHARAT_FROM_END": "obtener la letra # del final", + "TEXT_CHARAT_FIRST": "obtener la primera letra", + "TEXT_CHARAT_LAST": "obtener la \u00faltima letra", + "TEXT_CHARAT_RANDOM": "obtener letra aleatoria", + "TEXT_CHARAT_TOOLTIP": "Devuelve la letra a la posici\u00f3n especificada.", + "TEXT_GET_SUBSTRING_TOOLTIP": "Devuelve una porci\u00f3n determinada del texto.", + "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "en el texto", + "TEXT_GET_SUBSTRING_START_FROM_START": "obtener subcadena de la letra #", + "TEXT_GET_SUBSTRING_START_FROM_END": "obtener subcadena de la letra # del final", + "TEXT_GET_SUBSTRING_START_FIRST": "obtener subcadena de la primera letra", + "TEXT_GET_SUBSTRING_END_FROM_START": "a la letra #", + "TEXT_GET_SUBSTRING_END_FROM_END": "a la letra # del final", + "TEXT_GET_SUBSTRING_END_LAST": "a la \u00faltima letra", + "TEXT_CHANGECASE_TOOLTIP": "Devuelve una copia del texto en un caso diferente.", + "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "a may\u00fasculas", + "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "a min\u00fasculas", + "TEXT_CHANGECASE_OPERATOR_TITLECASE": "a may\u00fasculas cada palabra", + "TEXT_TRIM_TOOLTIP": "Devuelve una copia del texto con espacios retirados de uno o ambos extremos.", + "TEXT_TRIM_OPERATOR_BOTH": "recortar espacios de ambos lados", + "TEXT_TRIM_OPERATOR_LEFT": "recortar espacios del lado izquierdo", + "TEXT_TRIM_OPERATOR_RIGHT": "recortar espacios del lado derecho", + "TEXT_PRINT_TITLE": "imprimir %1", + "TEXT_PRINT_TOOLTIP": "Imprimir el texto especificado, n\u00famero u otro valor.", + "TEXT_PROMPT_TYPE_TEXT": "solicitar el texto con el mensaje", + "TEXT_PROMPT_TYPE_NUMBER": "solicitar el n\u00famero con el mensaje", + "TEXT_PROMPT_TOOLTIP_NUMBER": "Solicitar al usuario por un n\u00famero.", + "TEXT_PROMPT_TOOLTIP_TEXT": "Solicitar al usuario por un texto.", + "LISTS_CREATE_EMPTY_TITLE": "crear lista vac\u00eda", + "LISTS_CREATE_EMPTY_TOOLTIP": "Devuelve una lista, de longitud de 0, que no contenga ning\u00fan registro de datos", + "LISTS_CREATE_WITH_TOOLTIP": "Crear una lista con cualquier n\u00famero de elementos.", + "LISTS_CREATE_WITH_INPUT_WITH": "crear lista con", + "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "lista", + "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Agregar, eliminar o reorganizar las secciones para reconfigurar esta lista de bloques.", + "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Agregar un elemento a la lista.", + "LISTS_REPEAT_TOOLTIP": "Crea una lista que consta de un valor dado repetido el n\u00famero de veces especificado.", + "LISTS_REPEAT_TITLE": "crear lista con el elemento %1 repetido %2 veces", + "LISTS_LENGTH_TITLE": "longitud de %1", + "LISTS_LENGTH_TOOLTIP": "Devuelve la longitud de una lista.", + "LISTS_IS_EMPTY_TITLE": "%1 est\u00e1 vac\u00edo", + "LISTS_TOOLTIP": "Devuelve verdadero si la lista est\u00e1 vac\u00eda.", + "LISTS_INLIST": "en la lista", + "LISTS_INDEX_OF_FIRST": "encontrar la primera aparici\u00f3n del elemento", + "LISTS_INDEX_OF_LAST": "encontrar la \u00faltima aparici\u00f3n del elemento", + "LISTS_INDEX_OF_TOOLTIP": "Devuelve el \u00edndice de la primera/\u00faltima aparici\u00f3n del elemento en la lista. Devuelve 0 si el texto no se encuentra.", + "LISTS_GET_INDEX_GET": "obtener", + "LISTS_GET_INDEX_GET_REMOVE": "obtener y retirar", + "LISTS_GET_INDEX_REMOVE": "eliminar", + "LISTS_GET_INDEX_FROM_END": "# del final", + "LISTS_GET_INDEX_FIRST": "primero", + "LISTS_GET_INDEX_LAST": "\u00faltimo", + "LISTS_GET_INDEX_RANDOM": "aleatorio", + "LISTS_GET_INDEX_TOOLTIP_GET_FROM_START": "Devuelve el elemento a la posici\u00f3n especificada en la lista. #1 es el primer elemento.", + "LISTS_GET_INDEX_TOOLTIP_GET_FROM_END": "Devuelve el elemento a la posici\u00f3n especificada en la lista. #1 es el \u00faltimo elemento.", + "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Devuelve el primer elemento de una lista.", + "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Devuelve el \u00faltimo elemento de una lista.", + "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Devuelve un elemento aleatorio en una lista.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START": "Elimina y devuelve el elemento a la posici\u00f3n especificada en la lista. #1 es el primer elemento.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END": "Elimina y devuelve el elemento a la posici\u00f3n especificada en la lista. #1 es el \u00faltimo elemento.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Elimina y devuelve el primer elemento de una lista.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Elimina y devuelve el \u00faltimo elemento de una lista.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Elimina y devuelve un elemento aleatorio en una lista.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START": "Elimina el elemento a la posici\u00f3n especificada en la lista. #1 es el primer elemento.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END": "Elimina el elemento a la posici\u00f3n especificada en la lista. #1 es el \u00faltimo elemento.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Elimina el primer elemento de una lista.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Elimina el \u00faltimo elemento de una lista.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Elimina un elemento aleatorio en una lista.", + "LISTS_SET_INDEX_SET": "establece", + "LISTS_SET_INDEX_INSERT": "inserta en", + "LISTS_SET_INDEX_INPUT_TO": "como", + "LISTS_SET_INDEX_TOOLTIP_SET_FROM_START": "Establece el elemento a la posici\u00f3n especificada en una lista. #1 es el primer elemento.", + "LISTS_SET_INDEX_TOOLTIP_SET_FROM_END": "Establece el elemento a la posici\u00f3n especificada en una lista. #1 es el \u00faltimo elemento.", + "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Establece el primer elemento de una lista.", + "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Establece el \u00faltimo elemento de una lista.", + "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Establece un elemento aleatorio en una lista.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START": "Inserta el elemento a la posici\u00f3n especificada en la lista. #1 es el primer elemento.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END": "Inserta el elemento a la posici\u00f3n especificada en la lista. #1 es el \u00faltimo elemento.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Inserta el elemento al inicio de una lista.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "A\u00f1ade el elemento al final de una lista.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Inserta el elemento aleatoriamente en una lista.", + "LISTS_GET_SUBLIST_START_FROM_START": "obtener sub-lista de #", + "LISTS_GET_SUBLIST_START_FROM_END": "obtener sub-lista de # del final", + "LISTS_GET_SUBLIST_START_FIRST": "obtener sub-lista del primero", + "LISTS_GET_SUBLIST_END_FROM_START": "a #", + "LISTS_GET_SUBLIST_END_FROM_END": "a # del final", + "LISTS_GET_SUBLIST_END_LAST": "a la \u00faltima", + "LISTS_GET_SUBLIST_TOOLTIP": "Crea una copia de la parte especificada de una lista.", + "VARIABLES_GET_TOOLTIP": "Devuelve el valor de esta variable.", + "VARIABLES_GET_CREATE_SET": "Crear 'set %1'", + "VARIABLES_SET_TITLE": "establece", + "VARIABLES_SET_TAIL": "a", + "VARIABLES_SET_TOOLTIP": "Establece esta variable para que sea igual a la entrada.", + "VARIABLES_SET_CREATE_GET": "Crear 'obtener %1'", + "PROCEDURES_DEFNORETURN_TITLE": "a", + "PROCEDURES_DEFNORETURN_PROCEDURE": "hacer algo", + "PROCEDURES_BEFORE_PARAMS": "con:", + "PROCEDURES_DEFNORETURN_TOOLTIP": "Crea una funci\u00f3n sin salida.", + "PROCEDURES_DEFRETURN_RETURN": "devuelve", + "PROCEDURES_DEFRETURN_TOOLTIP": "Crea una funci\u00f3n con una salida.", + "PROCEDURES_DEF_DUPLICATE_WARNING": "Advertencia: Esta funci\u00f3n tiene par\u00e1metros duplicados.", + "PROCEDURES_CALLNORETURN_HELPURL": "http://es.wikipedia.org/wiki/Subrutina", + "PROCEDURES_CALLNORETURN_TOOLTIP": "Ejecuta la funci\u00f3n definida por el usuario '%1'.", + "PROCEDURES_CALLRETURN_HELPURL": "http://es.wikipedia.org/wiki/Subrutina", + "PROCEDURES_CALLRETURN_TOOLTIP": "Ejecuta la funci\u00f3n definida por el usuario '%1' y usar su salida.", + "PROCEDURES_MUTATORCONTAINER_TITLE": "entradas", + "PROCEDURES_MUTATORARG_TITLE": "nombre de entrada:", + "PROCEDURES_HIGHLIGHT_DEF": "Destacar definici\u00f3n de la funci\u00f3n", + "PROCEDURES_CREATE_DO": "Crear '%1'", + "PROCEDURES_IFRETURN_TOOLTIP": "Si el valor es verdadero, entonces devuelve un segundo valor.", + "PROCEDURES_IFRETURN_WARNING": "Advertencia: Este bloque solo puede ser utilizado dentro de la definici\u00f3n de una funci\u00f3n." +} \ No newline at end of file diff --git a/msg/json/fa.json b/msg/json/fa.json new file mode 100644 index 000000000..8526be5d7 --- /dev/null +++ b/msg/json/fa.json @@ -0,0 +1,293 @@ +{ + "@metadata": { + "authors": [ + "Ebraminio" + ] + }, + "VARIABLES_DEFAULT_NAME": "\u0645\u0648\u0631\u062f", + "DUPLICATE_BLOCK": "\u062a\u06a9\u0631\u0627\u0631\u06cc", + "ADD_COMMENT": "\u0627\u0641\u0632\u0648\u062f\u0646 \u0646\u0638\u0631", + "REMOVE_COMMENT": "\u062d\u0630\u0641 \u0646\u0638\u0631", + "EXTERNAL_INPUTS": "\u0648\u0631\u0648\u062f\u06cc\u200c\u0647\u0627\u06cc \u062e\u0627\u0631\u062c\u06cc", + "INLINE_INPUTS": "\u0648\u0631\u0648\u062f\u06cc\u200c\u0647\u0627\u06cc \u062f\u0631\u0648\u0646 \u062e\u0637\u06cc", + "DELETE_BLOCK": "\u062d\u0630\u0641 \u0628\u0644\u0648\u06a9", + "DELETE_X_BLOCKS": "\u062d\u0630\u0641 \u0628\u0644\u0648\u06a9\u200c\u0647\u0627\u06cc %1", + "COLLAPSE_BLOCK": "\u0641\u0631\u0648\u067e\u0627\u0634\u06cc \u0628\u0644\u0648\u06a9", + "COLLAPSE_ALL": "\u0641\u0631\u0648\u067e\u0627\u0634\u06cc \u0628\u0644\u0648\u06a9\u200c\u0647\u0627", + "EXPAND_BLOCK": "\u06af\u0633\u062a\u0631\u0634 \u0628\u0644\u0648\u06a9", + "EXPAND_ALL": "\u06af\u0633\u062a\u0631\u0634 \u0628\u0644\u0648\u06a9\u200c\u0647\u0627", + "DISABLE_BLOCK": "\u063a\u06cc\u0631\u0641\u0639\u0627\u0644\u200c\u0633\u0627\u0632\u06cc \u0628\u0644\u0648\u06a9", + "ENABLE_BLOCK": "\u0641\u0639\u0627\u0644\u200c\u0633\u0627\u0632\u06cc \u0628\u0644\u0648\u06a9", + "HELP": "\u0631\u0627\u0647\u0646\u0645\u0627", + "CHANGE_VALUE_TITLE": "\u062a\u063a\u06cc\u06cc\u0631 \u0645\u0642\u062f\u0627\u0631:", + "NEW_VARIABLE": "\u0645\u062a\u063a\u06cc\u0631 \u062c\u062f\u06cc\u062f...", + "NEW_VARIABLE_TITLE": "\u0646\u0627\u0645 \u0645\u062a\u063a\u06cc\u0631 \u062c\u062f\u06cc\u062f:", + "RENAME_VARIABLE": "\u062a\u063a\u06cc\u06cc\u0631 \u0646\u0627\u0645 \u0645\u062a\u063a\u06cc\u0631...", + "RENAME_VARIABLE_TITLE": "\u062a\u063a\u06cc\u06cc\u0631 \u0646\u0627\u0645 \u0647\u0645\u0647\u0654 \u0645\u062a\u063a\u06cc\u0631\u0647\u0627\u06cc \u00ab%1\u00bb \u0628\u0647:", + "COLOUR_PICKER_HELPURL": "http://fa.wikipedia.org/wiki/%D8%B1%D9%86%DA%AF", + "COLOUR_PICKER_TOOLTIP": "\u0627\u0646\u062a\u062e\u0627\u0628 \u06cc\u06a9 \u0631\u0646\u06af \u0627\u0632 \u062a\u062e\u062a\u0647\u200c\u0631\u0646\u06af.", + "COLOUR_RANDOM_TITLE": "\u0631\u0646\u06af \u062a\u0635\u0627\u062f\u0641\u06cc", + "COLOUR_RANDOM_TOOLTIP": "\u0627\u0646\u062a\u062e\u0627\u0628 \u06cc\u06a9 \u0631\u0646\u06af \u0628\u0647 \u0634\u06a9\u0644 \u062a\u0635\u0627\u062f\u0641\u06cc.", + "COLOUR_RGB_TITLE": "\u0631\u0646\u06af \u0628\u0627", + "COLOUR_RGB_RED": "\u0642\u0631\u0645\u0632", + "COLOUR_RGB_GREEN": "\u0633\u0628\u0632", + "COLOUR_RGB_BLUE": "\u0622\u0628\u06cc", + "COLOUR_RGB_TOOLTIP": "\u0633\u0627\u062e\u062a \u06cc\u06a9 \u0631\u0646\u06af \u0628\u0627 \u0645\u0642\u062f\u0627\u0631 \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647\u200c\u0627\u06cc \u0627\u0632 \u0642\u0631\u0645\u0632\u060c \u0633\u0628\u0632 \u0648 \u0622\u0628\u06cc. \u0647\u0645\u0647\u0654 \u0645\u0642\u0627\u062f\u06cc\u0631 \u0628\u0627\u06cc\u062f \u0628\u06cc\u0646 \u06f0 \u062a\u0627 \u06f1\u06f0\u06f0 \u0628\u0627\u0634\u0646\u062f.", + "COLOUR_BLEND_TITLE": "\u0645\u062e\u0644\u0648\u0637", + "COLOUR_BLEND_COLOUR1": "\u0631\u0646\u06af \u06f1", + "COLOUR_BLEND_COLOUR2": "\u0631\u0646\u06af \u06f2", + "COLOUR_BLEND_RATIO": "\u0646\u0633\u0628\u062a", + "COLOUR_BLEND_TOOLTIP": "\u062f\u0648 \u0631\u0646\u06af \u0631\u0627 \u0628\u0627 \u0646\u0633\u0628\u062a \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647 \u0645\u062e\u0644\u0648\u0637 \u0645\u06cc\u200c\u06a9\u0646\u062f (\u06f0\u066b\u06f0 - \u06f1\u066b\u06f0)", + "CONTROLS_REPEAT_HELPURL": "http://fa.wikipedia.org/wiki/%D8%AD%D9%84%D9%82%D9%87_%D9%81%D9%88%D8%B1", + "CONTROLS_REPEAT_TITLE": "%1 \u0628\u0627\u0631 \u062a\u06a9\u0631\u0627\u0631", + "CONTROLS_REPEAT_TITLE_REPEAT": "\u062a\u06a9\u0631\u0627\u0631", + "CONTROLS_REPEAT_TITLE_TIMES": "\u0628\u0627\u0631", + "CONTROLS_REPEAT_INPUT_DO": "\u0627\u0646\u062d\u0627\u0645", + "CONTROLS_REPEAT_TOOLTIP": "\u0627\u0646\u062c\u0627\u0645 \u0686\u0646\u062f \u0639\u0628\u0627\u0631\u062a \u0686\u0646\u062f\u06cc\u0646 \u0628\u0627\u0631.", + "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "\u062a\u06a9\u0631\u0627\u0631 \u062f\u0631 \u062d\u0627\u0644\u06cc \u06a9\u0647", + "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "\u062a\u06a9\u0631\u0627\u0631 \u062a\u0627 \u0632\u0645\u0627\u0646\u06cc \u06a9\u0647", + "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "\u062a\u0627 \u0632\u0645\u0627\u0646\u06cc \u06a9\u0647 \u06cc\u06a9 \u0645\u0642\u062f\u0627\u0631 \u0635\u062d\u06cc\u062d \u0627\u0633\u062a\u060c \u0686\u0646\u062f \u0639\u0628\u0627\u0631\u062a \u0631\u0627 \u0627\u0646\u062c\u0627\u0645 \u0628\u062f\u0647.", + "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "\u062a\u0627 \u0632\u0645\u0627\u0646\u06cc \u06a9\u0647 \u06cc\u06a9 \u0645\u0642\u062f\u0627\u0631 \u0646\u0627\u0635\u062d\u06cc\u062d \u0627\u0633\u062a\u060c \u0686\u0646\u062f \u0639\u0628\u0627\u0631\u062a \u0631\u0627 \u0627\u0646\u062c\u0627\u0645 \u0628\u062f\u0647.", + "CONTROLS_FOR_TOOLTIP": "\u0645\u062a\u063a\u06cc\u0631 %1 \u0631\u0627 \u062f\u0631 \u0645\u0642\u0627\u062f\u06cc\u0631 \u0634\u0631\u0648\u0639\u200c\u0634\u062f\u0647 \u0627\u0632 \u0639\u062f\u062f \u0627\u0646\u062a\u0647\u0627\u06cc \u0628\u0647 \u0639\u062f\u062f \u0627\u0646\u062a\u0647\u0627\u06cc\u06cc \u0631\u0627 \u062f\u0627\u0631\u062f\u060c \u0628\u0627 \u0641\u0648\u0627\u0635\u0644 \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647 \u0645\u06cc\u200c\u0634\u0645\u0627\u0631\u062f \u0648 \u0627\u06cc\u0646 \u0628\u0644\u0648\u06a9 \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647 \u0631\u0627 \u0627\u0646\u062c\u0627\u0645 \u0645\u06cc\u200c\u062f\u0647\u062f.", + "CONTROLS_FOR_INPUT_WITH": "\u0628\u0627 \u062a\u0639\u062f\u0627\u062f", + "CONTROLS_FOR_INPUT_FROM_TO_BY": "\u0627\u0632 %1 \u0628\u0647 %2 \u0628\u0627 \u06af\u0627\u0645\u200c\u0647\u0627\u06cc %3", + "CONTROLS_FOREACH_INPUT_ITEM": "\u0628\u0631\u0627\u06cc \u0647\u0631 \u0645\u0648\u0631\u062f", + "CONTROLS_FOREACH_INPUT_INLIST": "\u062f\u0631 \u0641\u0647\u0631\u0633\u062a", + "CONTROLS_FOREACH_TOOLTIP": "\u0628\u0631\u0627\u06cc \u0647\u0631 \u0645\u0648\u0631\u062f \u062f\u0631 \u0627\u06cc\u0646 \u0641\u0647\u0631\u0633\u062a\u060c \u062a\u0646\u0638\u06cc\u0645 \u0645\u062a\u063a\u06cc\u0631 \u00ab%1\u00bb \u0628\u0647 \u0645\u0648\u0631\u062f \u0648 \u0627\u0646\u062c\u0627\u0645 \u062a\u0639\u062f\u0627\u062f\u06cc \u0639\u0628\u0627\u0631\u062a.", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "\u0634\u06a9\u0633\u062a\u0646 \u062d\u0644\u0642\u0647", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "\u0627\u062f\u0627\u0645\u0647 \u0628\u0627 \u062a\u06a9\u0631\u0627\u0631 \u0628\u0639\u062f\u06cc \u062d\u0644\u0642\u0647", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "\u0634\u06a9\u0633\u062a\u0646 \u062d\u0644\u0642\u0647\u0654 \u0634\u0627\u0645\u0644.", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "\u067e\u0631\u06cc\u062f\u0646 \u0627\u0632 \u0628\u0642\u06cc\u0647\u0654 \u062d\u0644\u0642\u0647 \u0648 \u0627\u062f\u0627\u0645\u0647 \u0628\u0627 \u062a\u06a9\u0631\u0627\u0631 \u0628\u0639\u062f\u06cc.", + "CONTROLS_FLOW_STATEMENTS_WARNING": "\u0627\u062e\u0637\u0627\u0631: \u0627\u06cc\u0646 \u0628\u0644\u0648\u06a9 \u0645\u0645\u06a9\u0646 \u0627\u0633\u062a \u0641\u0642\u0637 \u062f\u0627\u062e\u0644 \u06cc\u06a9 \u062d\u0644\u0642\u0647 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0634\u0648\u062f.", + "CONTROLS_IF_TOOLTIP_1": "\u0627\u06af\u0631 \u06cc\u06a9 \u0645\u0642\u062f\u0627\u0631 \u0635\u062d\u06cc\u062d \u0627\u0633\u062a\u060c \u0633\u067e\u0633 \u0686\u0646\u062f \u0639\u0628\u0627\u0631\u062a \u0631\u0627 \u0627\u0646\u062c\u0627\u0645 \u0628\u062f\u0647.", + "CONTROLS_IF_TOOLTIP_2": "\u0627\u06af\u0631 \u06cc\u06a9 \u0645\u0642\u062f\u0627\u0631 \u0635\u062d\u06cc\u062d \u0627\u0633\u062a\u060c \u0627\u0648\u0644 \u0628\u0644\u0648\u06a9 \u0627\u0648\u0644 \u0639\u0628\u0627\u0631\u0627\u062a \u0631\u0627 \u0627\u0646\u062c\u0627\u0645 \u0628\u062f\u0647. \u062f\u0631 \u063a\u06cc\u0631 \u0627\u06cc\u0646 \u0635\u0648\u0631\u062a \u0628\u0644\u0648\u06a9 \u062f\u0648\u0645 \u0639\u0628\u0627\u0631\u0627\u062a \u0627\u0646\u062c\u0627\u0645 \u0628\u062f\u0647.", + "CONTROLS_IF_TOOLTIP_3": "\u0627\u06af\u0631 \u0645\u0642\u062f\u0627\u0631 \u0627\u0648\u0644 \u0635\u062d\u06cc\u062d \u0628\u0648\u062f\u060c \u0627\u0632 \u0622\u0646 \u0628\u0644\u0648\u06a9 \u0627\u0648\u0644 \u0639\u0628\u0627\u0631\u0627\u062a \u0631\u0627 \u0627\u0646\u062c\u0627\u0645 \u0628\u062f\u0647. \u062f\u0631 \u063a\u06cc\u0631 \u0627\u06cc\u0646 \u0635\u0648\u0631\u062a\u060c \u0627\u06af\u0631 \u0645\u0642\u062f\u0627\u0631 \u062f\u0648\u0645 \u0635\u062d\u06cc\u062d \u0627\u0633\u062a\u060c \u0628\u0644\u0648\u06a9 \u062f\u0648\u0645 \u0639\u0628\u0627\u0631\u0627\u062a \u0631\u0627 \u0627\u0646\u062c\u0627\u0645 \u0628\u062f\u0647.", + "CONTROLS_IF_TOOLTIP_4": "\u0627\u06af\u0631 \u0645\u0642\u062f\u0627\u0631 \u0627\u0648\u0644 \u062f\u0631\u0633\u062a \u0627\u0633\u062a\u060c \u0628\u0644\u0648\u06a9 \u0627\u0648\u0644 \u0639\u0628\u0627\u0631\u0627\u062a \u0631\u0627 \u0627\u0646\u062c\u0627\u0645 \u0628\u062f\u0647. \u062f\u0631 \u063a\u06cc\u0631 \u0627\u06cc\u0646 \u0635\u0648\u0631\u062a\u060c \u0627\u06af\u0631 \u0645\u0642\u062f\u0627\u0631 \u062f\u0648\u0645 \u062f\u0631\u0633\u062a \u0628\u0627\u0634\u062f \u0628\u0644\u0648\u06a9 \u062f\u0648\u0645 \u0639\u0628\u0627\u0631\u0627\u062a \u0631\u0627 \u0627\u0646\u062c\u0627\u0645 \u0628\u062f\u0647. \u0627\u06af\u0631 \u0647\u06cc\u0686 \u0627\u0632 \u0645\u0642\u0627\u062f\u06cc\u0631 \u062f\u0631\u0633\u062a \u0646\u0628\u0648\u062f\u060c \u0622\u062e\u0631\u06cc\u0646 \u0628\u0644\u0648\u06a9 \u0639\u0628\u0627\u0631\u0627\u062a \u0631\u0627 \u0627\u0646\u062c\u0627\u0645 \u0628\u062f\u0647.", + "CONTROLS_IF_MSG_IF": "\u0627\u06af\u0631", + "CONTROLS_IF_MSG_ELSEIF": "\u0627\u06af\u0631 \u0622\u0646\u06af\u0627\u0647", + "CONTROLS_IF_MSG_ELSE": "\u0622\u0646\u06af\u0627\u0647", + "CONTROLS_IF_IF_TOOLTIP": "\u0627\u0636\u0627\u0641\u0647\u060c \u062d\u0630\u0641 \u06cc\u0627 \u062a\u0631\u062a\u06cc\u0628\u200c\u0633\u0627\u0632\u06cc \u0642\u0633\u0645\u062a\u200c\u0647\u0627 \u0628\u0631\u0627\u06cc \u062a\u0646\u0638\u06cc\u0645 \u0645\u062c\u062f\u062f \u0627\u06cc\u0646 \u0628\u0644\u0648\u06a9 \u0627\u06af\u0631 \u0645\u0633\u062f\u0648\u062f \u0627\u0633\u062a.", + "CONTROLS_IF_ELSEIF_TOOLTIP": "\u0627\u0641\u0632\u0648\u062f\u0646 \u06cc\u06a9 \u0634\u0631\u0637 \u0628\u0647 \u0628\u0644\u0648\u06a9 \u0627\u06af\u0631.", + "CONTROLS_IF_ELSE_TOOLTIP": "\u0627\u0636\u0627\u0641\u0647\u200c\u06a9\u0631\u062f\u0646 \u0646\u0647\u0627\u06cc\u06cc\u060c \u06af\u0631\u0641\u062a\u0646 \u0647\u0645\u0647\u0654 \u0634\u0631\u0627\u06cc\u0637 \u0628\u0647 \u0628\u0644\u0648\u06a9 \u0627\u06af\u0631.", + "LOGIC_COMPARE_HELPURL": "http://fa.wikipedia.org/wiki/%D9%86%D8%A7%D8%A8%D8%B1%D8%A7%D8%A8%D8%B1%DB%8C", + "LOGIC_COMPARE_TOOLTIP_EQ": "\u0628\u0627\u0632\u06af\u0634\u062a \u0635\u062d\u06cc\u062d \u0627\u06af\u0631 \u0647\u0631 \u062f\u0648 \u0648\u0631\u0648\u062f\u06cc \u0628\u0627 \u06cc\u06a9\u062f\u06cc\u06af\u0631 \u0628\u0631\u0627\u0628\u0631 \u0628\u0627\u0634\u062f.", + "LOGIC_COMPARE_TOOLTIP_NEQ": "\u0628\u0631\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u0635\u062d\u06cc\u062d \u0627\u06af\u0631 \u0647\u0631 \u062f\u0648 \u0648\u0631\u0648\u062f\u06cc \u0628\u0627 \u06cc\u06a9\u062f\u06cc\u06af\u0631 \u0628\u0631\u0627\u0628\u0631 \u0646\u0628\u0627\u0634\u0646\u062f.", + "LOGIC_COMPARE_TOOLTIP_LT": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u0635\u062d\u06cc\u062d \u0627\u06af\u0631 \u0648\u0631\u0648\u062f\u06cc \u0627\u0648\u0644 \u06a9\u0648\u0686\u06a9\u062a\u0631 \u0627\u0632 \u0648\u0631\u0648\u062f\u06cc \u062f\u0648\u0645 \u0628\u0627\u0634\u062f.", + "LOGIC_COMPARE_TOOLTIP_LTE": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u0635\u062d\u06cc\u062d \u0627\u06af\u0631 \u0648\u0631\u0648\u062f\u06cc \u0627\u0648\u0644 \u06a9\u0648\u0686\u06a9\u062a\u0631 \u06cc\u0627 \u0645\u0633\u0627\u0648\u06cc \u0628\u0627 \u0648\u0631\u0648\u062f\u06cc \u062f\u0648\u0645 \u0628\u0627\u0634\u062f.", + "LOGIC_COMPARE_TOOLTIP_GT": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u0635\u062d\u06cc\u062d \u0627\u06af\u0631 \u0648\u0631\u0648\u062f\u06cc \u0627\u0648\u0644 \u0628\u0632\u0631\u06af\u062a\u0631 \u0627\u0632 \u0648\u0631\u0648\u062f\u06cc \u062f\u0648\u0645 \u0628\u0627\u0634\u062f.", + "LOGIC_COMPARE_TOOLTIP_GTE": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u0635\u062d\u06cc\u062d \u0627\u06af\u0631 \u0648\u0631\u0648\u062f\u06cc \u0627\u0648\u0644 \u0628\u0632\u0631\u06af\u062a\u0631 \u06cc\u0627 \u0645\u0633\u0627\u0648\u06cc \u06cc\u0627 \u0648\u0631\u0648\u062f\u06cc \u062f\u0648\u0645 \u0628\u0627\u0634\u062f.", + "LOGIC_OPERATION_TOOLTIP_AND": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u0635\u062d\u06cc\u062d \u0627\u06af\u0631 \u0647\u0631 \u062f\u0648 \u0648\u0631\u0648\u062f\u06cc \u0635\u062d\u06cc\u062d \u0628\u0627\u0634\u062f.", + "LOGIC_OPERATION_AND": "\u0648", + "LOGIC_OPERATION_TOOLTIP_OR": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u0635\u062d\u06cc\u062d \u0627\u06af\u0631 \u06cc\u06a9\u06cc \u0627\u0632 \u062f\u0648 \u0648\u0631\u0648\u062f\u06cc \u0635\u062d\u06cc\u062d \u0628\u0627\u0634\u062f.", + "LOGIC_OPERATION_OR": "\u06cc\u0627", + "LOGIC_NEGATE_TITLE": "\u0646\u0647 %1", + "LOGIC_NEGATE_TOOLTIP": "\u0635\u062c\u06cc\u062c \u0628\u0627\u0632 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f \u0627\u06af\u0631 \u0648\u0631\u0648\u062f\u06cc \u0646\u0627 \u0635\u062d\u06cc\u062d \u0628\u0627\u0634\u0646\u062f. \u0646\u0627\u0635\u062d\u06cc\u062d \u0628\u0627\u0632\u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f \u0627\u06af\u0631 \u0648\u0631\u0648\u062f\u06cc \u0635\u062d\u06cc\u062d \u0628\u0627\u0634\u062f.", + "LOGIC_BOOLEAN_TRUE": "\u0635\u062d\u06cc\u062d", + "LOGIC_BOOLEAN_FALSE": "\u0646\u0627\u0635\u062d\u06cc\u062d", + "LOGIC_BOOLEAN_TOOLTIP": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u06cc\u06a9\u06cc \u0627\u0632 \u0635\u062d\u06cc\u062d \u06cc\u0627 \u0646\u0627\u0635\u062d\u06cc\u062d.", + "LOGIC_NULL": "\u062a\u0647\u06cc", + "LOGIC_NULL_TOOLTIP": "\u062a\u0647\u06cc \u0628\u0627\u0632\u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "LOGIC_TERNARY_CONDITION": "\u0622\u0632\u0645\u0627\u06cc\u0634", + "LOGIC_TERNARY_IF_TRUE": "\u0627\u06af\u0631 \u0635\u062d\u06cc\u062d", + "LOGIC_TERNARY_IF_FALSE": "\u0627\u06af\u0631 \u0646\u0627\u0635\u062d\u06cc\u062d", + "LOGIC_TERNARY_TOOLTIP": "\u0628\u0631\u0631\u0633\u06cc \u0648\u0636\u0639\u06cc\u062a \u062f\u0631 \u00ab\u0622\u0632\u0645\u0627\u06cc\u0634\u00bb. \u0627\u06af\u0631 \u0648\u0636\u0639\u06cc\u062a \u0635\u062d\u06cc\u062d \u0628\u0627\u0634\u062f\u060c \u0645\u0642\u062f\u0627\u0631 \u00ab\u0627\u06af\u0631 \u0635\u062d\u06cc\u062d\u00bb \u0631\u0627 \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f \u062f\u0631 \u063a\u06cc\u0631 \u0627\u06cc\u0646\u0635\u0648\u0631\u062a \u0645\u0642\u062f\u0627\u0631 \u00ab\u0627\u06af\u0631 \u0646\u0627\u0635\u062d\u06cc\u062d\u00bb \u0631\u0627.", + "MATH_NUMBER_HELPURL": "http://fa.wikipedia.org/wiki/%D8%B9%D8%AF%D8%AF", + "MATH_NUMBER_TOOLTIP": "\u06cc\u06a9 \u0639\u062f\u062f.", + "MATH_ARITHMETIC_HELPURL": "http://fa.wikipedia.org/wiki/%D8%AD%D8%B3%D8%A7%D8%A8", + "MATH_ARITHMETIC_TOOLTIP_ADD": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u0645\u0642\u062f\u0627\u0631 \u062c\u0645\u0639 \u062f\u0648 \u0639\u062f\u062f.", + "MATH_ARITHMETIC_TOOLTIP_MINUS": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u062a\u0641\u0627\u0648\u062a \u062f\u0648 \u0639\u062f\u062f.", + "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u062d\u0627\u0635\u0644\u0636\u0631\u0628 \u062f\u0648 \u0639\u062f\u062f.", + "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u0628\u0627\u0642\u06cc\u200c\u0645\u0627\u0646\u062f\u0647\u0654 \u062f\u0648 \u0639\u062f\u062f.", + "MATH_ARITHMETIC_TOOLTIP_POWER": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u0627\u0648\u0644\u06cc\u0646 \u0639\u062f\u062f\u06cc \u06a9\u0647 \u0627\u0632 \u062a\u0648\u0627\u0646 \u0639\u062f\u062f \u062f\u0648\u0645 \u062d\u0627\u0635\u0644 \u0634\u062f\u0647 \u0628\u0627\u0634\u062f.", + "MATH_SINGLE_HELPURL": "http://fa.wikipedia.org/wiki/%D8%B1%DB%8C%D8%B4%D9%87_%D8%AF%D9%88%D9%85", + "MATH_SINGLE_OP_ROOT": "\u0631\u06cc\u0634\u0647\u0654 \u062f\u0648\u0645", + "MATH_SINGLE_TOOLTIP_ROOT": "\u0631\u06cc\u0634\u0647\u0654 \u062f\u0648\u0645 \u06cc\u06a9 \u0639\u062f\u062f \u0631\u0627 \u0628\u0627\u0632 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "MATH_SINGLE_OP_ABSOLUTE": "\u0645\u0637\u0644\u0642", + "MATH_SINGLE_TOOLTIP_ABS": "\u0642\u062f\u0631 \u0645\u0637\u0644\u0642 \u06cc\u06a9 \u0639\u062f\u062f \u0631\u0627 \u0628\u0627\u0632\u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "MATH_SINGLE_TOOLTIP_NEG": "\u0645\u0646\u0641\u06cc\u200c\u0634\u062f\u0647\u0654 \u06cc\u06a9 \u0639\u062f\u062f \u0631\u0627 \u0628\u0627\u0632 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "MATH_SINGLE_TOOLTIP_LN": "\u0644\u0648\u06af\u0627\u0631\u06cc\u062a\u0645 \u0637\u0628\u06cc\u0639\u06cc \u06cc\u06a9 \u0639\u062f\u062f \u0631\u0627 \u0628\u0627\u0632 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "MATH_SINGLE_TOOLTIP_LOG10": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u0644\u06af\u0627\u0631\u06cc\u062a\u0645 \u0628\u0631 \u067e\u0627\u06cc\u0647\u0654 \u06f1\u06f0 \u06cc\u06a9 \u0639\u062f\u062f.", + "MATH_SINGLE_TOOLTIP_EXP": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u062a\u0648\u0627\u0646 e \u06cc\u06a9 \u0639\u062f\u062f.", + "MATH_SINGLE_TOOLTIP_POW10": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u062a\u0648\u0627\u0646 \u06f1\u06f0 \u06cc\u06a9 \u0639\u062f\u062f.", + "MATH_TRIG_HELPURL": "http://fa.wikipedia.org/wiki/%D8%AA%D8%A7%D8%A8%D8%B9%E2%80%8C%D9%87%D8%A7%DB%8C_%D9%85%D8%AB%D9%84%D8%AB%D8%A7%D8%AA%DB%8C", + "MATH_TRIG_TOOLTIP_SIN": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u0633\u06cc\u0646\u0648\u0633 \u062f\u0631\u062c\u0647 (\u0646\u0647 \u0631\u0627\u062f\u06cc\u0627\u0646).", + "MATH_TRIG_TOOLTIP_COS": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u06a9\u0633\u06cc\u0646\u0648\u0633 \u062f\u0631\u062c\u0647 (\u0646\u0647 \u0631\u0627\u062f\u06cc\u0627\u0646).", + "MATH_TRIG_TOOLTIP_TAN": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u062a\u0627\u0646\u0698\u0627\u0646\u062a \u06cc\u06a9 \u062f\u0631\u062c\u0647 (\u0646\u0647 \u0631\u0627\u062f\u06cc\u0627\u0646).", + "MATH_TRIG_TOOLTIP_ASIN": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u0622\u0631\u06a9\u200c\u0633\u06cc\u0646\u0648\u0633 \u062f\u0631\u062c\u0647 (\u0646\u0647 \u0631\u0627\u062f\u06cc\u0627\u0646).", + "MATH_TRIG_TOOLTIP_ACOS": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u0622\u0631\u06a9\u200c\u06a9\u0633\u06cc\u0646\u0648\u0633 \u062f\u0631\u062c\u0647 (\u0646\u0647 \u0631\u0627\u062f\u06cc\u0627\u0646).", + "MATH_TRIG_TOOLTIP_ATAN": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u0622\u0631\u06a9\u200c\u062a\u0627\u0646\u0698\u0627\u0646\u062a \u062f\u0631\u062c\u0647 (\u0646\u0647 \u0631\u0627\u062f\u06cc\u0627\u0646).", + "MATH_CONSTANT_HELPURL": "http://fa.wikipedia.org/wiki/%D8%AB%D8%A7%D8%A8%D8%AA_%D8%B1%DB%8C%D8%A7%D8%B6%DB%8C", + "MATH_CONSTANT_TOOLTIP": "\u06cc\u06a9\u06cc \u0627\u0632 \u0645\u0642\u0627\u062f\u06cc\u0631 \u0645\u0634\u062a\u0631\u06a9 \u0631\u0627 \u0628\u0631\u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f: \u03c0 (\u06f3\u066b\u06f1\u06f4\u06f1\u2026)\u060c e (\u06f2\u066b\u06f7\u06f1\u06f8...)\u060c \u03c6 (\u06f1\u066b\u06f6\u06f1\u06f8)\u060c sqrt(\u06f2) (\u06f1\u066b\u06f4\u06f1\u06f4)\u060c sqrt(\u06f1/\u06f2) (\u06f0\u066b\u06f7\u06f0\u06f7...) \u0648 \u06cc\u0627 \u221e (\u0628\u06cc\u200c\u0646\u0647\u0627\u06cc\u062a).", + "MATH_IS_EVEN": "\u0632\u0648\u062c \u0627\u0633\u062a", + "MATH_IS_ODD": "\u0641\u0631\u062f \u0627\u0633\u062a", + "MATH_IS_PRIME": "\u0639\u062f\u062f \u0627\u0648\u0644 \u0627\u0633\u062a", + "MATH_IS_WHOLE": "\u06a9\u0627\u0645\u0644 \u0627\u0633\u062a", + "MATH_IS_POSITIVE": "\u0645\u062b\u0628\u062a \u0627\u0633\u062a", + "MATH_IS_NEGATIVE": "\u0645\u0646\u0641\u06cc \u0627\u0633\u062a", + "MATH_IS_DIVISIBLE_BY": "\u062a\u0642\u0633\u06cc\u0645 \u0634\u062f\u0647 \u0628\u0631", + "MATH_IS_TOOLTIP": "\u0628\u0631\u0631\u0633\u06cc \u0645\u06cc\u200c\u06a9\u0646\u062f \u06a9\u0647 \u0622\u06cc\u0627 \u06cc\u06a9 \u0639\u062f\u062f \u0632\u0648\u062c\u060c \u0641\u0631\u062f\u060c \u0627\u0648\u0644\u060c \u06a9\u0627\u0645\u0644\u060c \u0645\u062b\u0628\u062a\u060c \u0645\u0646\u0641\u06cc \u06cc\u0627 \u0628\u062e\u0634\u200c\u067e\u0630\u06cc\u0631 \u0639\u062f\u062f \u062e\u0627\u0635\u06cc \u0628\u0627\u0634\u062f \u0631\u0627 \u0628\u0631\u0631\u0633\u06cc \u0645\u06cc\u200c\u06a9\u0646\u062f. \u062f\u0631\u0633\u062a \u06cc\u0627 \u0646\u0627\u062f\u0631\u0633\u062a \u0628\u0627\u0632 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "MATH_CHANGE_TITLE_CHANGE": "\u062a\u063a\u06cc\u06cc\u0631", + "MATH_CHANGE_INPUT_BY": "\u0628\u0627", + "MATH_CHANGE_TOOLTIP": "\u0627\u0641\u0632\u0648\u062f\u0646 \u06cc\u06a9 \u0639\u062f\u062f \u0628\u0647 \u0645\u062a\u063a\u06cc\u0631 '%1'.", + "MATH_ROUND_HELPURL": "http://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29", + "MATH_ROUND_TOOLTIP": "\u06af\u0631\u062f\u06a9\u0631\u062f\u0646 \u06cc\u06a9 \u0639\u062f\u062f \u0628\u0647 \u0628\u0627\u0644\u0627 \u06cc\u0627 \u067e\u0627\u06cc\u06cc\u0646.", + "MATH_ROUND_OPERATOR_ROUND": "\u06af\u0631\u062f\u06a9\u0631\u062f\u0646", + "MATH_ROUND_OPERATOR_ROUNDUP": "\u06af\u0631\u062f \u0628\u0647 \u0628\u0627\u0644\u0627", + "MATH_ROUND_OPERATOR_ROUNDDOWN": "\u06af\u0631\u062f \u0628\u0647 \u067e\u0627\u06cc\u06cc\u0646", + "MATH_ONLIST_OPERATOR_SUM": "\u062c\u0645\u0639 \u0641\u0647\u0631\u0633\u062a", + "MATH_ONLIST_TOOLTIP_SUM": "\u062c\u0645\u0639 \u0647\u0645\u0647\u0654 \u0639\u062f\u062f\u0647\u0627\u06cc \u0641\u0647\u0631\u0633\u062a \u0631\u0627 \u0628\u0627\u0632 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "MATH_ONLIST_OPERATOR_MIN": "\u06a9\u0648\u0686\u06a9\u062a\u0631\u06cc\u0646 \u0641\u0647\u0631\u0633\u062a", + "MATH_ONLIST_TOOLTIP_MIN": "\u06a9\u0648\u0686\u06a9\u200c\u062a\u0631\u06cc\u0646 \u0639\u062f\u062f \u062f\u0631 \u0641\u0647\u0631\u0633\u062a \u0631\u0627 \u0628\u0627\u0632 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "MATH_ONLIST_OPERATOR_MAX": "\u0628\u0632\u0631\u06af\u200c\u062a\u0631\u06cc\u0646 \u0641\u0647\u0631\u0633\u062a", + "MATH_ONLIST_TOOLTIP_MAX": "\u0628\u0632\u0631\u06af\u200c\u062a\u0631\u06cc\u0646 \u0639\u062f\u062f \u062f\u0631 \u0641\u0647\u0631\u0633\u062a \u0631\u0627 \u0628\u0627\u0632 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "MATH_ONLIST_OPERATOR_AVERAGE": "\u0645\u06cc\u0627\u0646\u06af\u06cc\u0646 \u0641\u0647\u0631\u0633\u062a", + "MATH_ONLIST_TOOLTIP_AVERAGE": "\u0645\u06cc\u0627\u0646\u06af\u06cc\u0646 (\u0645\u06cc\u0627\u0646\u06af\u06cc\u0646 \u0631\u06cc\u0627\u0636\u06cc) \u0645\u0642\u0627\u062f\u06cc\u0631 \u0639\u062f\u062f\u06cc \u0641\u0647\u0631\u0633\u062a \u0631\u0627 \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "MATH_ONLIST_OPERATOR_MEDIAN": "\u0645\u06cc\u0627\u0646\u0647\u0654 \u0641\u0647\u0631\u0633\u062a", + "MATH_ONLIST_TOOLTIP_MEDIAN": "\u0645\u06cc\u0627\u0646\u0647\u0654 \u0639\u062f\u062f \u062f\u0631 \u0641\u0647\u0631\u0633\u062a \u0631\u0627 \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "MATH_ONLIST_OPERATOR_MODE": "\u0645\u062f \u0641\u0647\u0631\u0633\u062a", + "MATH_ONLIST_TOOLTIP_MODE": "\u0634\u0627\u06cc\u0639\u200c\u062a\u0631\u06cc\u0646 \u0642\u0644\u0645(\u0647\u0627\u06cc) \u062f\u0631 \u0641\u0647\u0631\u0633\u062a \u0631\u0627 \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "MATH_ONLIST_OPERATOR_STD_DEV": "\u0627\u0646\u062d\u0631\u0627\u0641 \u0645\u0639\u06cc\u0627\u0631 \u0641\u0647\u0631\u0633\u062a", + "MATH_ONLIST_TOOLTIP_STD_DEV": "\u0627\u0646\u062d\u0631\u0627\u0641 \u0645\u0639\u06cc\u0627\u0631 \u0641\u0647\u0631\u0633\u062a \u0631\u0627 \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "MATH_ONLIST_OPERATOR_RANDOM": "\u0645\u0648\u0631\u062f \u062a\u0635\u0627\u062f\u0641\u06cc \u0627\u0632 \u0641\u0647\u0631\u0633\u062a", + "MATH_ONLIST_TOOLTIP_RANDOM": "\u0645\u0648\u0631\u062f\u06cc \u062a\u0635\u0627\u062f\u0641\u06cc \u0627\u0632 \u0641\u0647\u0631\u0633\u062a \u0631\u0627 \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "MATH_MODULO_HELPURL": "http://fa.wikipedia.org/wiki/%D8%B9%D9%85%D9%84%DB%8C%D8%A7%D8%AA_%D9%BE%DB%8C%D9%85%D8%A7%D9%86%D9%87", + "MATH_MODULO_TITLE": "\u0628\u0627\u0642\u06cc\u200c\u0645\u0627\u0646\u062f\u0647\u0654 %1 + %2", + "MATH_MODULO_TOOLTIP": "\u0628\u0627\u0642\u06cc\u200c\u0645\u0627\u0646\u062f\u0647\u0654 \u062a\u0642\u0633\u06cc\u0645 \u062f\u0648 \u0639\u062f\u062f \u0631\u0627 \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "MATH_CONSTRAIN_TITLE": "\u0645\u062d\u062f\u0648\u062f\u06a9\u0631\u062f\u0646 %1 \u067e\u0627\u06cc\u06cc\u0646 %2 \u0628\u0627\u0644\u0627 %3", + "MATH_CONSTRAIN_TOOLTIP": "\u0645\u062d\u062f\u0648\u062f\u06a9\u0631\u062f\u0646 \u06cc\u06a9 \u0639\u062f\u062f \u0628\u06cc\u0646 \u0645\u062d\u062f\u0648\u062f\u06cc\u062a\u200c\u0647\u0627\u06cc \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647 (\u0628\u0633\u062a\u0647).", + "MATH_RANDOM_INT_HELPURL": "http://fa.wikipedia.org/wiki/%D8%AA%D9%88%D9%84%DB%8C%D8%AF_%D8%A7%D8%B9%D8%AF%D8%A7%D8%AF_%D8%AA%D8%B5%D8%A7%D8%AF%D9%81%DB%8C", + "MATH_RANDOM_INT_TITLE": "\u0639\u062f\u062f \u0635\u062d\u06cc\u062d \u062a\u0635\u0627\u062f\u0641\u06cc \u0628\u06cc\u0646 %1 \u062a\u0627 %2", + "MATH_RANDOM_INT_TOOLTIP": "\u06cc\u06a9 \u0639\u062f\u062f \u062a\u0635\u0627\u062f\u0641\u06cc \u0628\u06cc\u0646 \u062f\u0648 \u0645\u0642\u062f\u0627\u0631 \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647 \u0628\u0647 \u0635\u0648\u0631\u062a \u0628\u0633\u062a\u0647 \u0628\u0627\u0632 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "MATH_RANDOM_FLOAT_HELPURL": "http://fa.wikipedia.org/wiki/%D8%AA%D9%88%D9%84%DB%8C%D8%AF_%D8%A7%D8%B9%D8%AF%D8%A7%D8%AF_%D8%AA%D8%B5%D8%A7%D8%AF%D9%81%DB%8C", + "MATH_RANDOM_FLOAT_TITLE_RANDOM": "\u06a9\u0633\u0631 \u062a\u0635\u0627\u062f\u0641\u06cc", + "MATH_RANDOM_FLOAT_TOOLTIP": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u06a9\u0633\u0631\u06cc \u062a\u0635\u0627\u062f\u0641\u06cc \u0628\u06cc\u0646 \u06f0\u066b\u06f0 (\u0628\u0633\u062a\u0647) \u062a\u0627 \u06f1\u066b\u06f0 (\u0628\u0627\u0632).", + "TEXT_TEXT_HELPURL": "http://fa.wikipedia.org/wiki/%D8%B1%D8%B4%D8%AA%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29", + "TEXT_TEXT_TOOLTIP": "\u06cc\u06a9 \u062d\u0631\u0641\u060c \u06a9\u0644\u0645\u0647 \u06cc\u0627 \u062e\u0637\u06cc \u0627\u0632 \u0645\u062a\u0646.", + "TEXT_JOIN_TITLE_CREATEWITH": "\u0627\u06cc\u062c\u0627\u062f \u0645\u062a\u0646 \u0628\u0627", + "TEXT_JOIN_TOOLTIP": "\u06cc\u06a9 \u062a\u06a9\u0647\u200c\u0627\u06cc \u0627\u0632 \u0645\u062a\u0646 \u0631\u0627 \u0628\u0627 \u0686\u0633\u067e\u0627\u0646\u062f\u0646 \u0647\u0645\u0647\u0654 \u062a\u0639\u062f\u0627\u062f \u0627\u0632 \u0645\u0648\u0627\u0631\u062f \u0627\u06cc\u062c\u0627\u062f \u0645\u06cc\u200c\u06a9\u0646\u062f.", + "TEXT_CREATE_JOIN_TITLE_JOIN": "\u0639\u0636\u0648\u06cc\u062a", + "TEXT_CREATE_JOIN_TOOLTIP": "\u0627\u0636\u0627\u0641\u0647\u200c\u06a9\u0631\u062f\u0646\u060c \u062d\u0630\u0641 \u06cc\u0627 \u0645\u0631\u062a\u0628\u200c\u0633\u0627\u0632\u06cc \u0628\u062d\u0634\u200c\u0647\u0627 \u0628\u0631\u0627\u06cc \u062a\u0646\u0638\u06cc\u0645 \u0645\u062c\u062f\u062f \u0627\u06cc\u0646 \u0628\u0644\u0648\u06a9 \u0645\u062a\u0646\u06cc.", + "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "\u0627\u0641\u0632\u0648\u062f\u0646 \u06cc\u06a9 \u0645\u0648\u0631\u062f \u0628\u0647 \u0645\u062a\u0646.", + "TEXT_APPEND_TO": "\u0628\u0647", + "TEXT_APPEND_APPENDTEXT": "\u0627\u0644\u062d\u0627\u0642 \u0645\u062a\u0646", + "TEXT_APPEND_TOOLTIP": "\u0627\u0644\u062d\u0627\u0642 \u0645\u062a\u0646\u06cc \u0628\u0647 \u0645\u062a\u063a\u06cc\u0631 \u00ab%1\u00bb.", + "TEXT_LENGTH_TITLE": "\u0637\u0648\u0644 %1", + "TEXT_LENGTH_TOOLTIP": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u0639\u062f\u062f\u06cc \u0627\u0632 \u062d\u0631\u0648\u0641 (\u0634\u0627\u0645\u0644 \u0641\u0627\u0635\u0644\u0647\u200c\u0647\u0627) \u062f\u0631 \u0645\u062a\u0646 \u0641\u0631\u0627\u0647\u0645\u200c\u0634\u062f\u0647.", + "TEXT_ISEMPTY_TITLE": "%1 \u062e\u0627\u0644\u06cc \u0627\u0633\u062a", + "TEXT_ISEMPTY_TOOLTIP": "\u0627\u0636\u0627\u0641\u0647\u200c\u06a9\u0631\u062f\u0646 \u0635\u062d\u06cc\u062d \u0627\u06af\u0631 \u0645\u062a\u0646 \u0641\u0631\u0627\u0647\u0645\u200c\u0634\u062f\u0647 \u062e\u0627\u0644\u06cc \u0627\u0633\u062a.", + "TEXT_INDEXOF_TOOLTIP": "\u0634\u0627\u062e\u0635\u06cc \u0627\u0632 \u0627\u0648\u0644\u06cc\u0646 \u0622\u062e\u0631\u06cc\u0646 \u0631\u062e\u200c\u062f\u0627\u062f \u0645\u062a\u0646 \u0627\u0648\u0644 \u062f\u0631 \u0645\u062a\u0646 \u062f\u0648\u0645 \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f. \u0627\u06af\u0631 \u0645\u062a\u0646 \u06cc\u0627\u0641\u062a \u0646\u0634\u062f \u06f0 \u0628\u0627\u0632 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "TEXT_INDEXOF_INPUT_INTEXT": "\u062f\u0631 \u0645\u062a\u0646", + "TEXT_INDEXOF_OPERATOR_FIRST": "\u0627\u0648\u0644\u06cc\u0646 \u0631\u062e\u062f\u0627\u062f \u0645\u062a\u0646 \u0631\u0627 \u0628\u06cc\u0627\u0628", + "TEXT_INDEXOF_OPERATOR_LAST": "\u0622\u062e\u0631\u06cc\u0646 \u0631\u062e\u062f\u0627\u062f \u0645\u062a\u0646 \u0631\u0627 \u0628\u06cc\u0627\u0628", + "TEXT_CHARAT_INPUT_INTEXT": "\u062f\u0631 \u0645\u062a\u0646", + "TEXT_CHARAT_FROM_START": "\u06af\u0631\u0641\u062a\u0646 \u062d\u0631\u0641 #", + "TEXT_CHARAT_FROM_END": "\u06af\u0631\u0641\u062a\u0646 \u062d\u0631\u0641 # \u0627\u0632 \u0622\u062e\u0631", + "TEXT_CHARAT_FIRST": "\u06af\u0631\u0641\u062a\u0646 \u0627\u0648\u0644\u06cc\u0646 \u062d\u0631\u0641", + "TEXT_CHARAT_LAST": "\u06af\u0631\u0641\u062a\u0646 \u0622\u062e\u0631\u06cc\u0646 \u062d\u0631\u0641", + "TEXT_CHARAT_RANDOM": "\u06af\u0631\u0641\u062a\u0646 \u062d\u0631\u0641 \u062a\u0635\u0627\u062f\u0641\u06cc", + "TEXT_CHARAT_TOOLTIP": "\u062d\u0631\u0641\u06cc \u062f\u0631 \u0645\u0648\u0642\u0639\u06cc\u062a \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647 \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "TEXT_GET_SUBSTRING_TOOLTIP": "\u0642\u0633\u0645\u062a \u0645\u0634\u062e\u0635\u06cc\u200c\u0634\u062f\u0647\u200c\u0627\u06cc \u0627\u0632 \u0645\u062a\u0646 \u0631\u0627 \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "\u062f\u0631 \u0645\u062a\u0646", + "TEXT_GET_SUBSTRING_START_FROM_START": "\u06af\u0631\u0641\u062a\u0646 \u0632\u06cc\u0631\u0645\u062a\u0646 \u0627\u0632 \u062d\u0631\u0641 #", + "TEXT_GET_SUBSTRING_START_FROM_END": "\u06af\u0631\u0641\u062a\u0646 \u0632\u06cc\u0631\u0645\u062a\u0646 \u0627\u0632 \u062d\u0631\u0641 # \u0628\u0647 \u0627\u0646\u062a\u0647\u0627", + "TEXT_GET_SUBSTRING_START_FIRST": "\u06af\u0631\u0641\u062a\u0646 \u0632\u06cc\u0631\u0645\u062a\u0646 \u0627\u0632 \u0627\u0648\u0644\u06cc\u0646 \u062d\u0631\u0641", + "TEXT_GET_SUBSTRING_END_FROM_START": "\u0628\u0647 \u062d\u0631\u0641 #", + "TEXT_GET_SUBSTRING_END_FROM_END": "\u0628\u0647 \u062d\u0631\u0641 # \u0627\u0632 \u0627\u0646\u062a\u0647\u0627", + "TEXT_GET_SUBSTRING_END_LAST": "\u0628\u0647 \u0622\u062e\u0631\u06cc\u0646 \u062d\u0631\u0641", + "TEXT_CHANGECASE_TOOLTIP": "\u0628\u0627\u0632\u06af\u0631\u062f\u0627\u0646\u062f\u0646 \u06a9\u067e\u06cc \u0645\u062a\u0646 \u062f\u0631 \u062d\u0627\u0644\u062a\u06cc \u0645\u062a\u0641\u0627\u0648\u062a.", + "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "\u0628\u0647 \u062d\u0631\u0648\u0641 \u0628\u0632\u0631\u06af", + "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "\u0628\u0647 \u062d\u0631\u0648\u0641 \u06a9\u0648\u0686\u06a9", + "TEXT_CHANGECASE_OPERATOR_TITLECASE": "\u0628\u0647 \u062d\u0631\u0648\u0641 \u0628\u0632\u0631\u06af \u0639\u0646\u0648\u0627\u0646", + "TEXT_TRIM_TOOLTIP": "\u06a9\u067e\u06cc \u0627\u0632 \u0645\u062a\u0646 \u0628\u0627 \u0641\u0627\u0635\u0644\u0647\u200c\u0647\u0627\u06cc \u062d\u0630\u0641\u200c\u0634\u062f\u0647 \u0627\u0632 \u06cc\u06a9 \u06cc\u0627 \u0647\u0631 \u062f\u0648 \u067e\u0627\u06cc\u0627\u0646 \u0628\u0627\u0632 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "TEXT_TRIM_OPERATOR_BOTH": "\u062a\u0631\u0627\u0634\u06cc\u062f\u0646 \u0641\u0627\u0635\u0644\u0647\u200c\u0647\u0627 \u0627\u0632 \u0647\u0631 \u062f\u0648 \u0637\u0631\u0641", + "TEXT_TRIM_OPERATOR_LEFT": "\u062a\u0631\u0627\u0634\u06cc\u062f\u0646 \u0641\u0627\u0635\u0644\u0647\u200c\u0647\u0627 \u0627\u0632 \u0637\u0631\u0641 \u0686\u067e", + "TEXT_TRIM_OPERATOR_RIGHT": "\u062a\u0631\u0627\u0634\u06cc\u062f\u0646 \u0641\u0627\u0635\u0644\u0647\u200c\u0647\u0627 \u0627\u0632 \u0637\u0631\u0641 \u0686\u067e", + "TEXT_PRINT_TITLE": "\u0686\u0627\u067e %1", + "TEXT_PRINT_TOOLTIP": "\u0686\u0627\u067e \u0645\u062a\u0646\u060c \u0639\u062f\u062f \u06cc\u0627 \u0647\u0631 \u0645\u0642\u062f\u0627\u0631 \u062f\u06cc\u06af\u0631 \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647.", + "TEXT_PROMPT_TYPE_TEXT": "\u0627\u0639\u0644\u0627\u0646 \u0628\u0631\u0627\u06cc \u0645\u062a\u0646 \u0628\u0627 \u067e\u06cc\u0627\u0645", + "TEXT_PROMPT_TYPE_NUMBER": "\u0627\u0639\u0644\u0627\u0646 \u0628\u0631\u0627\u06cc \u0639\u062f\u062f \u0628\u0627 \u067e\u06cc\u0627\u0645", + "TEXT_PROMPT_TOOLTIP_NUMBER": "\u0627\u0639\u0644\u0627\u0646 \u0628\u0631\u0627\u06cc \u06a9\u0627\u0631\u0628\u0631 \u0628\u0627 \u06cc\u06a9 \u0639\u062f\u062f.", + "TEXT_PROMPT_TOOLTIP_TEXT": "\u0627\u0639\u0644\u0627\u0646 \u0628\u0631\u0627\u06cc \u06a9\u0627\u0631\u0628\u0631 \u0628\u0631\u0627\u06cc \u06cc\u06a9 \u0645\u062a\u0646.", + "LISTS_CREATE_EMPTY_TITLE": "\u0627\u06cc\u062c\u0627\u062f \u0641\u0647\u0631\u0633\u062a \u062e\u0627\u0644\u06cc", + "LISTS_CREATE_EMPTY_TOOLTIP": "\u0641\u0647\u0631\u0633\u062a\u06cc \u0628\u0627 \u0637\u0648\u0644 \u0635\u0641\u0631 \u0634\u0627\u0645\u0644 \u0647\u06cc\u0686 \u0631\u06a9\u0648\u0631\u062f \u062f\u0627\u062f\u0647\u200c\u0627\u06cc \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "LISTS_CREATE_WITH_TOOLTIP": "\u0641\u0647\u0631\u0633\u062a\u06cc \u0627\u0632 \u0647\u0631 \u0639\u062f\u062f\u06cc \u0627\u0632 \u0645\u0648\u0627\u0631\u062f \u0645\u06cc\u200c\u0633\u0627\u0632\u062f.", + "LISTS_CREATE_WITH_INPUT_WITH": "\u0627\u06cc\u062c\u0627\u062f \u0641\u0647\u0631\u0633\u062a \u0628\u0627", + "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "\u0641\u0647\u0631\u0633\u062a", + "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "\u0627\u0636\u0627\u0641\u0647\u200c\u06a9\u0631\u062f\u0646\u060c \u062d\u0630\u0641\u200c\u06a9\u0631\u062f\u0646 \u06cc\u0627 \u062a\u0631\u062a\u06cc\u0628\u200c\u0633\u0627\u0632\u06cc \u0645\u062c\u062f\u062f \u0628\u062e\u0634\u200c\u0647\u0627 \u0627\u06cc\u0646 \u0628\u0644\u0648\u06a9 \u0641\u0647\u0631\u0633\u062a\u06cc.", + "LISTS_CREATE_WITH_ITEM_TOOLTIP": "\u0627\u0636\u0627\u0641\u0647\u200c\u06a9\u0631\u062f\u0646 \u06cc\u06a9 \u0645\u0648\u0631\u062f \u0628\u0647 \u0641\u0647\u0631\u0633\u062a.", + "LISTS_REPEAT_TOOLTIP": "\u0641\u0647\u0631\u0633\u062a\u06cc \u0634\u0627\u0645\u0644 \u0645\u0642\u0627\u062f\u06cc\u0631 \u062f\u0627\u062f\u0647\u200c\u0634\u062f\u0647\u0654 \u062a\u06a9\u0631\u0627\u0631 \u0634\u062f\u0647 \u0639\u062f\u062f \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647 \u0645\u06cc\u200c\u0633\u0627\u0632\u062f.", + "LISTS_REPEAT_TITLE": "\u0641\u0647\u0631\u0633\u062a\u06cc \u0628\u0627 %1 \u062a\u06a9\u0631\u0627\u0631\u0634\u062f\u0647 \u0628\u0647 \u0627\u0646\u062f\u0627\u0632\u0647\u0654 %2 \u0645\u06cc\u200c\u0633\u0627\u0632\u062f", + "LISTS_LENGTH_TITLE": "\u0637\u0648\u0644 %1", + "LISTS_LENGTH_TOOLTIP": "\u0637\u0648\u0644 \u06cc\u06a9 \u0641\u0647\u0631\u0633\u062a \u0631\u0627 \u0628\u0631\u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "LISTS_IS_EMPTY_TITLE": "%1 \u062e\u0627\u0644\u06cc \u0627\u0633\u062a", + "LISTS_TOOLTIP": "\u0627\u06af\u0631 \u0641\u0647\u0631\u0633\u062a \u062e\u0627\u0644\u06cc \u0627\u0633\u062a \u0645\u0642\u062f\u0627\u0631 \u0635\u062c\u06cc\u062c \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "LISTS_INLIST": "\u062f\u0631 \u0641\u0647\u0631\u0633\u062a", + "LISTS_INDEX_OF_FIRST": "\u06cc\u0627\u0641\u062a\u0646 \u0627\u0648\u0644\u06cc\u0646 \u0631\u062e\u200c\u062f\u0627\u062f \u0645\u0648\u0631\u062f", + "LISTS_INDEX_OF_LAST": "\u06cc\u0627\u0641\u062a\u0646 \u0622\u062e\u0631\u06cc\u0646 \u0631\u062e\u200c\u062f\u0627\u062f \u0645\u0648\u0631\u062f", + "LISTS_INDEX_OF_TOOLTIP": "\u0634\u0627\u062e\u0635\u06cc \u0627\u0632 \u0627\u0648\u0644\u06cc\u0646/\u0622\u062e\u0631\u06cc\u0646 \u0631\u062e\u200c\u062f\u0627\u062f \u0645\u0648\u0631\u062f \u062f\u0631 \u0641\u0647\u0631\u0633\u062a \u0631\u0627 \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f. \u06f0 \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f \u0627\u06af\u0631 \u0645\u062a\u0646 \u0645\u0648\u062c\u0648\u062f \u0646\u0628\u0648\u062f.", + "LISTS_GET_INDEX_GET": "\u06af\u0631\u0641\u062a\u0646", + "LISTS_GET_INDEX_GET_REMOVE": "\u06af\u0631\u0641\u062a\u0646 \u0648 \u062d\u0630\u0641\u200c\u06a9\u0631\u062f\u0646", + "LISTS_GET_INDEX_REMOVE": "\u062d\u0630\u0641\u200c\u06a9\u0631\u062f\u0646", + "LISTS_GET_INDEX_FROM_END": "# \u0627\u0632 \u0627\u0646\u062a\u0647\u0627", + "LISTS_GET_INDEX_FIRST": "\u0627\u0648\u0644\u06cc\u0646", + "LISTS_GET_INDEX_LAST": "\u0622\u062e\u0631\u06cc\u0646", + "LISTS_GET_INDEX_RANDOM": "\u062a\u0635\u0627\u062f\u0641\u06cc", + "LISTS_GET_INDEX_TOOLTIP_GET_FROM_START": "\u0645\u0648\u0631\u062f\u06cc \u062f\u0631 \u0645\u062d\u0644 \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647 \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f. #1 \u0627\u0648\u0644\u06cc\u0646 \u0645\u0648\u0631\u062f \u0627\u0633\u062a.", + "LISTS_GET_INDEX_TOOLTIP_GET_FROM_END": "\u0645\u0648\u0631\u062f\u06cc \u062f\u0631 \u0645\u062d\u0644 \u0645\u0634\u062e\u0635 \u062f\u0631 \u0641\u0647\u0631\u0633\u062a \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f. #1 \u0622\u062e\u0631\u06cc\u0646 \u0645\u0648\u0631\u062f \u0627\u0633\u062a.", + "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "\u0627\u0648\u0644\u06cc\u0646 \u0645\u0648\u0631\u062f \u06cc\u06a9 \u0641\u0647\u0631\u0633\u062a \u0631\u0627 \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "\u0622\u062e\u0631\u06cc\u0646 \u0645\u0648\u0631\u062f \u062f\u0631 \u06cc\u06a9 \u0641\u0647\u0631\u0633\u062a \u0631\u0627 \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "\u06cc\u06a9 \u0645\u0648\u0631\u062f \u062a\u0635\u0627\u062f\u0641\u06cc \u062f\u0631 \u06cc\u06a9 \u0641\u0647\u0631\u0633\u062a \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START": "\u0645\u0648\u0631\u062f \u062f\u0631 \u0645\u062d\u0644 \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647 \u062f\u0631 \u0641\u0647\u0631\u0633\u062a \u0631\u0627 \u062d\u0630\u0641 \u0648 \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f. #1 \u0627\u0648\u0644\u06cc\u0646 \u0645\u0648\u0631\u062f \u0627\u0633\u062a.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END": "\u0645\u0648\u0631\u062f \u062f\u0631 \u0645\u062d\u0644 \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647 \u062f\u0631 \u0641\u0647\u0631\u0633\u062a \u0631\u0627 \u062d\u0630\u0641 \u0648 \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f. #1 \u0622\u062e\u0631\u06cc\u0646 \u0645\u0648\u0631\u062f \u0627\u0633\u062a.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "\u0627\u0648\u0644\u06cc\u0646 \u0645\u0648\u0631\u062f \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647 \u062f\u0631 \u0641\u0647\u0631\u0633\u062a \u0631\u0627 \u062d\u0630\u0641 \u0648 \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "\u0622\u062e\u0631\u06cc\u0646 \u0645\u0648\u0631\u062f \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647 \u062f\u0631 \u0641\u0647\u0631\u0633\u062a \u0631\u0627 \u062d\u0630\u0641 \u0648 \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "\u0645\u0648\u0631\u062f \u062a\u0635\u0627\u062f\u0641\u06cc\u200c\u0627\u06cc \u0631\u0627 \u062f\u0631 \u0641\u0647\u0631\u0633\u062a \u062d\u0630\u0641 \u0648 \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START": "\u0645\u0648\u0631\u062f \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647 \u062f\u0631 \u0645\u0648\u0642\u0639\u06cc\u062a \u0645\u0634\u062e\u0635 \u062f\u0631 \u06cc\u06a9 \u0641\u0647\u0631\u0633\u062a \u0631\u0627 \u062d\u0630\u0641 \u0648 \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f. #1 \u0627\u0648\u0644\u06cc\u0646 \u0645\u0648\u0631\u062f \u0627\u0633\u062a.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END": "\u0645\u0648\u0631\u062f \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647 \u062f\u0631 \u0645\u0648\u0642\u0639\u06cc\u062a \u0645\u0634\u062e\u0635 \u062f\u0631 \u06cc\u06a9 \u0641\u0647\u0631\u0633\u062a \u0631\u0627 \u062d\u0630\u0641 \u0648 \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f. #1 \u0622\u062e\u0631\u06cc\u0646 \u0645\u0648\u0631\u062f \u0627\u0633\u062a.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "\u0627\u0648\u0644\u06cc\u0646 \u0645\u0648\u0631\u062f \u0631\u0627 \u062f\u0631 \u06cc\u06a9 \u0641\u0647\u0631\u0633\u062a \u062d\u0630\u0641 \u0645\u06cc\u200c\u06a9\u0646\u062f.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "\u0622\u062e\u0631\u06cc\u0646 \u0645\u0648\u0631\u062f \u0631\u0627 \u062f\u0631 \u06cc\u06a9 \u0641\u0647\u0631\u0633\u062a \u062d\u0630\u0641 \u0645\u06cc\u200c\u06a9\u0646\u062f.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "\u06cc\u06a9 \u0645\u0648\u0631\u062f \u062a\u0635\u0627\u062f\u0641\u06cc \u0631\u0627 \u06cc\u06a9 \u0641\u0647\u0631\u0633\u062a \u062d\u0630\u0641 \u0645\u06cc\u200c\u06a9\u0646\u062f.", + "LISTS_SET_INDEX_SET": "\u0645\u062c\u0645\u0648\u0639\u0647", + "LISTS_SET_INDEX_INSERT": "\u062f\u0631\u062c \u062f\u0631", + "LISTS_SET_INDEX_INPUT_TO": "\u0628\u0647\u200c\u0639\u0646\u0648\u0627\u0646", + "LISTS_SET_INDEX_TOOLTIP_SET_FROM_START": "\u0645\u0648\u0631\u062f \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647 \u062f\u0631 \u06cc\u06a9 \u0641\u0647\u0631\u0633\u062a \u0631\u0627 \u0642\u0631\u0627\u0631 \u0645\u06cc\u200c\u062f\u0647\u062f. #1 \u0627\u0648\u0644\u06cc\u0646 \u0645\u0648\u0631\u062f \u0627\u0633\u062a.", + "LISTS_SET_INDEX_TOOLTIP_SET_FROM_END": "\u0645\u0648\u0631\u062f \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647 \u062f\u0631 \u06cc\u06a9 \u0641\u0647\u0631\u0633\u062a \u0631\u0627 \u0642\u0631\u0627\u0631 \u0645\u06cc\u200c\u062f\u0647\u062f. #1 \u0622\u062e\u0631\u06cc\u0646 \u0645\u0648\u0631\u062f \u0627\u0633\u062a.", + "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "\u0627\u0648\u0644\u06cc\u0646 \u0645\u0648\u0631\u062f \u062f\u0631 \u06cc\u06a9 \u0641\u0647\u0631\u0633\u062a \u0631\u0627 \u062a\u0639\u06cc\u06cc\u0646 \u0645\u06cc\u200c\u06a9\u0646\u062f.", + "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "\u0622\u062e\u0631\u06cc\u0646 \u0645\u0648\u0631\u062f \u062f\u0631 \u06cc\u06a9 \u0641\u0647\u0631\u0633\u062a \u0631\u0627 \u062a\u0639\u06cc\u06cc\u0646 \u0645\u06cc\u200c\u06a9\u0646\u062f.", + "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "\u06cc\u06a9 \u0645\u0648\u0631\u062f \u062a\u0635\u0627\u062f\u0641\u06cc \u062f\u0631 \u06cc\u06a9 \u0641\u0647\u0631\u0633\u062a \u0631\u0627 \u062a\u0639\u06cc\u06cc\u0646 \u0645\u06cc\u200c\u06a9\u0646\u062f.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START": "\u0645\u0648\u0631\u062f\u06cc \u062f\u0631 \u0645\u0648\u0642\u0639\u06cc\u062a \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647 \u062f\u0631 \u06cc\u06a9 \u0641\u0647\u0631\u0633\u062a \u0627\u0636\u0627\u0641\u0647 \u0645\u06cc\u200c\u06a9\u0646\u062f. #1 \u0627\u0648\u0644\u06cc\u0646 \u0645\u0648\u0631\u062f \u0627\u0633\u062a.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END": "\u0645\u0648\u0631\u062f\u06cc \u062f\u0631 \u0645\u0648\u0642\u0639\u06cc\u062a \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647 \u062f\u0631 \u06cc\u06a9 \u0641\u0647\u0631\u0633\u062a \u0627\u0636\u0627\u0641\u0647 \u0645\u06cc\u200c\u06a9\u0646\u062f. #1 \u0622\u062e\u0631\u06cc\u0646 \u0645\u0648\u0631\u062f \u0627\u0633\u062a.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "\u0645\u0648\u0631\u062f\u06cc \u0628\u0647 \u062a\u0647 \u0641\u0647\u0631\u0633\u062a \u0627\u0636\u0627\u0641\u0647 \u0645\u06cc\u200c\u06a9\u0646\u062f.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "\u0645\u0648\u0631\u062f\u06cc \u0628\u0647 \u062a\u0647 \u0641\u0647\u0631\u0633\u062a \u0627\u0644\u062d\u0627\u0642 \u0645\u06cc\u200c\u06a9\u0646\u062f.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "\u0645\u0648\u0631\u062f \u0631\u0627 \u0628\u0647 \u0635\u0648\u0631\u062a \u062a\u0635\u0627\u062f\u0641\u06cc \u062f\u0631 \u06cc\u06a9 \u0641\u0647\u0631\u0633\u062a \u0645\u06cc\u200c\u0627\u0641\u0632\u0627\u06cc\u062f.", + "LISTS_GET_SUBLIST_START_FROM_START": "\u06af\u0631\u0641\u062a\u0646 \u0632\u06cc\u0631\u0645\u062c\u0645\u0648\u0639\u0647\u200c\u0627\u06cc \u0627\u0632 #", + "LISTS_GET_SUBLIST_START_FROM_END": "\u06af\u0631\u0641\u062a\u0646 \u0632\u06cc\u0631\u0645\u062c\u0645\u0648\u0639\u0647\u200c\u0627\u06cc \u0627\u0632 # \u0627\u0632 \u0627\u0646\u062a\u0647\u0627", + "LISTS_GET_SUBLIST_START_FIRST": "\u06af\u0631\u0641\u062a\u0646 \u0632\u06cc\u0631\u0645\u062c\u0645\u0648\u0639\u0647\u200c\u0627\u06cc \u0627\u0632 \u0627\u0628\u062a\u062f\u0627", + "LISTS_GET_SUBLIST_END_FROM_START": "\u0628\u0647 #", + "LISTS_GET_SUBLIST_END_FROM_END": "\u0628\u0647 # \u0627\u0632 \u0627\u0646\u062a\u0647\u0627", + "LISTS_GET_SUBLIST_END_LAST": "\u0628\u0647 \u0622\u062e\u0631\u06cc\u0646", + "LISTS_GET_SUBLIST_TOOLTIP": "\u06a9\u067e\u06cc \u0627\u0632 \u0642\u0633\u0645\u062a \u0645\u0634\u062e\u0635\u200c\u0634\u062f\u0647\u0654 \u0644\u06cc\u0633\u062a \u062f\u0631\u0633\u062a \u0645\u06cc\u200c\u06a9\u0646\u062f.", + "VARIABLES_GET_TOOLTIP": "\u0645\u0642\u062f\u0627\u0631 \u0627\u06cc\u0646 \u0645\u062a\u063a\u06cc\u0631 \u0631\u0627 \u0628\u0631 \u0645\u06cc\u200c\u06af\u0631\u062f\u0627\u0646\u062f.", + "VARIABLES_GET_CREATE_SET": "\u062f\u0631\u0633\u062a\u200c\u06a9\u0631\u062f\u0646 \u00ab\u062a\u0646\u0638\u06cc\u0645 %1\u00bb", + "VARIABLES_SET_TITLE": "\u0645\u062c\u0645\u0648\u0639\u0647", + "VARIABLES_SET_TAIL": "\u0628\u0647", + "VARIABLES_SET_TOOLTIP": "\u0645\u062a\u063a\u06cc\u0631 \u0628\u0631\u0627\u0628\u0631 \u0628\u0627 \u062e\u0631\u0648\u062c\u06cc \u0631\u0627 \u0645\u0634\u062e\u0635 \u0645\u06cc\u200c\u06a9\u0646\u062f.", + "VARIABLES_SET_CREATE_GET": "\u062f\u0631\u0633\u062a\u200c\u06a9\u0631\u062f\u0646 \u00ab\u06af\u0631\u0641\u062a\u0646 %1\u00bb", + "PROCEDURES_DEFNORETURN_TITLE": "\u0628\u0647", + "PROCEDURES_DEFNORETURN_PROCEDURE": "\u0627\u0646\u062c\u0627\u0645 \u0686\u06cc\u0632\u06cc", + "PROCEDURES_BEFORE_PARAMS": "\u0628\u0627:", + "PROCEDURES_DEFNORETURN_TOOLTIP": "\u062a\u0627\u0628\u0639\u06cc \u0645\u06cc\u200c\u0633\u0627\u0632\u062f \u0628\u062f\u0648\u0646 \u0647\u06cc\u0686 \u062e\u0631\u0648\u062c\u06cc.", + "PROCEDURES_DEFRETURN_RETURN": "\u0628\u0627\u0632\u06af\u0634\u062a", + "PROCEDURES_DEFRETURN_TOOLTIP": "\u062a\u0627\u0628\u0639\u06cc \u0628\u0627 \u06cc\u06a9 \u062e\u0631\u0648\u062c\u06cc \u0645\u06cc\u200c\u0633\u0627\u0632\u062f.", + "PROCEDURES_DEF_DUPLICATE_WARNING": "\u0627\u062e\u0637\u0627\u0631: \u0627\u06cc\u0646 \u062a\u0627\u0628\u0639\u06cc \u067e\u0627\u0631\u0627\u0645\u062a\u0631 \u062a\u06a9\u0631\u0627\u0631\u06cc \u062f\u0627\u0631\u062f.", + "PROCEDURES_CALLNORETURN_HELPURL": "http://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29", + "PROCEDURES_CALLNORETURN_TOOLTIP": "\u0627\u062c\u0631\u0627\u06cc \u062a\u0627\u0628\u0639 \u062a\u0639\u0631\u06cc\u0641\u200c\u0634\u062f\u0647 \u062a\u0648\u0633\u0637 \u06a9\u0627\u0631\u0628\u0631 \u00ab%1\u00bb.", + "PROCEDURES_CALLRETURN_HELPURL": "http://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29", + "PROCEDURES_CALLRETURN_TOOLTIP": "\u0627\u062c\u0631\u0627\u06cc \u062a\u0627\u0628\u0639 \u062a\u0639\u0631\u06cc\u0641\u200c\u0634\u062f\u0647 \u062a\u0648\u0633\u0637 \u06a9\u0627\u0631\u0628\u0631 \u00ab%1\u00bb \u0648 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 \u062e\u0631\u0648\u062c\u06cc \u0622\u0646.", + "PROCEDURES_MUTATORCONTAINER_TITLE": "\u0648\u0631\u0648\u062f\u06cc\u200c\u0647\u0627", + "PROCEDURES_MUTATORARG_TITLE": "\u0646\u0627\u0645 \u0648\u0631\u0648\u062f\u06cc:", + "PROCEDURES_HIGHLIGHT_DEF": "\u0628\u0631\u062c\u0633\u062a\u0647\u200c\u0633\u0627\u0632\u06cc \u062a\u0639\u0631\u06cc\u0641 \u062a\u0627\u0628\u0639", + "PROCEDURES_CREATE_DO": "\u0633\u0627\u062e\u062a\u0646 \u00ab%1\u00bb", + "PROCEDURES_IFRETURN_TOOLTIP": "\u0627\u06af\u0631 \u06cc\u06a9 \u0645\u0642\u062f\u0627\u0631 \u0635\u062d\u06cc\u062d \u0627\u0633\u062a\u060c \u0645\u0642\u062f\u0627\u0631 \u062f\u0648\u0645 \u0631\u0627 \u0628\u0631\u06af\u0631\u062f\u0627\u0646.", + "PROCEDURES_IFRETURN_WARNING": "\u0627\u062e\u0637\u0627\u0631: \u0627\u06cc\u0646 \u0628\u0644\u0648\u06af \u0627\u062d\u062a\u0645\u0627\u0644\u0627\u064b \u0641\u0642\u0637 \u062f\u0627\u062e\u0644 \u06cc\u06a9 \u062a\u0627\u0628\u0639 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc\u200c\u0634\u0648\u062f." +} \ No newline at end of file diff --git a/msg/json/fr.json b/msg/json/fr.json new file mode 100644 index 000000000..ece8861d0 --- /dev/null +++ b/msg/json/fr.json @@ -0,0 +1,306 @@ +{ + "@metadata": { + "authors": [ + "Espertus", + "Gomoko" + ] + }, + "VARIABLES_DEFAULT_NAME": "\u00e9l\u00e9ment", + "DUPLICATE_BLOCK": "Dupliquer", + "ADD_COMMENT": "Ajouter un commentaire", + "REMOVE_COMMENT": "Supprimer un commentaire", + "EXTERNAL_INPUTS": "Entr\u00e9es externes", + "INLINE_INPUTS": "Entr\u00e9es en ligne", + "DELETE_BLOCK": "Supprimer le bloc", + "DELETE_X_BLOCKS": "Supprimer %1 blocs", + "COLLAPSE_BLOCK": "R\u00e9duire le bloc", + "COLLAPSE_ALL": "R\u00e9duire les blocs", + "EXPAND_BLOCK": "D\u00e9velopper le bloc", + "EXPAND_ALL": "D\u00e9velopper les blocs", + "DISABLE_BLOCK": "D\u00e9sactiver le bloc", + "ENABLE_BLOCK": "Activer le bloc", + "HELP": "Aide", + "CHANGE_VALUE_TITLE": "Modifier la valeur :", + "NEW_VARIABLE": "Nouvelle variable\u2026", + "NEW_VARIABLE_TITLE": "Nom de la nouvelle variable :", + "RENAME_VARIABLE": "Renommer la variable\u2026", + "RENAME_VARIABLE_TITLE": "Renommer toutes les variables '%1' en :", + "COLOUR_PICKER_HELPURL": "http://fr.wikipedia.org/wiki/Couleur", + "COLOUR_PICKER_TOOLTIP": "Choisir une couleur dans la palette", + "COLOUR_RANDOM_TITLE": "couleur al\u00e9atoire", + "COLOUR_RANDOM_TOOLTIP": "Choisir une couleur au hasard.", + "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", + "COLOUR_RGB_TITLE": "colorer avec", + "COLOUR_RGB_RED": "rouge", + "COLOUR_RGB_GREEN": "vert", + "COLOUR_RGB_BLUE": "bleu", + "COLOUR_RGB_TOOLTIP": "Cr\u00e9er une couleur avec la quantit\u00e9 sp\u00e9cifi\u00e9e de rouge, vert et bleu. Toutes les valeurs doivent \u00eatre entre 0 et 100.", + "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", + "COLOUR_BLEND_TITLE": "m\u00e9langer", + "COLOUR_BLEND_COLOUR1": "couleur 1", + "COLOUR_BLEND_COLOUR2": "couleur 2", + "COLOUR_BLEND_RATIO": "ratio", + "COLOUR_BLEND_TOOLTIP": "M\u00e9lange deux couleurs ensemble avec un ratio donn\u00e9 (0.0 - 1.0).", + "CONTROLS_REPEAT_HELPURL": "http://en.wikipedia.org/wiki/For_loop", + "CONTROLS_REPEAT_TITLE": "r\u00e9p\u00e9ter %1 fois", + "CONTROLS_REPEAT_TITLE_REPEAT": "r\u00e9p\u00e9ter", + "CONTROLS_REPEAT_TITLE_TIMES": "fois", + "CONTROLS_REPEAT_INPUT_DO": "faire", + "CONTROLS_REPEAT_TOOLTIP": "Ex\u00e9cuter certains ordres plusieurs fois.", + "CONTROLS_WHILEUNTIL_HELPURL": "http://code.google.com/p/blockly/wiki/Repeat", + "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "r\u00e9p\u00e9ter tant que", + "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "r\u00e9p\u00e9ter jusqu\u2019\u00e0", + "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Tant qu\u2019une valeur est vraie, alors ex\u00e9cuter certains ordres.", + "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Tant qu\u2019une valeur est fausse, alors ex\u00e9cuter certains ordres.", + "CONTROLS_FOR_HELPURL": "https://code.google.com/p/blockly/wiki/Loops#count_with", + "CONTROLS_FOR_TOOLTIP": "Faire en sorte que la variable %1 prenne les valeurs depuis le num\u00e9ro de d\u00e9but jusqu\u2019au num\u00e9ro de fin, en s\u2019incr\u00e9mentant de l\u2019intervalle sp\u00e9cifi\u00e9, et ex\u00e9cuter les ordres sp\u00e9cifi\u00e9s.", + "CONTROLS_FOR_INPUT_WITH": "compter avec", + "CONTROLS_FOR_INPUT_FROM_TO_BY": "de %1 \u00e0 %2 par %3", + "CONTROLS_FOREACH_HELPURL": "https://code.google.com/p/blockly/wiki/Loops#for_each pour chaque bloc", + "CONTROLS_FOREACH_INPUT_ITEM": "pour chaque \u00e9l\u00e9ment", + "CONTROLS_FOREACH_INPUT_INLIST": "dans la liste", + "CONTROLS_FOREACH_TOOLTIP": "Pour chaque \u00e9l\u00e9ment dans une liste, donner la valeur de l\u2019\u00e9l\u00e9ment \u00e0 la variable '%1', puis ex\u00e9cuter certains ordres.", + "CONTROLS_FLOW_STATEMENTS_HELPURL": "https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "sortir de la boucle", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "continuer avec la prochaine it\u00e9ration de la boucle", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Sortir de la boucle englobante.", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Sauter le reste de cette boucle, et poursuivre avec l\u2019it\u00e9ration suivante.", + "CONTROLS_FLOW_STATEMENTS_WARNING": "Attention : Ce bloc ne devrait \u00eatre utilis\u00e9 que dans une boucle.", + "CONTROLS_IF_HELPURL": "http://code.google.com/p/blockly/wiki/If_Then", + "CONTROLS_IF_TOOLTIP_1": "Si une valeur est vraie, alors ex\u00e9cuter certains ordres.", + "CONTROLS_IF_TOOLTIP_2": "Si une valeur est vraie, alors ex\u00e9cuter le premier bloc d\u2019ordres. Sinon, ex\u00e9cuter le second bloc d\u2019ordres.", + "CONTROLS_IF_TOOLTIP_3": "Si la premi\u00e8re valeur est vraie, alors ex\u00e9cuter le premier bloc d\u2019ordres. Sinon, si la seconde valeur est vraie, ex\u00e9cuter le second bloc d\u2019ordres.", + "CONTROLS_IF_TOOLTIP_4": "Si la premi\u00e8re valeur est vraie, alors ex\u00e9cuter le premier bloc d\u2019ordres. Sinon, si la seconde valeur est vraie, ex\u00e9cuter le second bloc d\u2019ordres. Si aucune des valeurs n\u2019est vraie, ex\u00e9cuter le dernier bloc d\u2019ordres.", + "CONTROLS_IF_MSG_IF": "si", + "CONTROLS_IF_MSG_ELSEIF": "sinon si", + "CONTROLS_IF_MSG_ELSE": "sinon", + "CONTROLS_IF_IF_TOOLTIP": "Ajouter, supprimer ou r\u00e9ordonner les sections pour reconfigurer ce bloc si.", + "CONTROLS_IF_ELSEIF_TOOLTIP": "Ajouter une condition au bloc si.", + "CONTROLS_IF_ELSE_TOOLTIP": "Ajouter une condition finale fourre-tout au bloc si.", + "LOGIC_COMPARE_HELPURL": "http://en.wikipedia.org/wiki/Inequality_(mathematics)", + "LOGIC_COMPARE_TOOLTIP_EQ": "Renvoyer vrai si les deux entr\u00e9es sont \u00e9gales.", + "LOGIC_COMPARE_TOOLTIP_NEQ": "Renvoyer vrai si les deux entr\u00e9es ne sont pas \u00e9gales.", + "LOGIC_COMPARE_TOOLTIP_LT": "Renvoyer vrai si la premi\u00e8re entr\u00e9e est plus petite que la seconde.", + "LOGIC_COMPARE_TOOLTIP_LTE": "Renvoyer vrai si la premi\u00e8re entr\u00e9e est plus petite ou \u00e9gale \u00e0 la seconde.", + "LOGIC_COMPARE_TOOLTIP_GT": "Renvoyer vrai si la premi\u00e8re entr\u00e9e est plus grande que la seconde.", + "LOGIC_COMPARE_TOOLTIP_GTE": "Renvoyer vrai si la premi\u00e8re entr\u00e9e est plus grande ou \u00e9gale \u00e0 la seconde.", + "LOGIC_OPERATION_HELPURL": "http://code.google.com/p/blockly/wiki/And_Or", + "LOGIC_OPERATION_TOOLTIP_AND": "Renvoyer vrai si les deux entr\u00e9es sont vraies.", + "LOGIC_OPERATION_AND": "et", + "LOGIC_OPERATION_TOOLTIP_OR": "Renvoyer vrai si au moins une des entr\u00e9es est vraie.", + "LOGIC_OPERATION_OR": "ou", + "LOGIC_NEGATE_HELPURL": "http://code.google.com/p/blockly/wiki/Not", + "LOGIC_NEGATE_TITLE": "pas %1", + "LOGIC_NEGATE_TOOLTIP": "Renvoie vrai si l\u2019entr\u00e9e est fausse. Renvoie faux si l\u2019entr\u00e9e est vraie.", + "LOGIC_BOOLEAN_HELPURL": "http://code.google.com/p/blockly/wiki/True_False", + "LOGIC_BOOLEAN_TRUE": "vrai", + "LOGIC_BOOLEAN_FALSE": "faux", + "LOGIC_BOOLEAN_TOOLTIP": "Renvoie soit vrai soit faux.", + "LOGIC_NULL_HELPURL": "http://en.wikipedia.org/wiki/Nullable_type", + "LOGIC_NULL": "nul", + "LOGIC_NULL_TOOLTIP": "Renvoie nul.", + "LOGIC_TERNARY_HELPURL": "http://en.wikipedia.org/wiki/%3F:", + "LOGIC_TERNARY_CONDITION": "test", + "LOGIC_TERNARY_IF_TRUE": "si vrai", + "LOGIC_TERNARY_IF_FALSE": "si faux", + "LOGIC_TERNARY_TOOLTIP": "V\u00e9rifier la condition dans 'test'. Si elle est vraie, renvoie la valeur 'si vrai'\u202f; sinon renvoie la valeur 'si faux'.", + "MATH_NUMBER_HELPURL": "http://en.wikipedia.org/wiki/Number", + "MATH_NUMBER_TOOLTIP": "Un nombre.", + "MATH_ARITHMETIC_HELPURL": "http://en.wikipedia.org/wiki/Arithmetic", + "MATH_ARITHMETIC_TOOLTIP_ADD": "Renvoie la somme des deux nombres.", + "MATH_ARITHMETIC_TOOLTIP_MINUS": "Renvoie la diff\u00e9rence des deux nombres.", + "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Renvoie le produit des deux nombres.", + "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Renvoie le quotient des deux nombres.", + "MATH_ARITHMETIC_TOOLTIP_POWER": "Renvoie le premier nombre \u00e9lev\u00e9 \u00e0 la puissance du second.", + "MATH_SINGLE_HELPURL": "http://en.wikipedia.org/wiki/Square_root", + "MATH_SINGLE_OP_ROOT": "racine carr\u00e9e", + "MATH_SINGLE_TOOLTIP_ROOT": "Renvoie la racine carr\u00e9e d\u2019un nombre.", + "MATH_SINGLE_OP_ABSOLUTE": "absolu", + "MATH_SINGLE_TOOLTIP_ABS": "Renvoie la valeur absolue d\u2019un nombre.", + "MATH_SINGLE_TOOLTIP_NEG": "Renvoie l\u2019oppos\u00e9 d\u2019un nombre", + "MATH_SINGLE_TOOLTIP_LN": "Renvoie le logarithme naturel d\u2019un nombre.", + "MATH_SINGLE_TOOLTIP_LOG10": "Renvoie le logarithme base 10 d\u2019un nombre.", + "MATH_SINGLE_TOOLTIP_EXP": "Renvoie e \u00e0 la puissance d\u2019un nombre.", + "MATH_SINGLE_TOOLTIP_POW10": "Renvoie 10 \u00e0 la puissance d\u2019un nombre.", + "MATH_TRIG_HELPURL": "http://en.wikipedia.org/wiki/Trigonometric_functions", + "MATH_TRIG_TOOLTIP_SIN": "Renvoie le sinus d\u2019un angle en degr\u00e9s (pas en radians).", + "MATH_TRIG_TOOLTIP_COS": "Renvoie le cosinus d\u2019un angle en degr\u00e9s (pas en radians).", + "MATH_TRIG_TOOLTIP_TAN": "Renvoie la tangente d\u2019un angle en degr\u00e9s (pas en radians).", + "MATH_TRIG_TOOLTIP_ASIN": "Renvoie l\u2019arcsinus d\u2019un nombre.", + "MATH_TRIG_TOOLTIP_ACOS": "Renvoie l\u2019arccosinus d\u2019un nombre.", + "MATH_TRIG_TOOLTIP_ATAN": "Renvoie l\u2019arctangente d\u2019un nombre.", + "MATH_CONSTANT_HELPURL": "http://en.wikipedia.org/wiki/Mathematical_constant", + "MATH_CONSTANT_TOOLTIP": "Renvoie une des constantes courantes : \u03c0 (3.141\u2026), e (2.718\u2026), \u03c6 (1.618\u2026), sqrt(2) (1.414\u2026), sqrt(\u00bd) (0.707\u2026), ou \u221e (infini).", + "MATH_IS_EVEN": "est pair", + "MATH_IS_ODD": "est impair", + "MATH_IS_PRIME": "est premier", + "MATH_IS_WHOLE": "est entier", + "MATH_IS_POSITIVE": "est positif", + "MATH_IS_NEGATIVE": "est n\u00e9gatif", + "MATH_IS_DIVISIBLE_BY": "est divisible par", + "MATH_IS_TOOLTIP": "V\u00e9rifier si un nombre est pair, impair, premier, entier, positif, n\u00e9gatif, ou s\u2019il est divisible par un certain nombre. Renvoie vrai ou faux.", + "MATH_CHANGE_TITLE_CHANGE": "incr\u00e9menter", + "MATH_CHANGE_INPUT_BY": "de", + "MATH_CHANGE_TOOLTIP": "Ajouter un nombre \u00e0 la variable '%1'.", + "MATH_ROUND_HELPURL": "http://en.wikipedia.org/wiki/Rounding", + "MATH_ROUND_TOOLTIP": "Arrondir un nombre au-dessus ou au-dessous.", + "MATH_ROUND_OPERATOR_ROUND": "arrondir", + "MATH_ROUND_OPERATOR_ROUNDUP": "arrondir au sup\u00e9rieur", + "MATH_ROUND_OPERATOR_ROUNDDOWN": "arrondir \u00e0 l\u2019inf\u00e9rieur", + "MATH_ONLIST_OPERATOR_SUM": "somme de la liste", + "MATH_ONLIST_TOOLTIP_SUM": "Renvoyer la somme de tous les nombres dans la liste.", + "MATH_ONLIST_OPERATOR_MIN": "minimum de la liste", + "MATH_ONLIST_TOOLTIP_MIN": "Renvoyer le plus petit nombre dans la liste.", + "MATH_ONLIST_OPERATOR_MAX": "maximum de la liste", + "MATH_ONLIST_TOOLTIP_MAX": "Renvoyer le plus grand nombre dans la liste.", + "MATH_ONLIST_OPERATOR_AVERAGE": "moyenne de la liste", + "MATH_ONLIST_TOOLTIP_AVERAGE": "Renvoyer la moyenne (arithm\u00e9tique) des valeurs num\u00e9riques dans la liste.", + "MATH_ONLIST_OPERATOR_MEDIAN": "m\u00e9diane de la liste", + "MATH_ONLIST_TOOLTIP_MEDIAN": "Renvoyer le nombre m\u00e9dian dans la liste.", + "MATH_ONLIST_OPERATOR_MODE": "majoritaires de la liste", + "MATH_ONLIST_TOOLTIP_MODE": "Renvoyer une liste des \u00e9l\u00e9ment(s) le(s) plus courant(s) dans la liste.", + "MATH_ONLIST_OPERATOR_STD_DEV": "\u00e9cart-type de la liste", + "MATH_ONLIST_TOOLTIP_STD_DEV": "Renvoyer l\u2019\u00e9cart-type de la liste.", + "MATH_ONLIST_OPERATOR_RANDOM": "\u00e9l\u00e9ment al\u00e9atoire de la liste", + "MATH_ONLIST_TOOLTIP_RANDOM": "Renvoyer un \u00e9l\u00e9ment dans la liste au hasard.", + "MATH_MODULO_HELPURL": "http://en.wikipedia.org/wiki/Modulo_operation", + "MATH_MODULO_TITLE": "reste de %1 \u00f7 %2", + "MATH_MODULO_TOOLTIP": "Renvoyer le reste de la division des deux nombres.", + "MATH_CONSTRAIN_TITLE": "contraindre %1 entre %2 et %3", + "MATH_CONSTRAIN_TOOLTIP": "Contraindre un nombre \u00e0 \u00eatre entre les limites sp\u00e9cifi\u00e9es (incluses).", + "MATH_RANDOM_INT_HELPURL": "http://en.wikipedia.org/wiki/Random_number_generation", + "MATH_RANDOM_INT_TITLE": "entier al\u00e9atoire entre %1 et %2", + "MATH_RANDOM_INT_TOOLTIP": "Renvoyer un entier al\u00e9atoire entre les deux limites sp\u00e9cifi\u00e9es, incluses.", + "MATH_RANDOM_FLOAT_HELPURL": "http://en.wikipedia.org/wiki/Random_number_generation", + "MATH_RANDOM_FLOAT_TITLE_RANDOM": "fraction al\u00e9atoire", + "MATH_RANDOM_FLOAT_TOOLTIP": "Renvoyer une fraction al\u00e9atoire entre 0.0 (inclus) et 1.0 (exclus).", + "TEXT_TEXT_HELPURL": "http://en.wikipedia.org/wiki/String_(computer_science)", + "TEXT_TEXT_TOOLTIP": "Une lettre, un mot ou une ligne de texte.", + "TEXT_JOIN_TITLE_CREATEWITH": "cr\u00e9er le texte avec", + "TEXT_JOIN_TOOLTIP": "Cr\u00e9er un morceau de texte en agr\u00e9geant un nombre quelconque d\u2019\u00e9l\u00e9ments.", + "TEXT_CREATE_JOIN_TITLE_JOIN": "joindre", + "TEXT_CREATE_JOIN_TOOLTIP": "Ajouter, supprimer, ou r\u00e9ordonner des sections pour reconfigurer ce bloc de texte.", + "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Ajouter un \u00e9l\u00e9ment au texte.", + "TEXT_APPEND_TO": "\u00e0", + "TEXT_APPEND_APPENDTEXT": "ajouter le texte", + "TEXT_APPEND_TOOLTIP": "Ajouter du texte \u00e0 la variable '%1'.", + "TEXT_LENGTH_TITLE": "longueur de %1", + "TEXT_LENGTH_TOOLTIP": "Renvoie le nombre de lettres (espaces compris) dans le texte fourni.", + "TEXT_ISEMPTY_TITLE": "%1 est vide", + "TEXT_ISEMPTY_TOOLTIP": "Renvoie vrai si le texte fourni est vide.", + "TEXT_INDEXOF_TOOLTIP": "Renvoie l\u2019index de la premi\u00e8re/derni\u00e8re occurrence de la premi\u00e8re cha\u00eene dans la seconde. Renvoie 0 si la cha\u00eene n\u2019est pas trouv\u00e9e.", + "TEXT_INDEXOF_INPUT_INTEXT": "dans le texte", + "TEXT_INDEXOF_OPERATOR_FIRST": "trouver la premi\u00e8re occurrence de la cha\u00eene", + "TEXT_INDEXOF_OPERATOR_LAST": "trouver la derni\u00e8re occurrence de la cha\u00eene", + "TEXT_CHARAT_INPUT_INTEXT": "dans le texte", + "TEXT_CHARAT_FROM_START": "obtenir la lettre #", + "TEXT_CHARAT_FROM_END": "obtenir la lettre # depuis la fin", + "TEXT_CHARAT_FIRST": "obtenir la premi\u00e8re lettre", + "TEXT_CHARAT_LAST": "obtenir la derni\u00e8re lettre", + "TEXT_CHARAT_RANDOM": "obtenir une lettre au hasard", + "TEXT_CHARAT_TOOLTIP": "Renvoie la lettre \u00e0 la position indiqu\u00e9e.", + "TEXT_GET_SUBSTRING_TOOLTIP": "Renvoie une partie indiqu\u00e9e du texte.", + "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "dans le texte", + "TEXT_GET_SUBSTRING_START_FROM_START": "obtenir la sous-cha\u00eene depuis la lettre #", + "TEXT_GET_SUBSTRING_START_FROM_END": "obtenir la sous-cha\u00eene depuis la lettre # depuis la fin", + "TEXT_GET_SUBSTRING_START_FIRST": "obtenir la sous-cha\u00eene depuis la premi\u00e8re lettre", + "TEXT_GET_SUBSTRING_END_FROM_START": "jusqu\u2019\u00e0 la lettre #", + "TEXT_GET_SUBSTRING_END_FROM_END": "jusqu\u2019\u00e0 la lettre # depuis la fin", + "TEXT_GET_SUBSTRING_END_LAST": "jusqu\u2019\u00e0 la derni\u00e8re lettre", + "TEXT_CHANGECASE_TOOLTIP": "Renvoyer une copie du texte dans une autre casse.", + "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "en MAJUSCULES", + "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "en minuscules", + "TEXT_CHANGECASE_OPERATOR_TITLECASE": "en Majuscule Au D\u00e9but De Chaque Mot", + "TEXT_TRIM_TOOLTIP": "Renvoyer une copie du texte avec les espaces supprim\u00e9s d\u2019un bout ou des deux.", + "TEXT_TRIM_OPERATOR_BOTH": "supprimer les espaces des deux c\u00f4t\u00e9s", + "TEXT_TRIM_OPERATOR_LEFT": "supprimer les espaces du c\u00f4t\u00e9 gauche", + "TEXT_TRIM_OPERATOR_RIGHT": "supprimer les espaces du c\u00f4t\u00e9 droit", + "TEXT_PRINT_TITLE": "afficher %1", + "TEXT_PRINT_TOOLTIP": "Afficher le texte, le nombre ou une autre valeur sp\u00e9cifi\u00e9.", + "TEXT_PROMPT_TYPE_TEXT": "invite pour un texte avec un message", + "TEXT_PROMPT_TYPE_NUMBER": "invite pour un nombre avec un message", + "TEXT_PROMPT_TOOLTIP_NUMBER": "Demander un nombre \u00e0 l\u2019utilisateur.", + "TEXT_PROMPT_TOOLTIP_TEXT": "Demander un texte \u00e0 l\u2019utilisateur.", + "LISTS_CREATE_EMPTY_TITLE": "cr\u00e9er une liste vide", + "LISTS_CREATE_EMPTY_TOOLTIP": "Renvoyer une liste, de longueur 0, ne contenant aucun enregistrement", + "LISTS_CREATE_WITH_TOOLTIP": "Cr\u00e9er une liste avec un nombre quelconque d\u2019\u00e9l\u00e9ments.", + "LISTS_CREATE_WITH_INPUT_WITH": "cr\u00e9er une liste avec", + "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "liste", + "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Ajouter, supprimer, ou r\u00e9ordonner les sections pour reconfigurer ce bloc de liste.", + "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Ajouter un \u00e9l\u00e9ment \u00e0 la liste.", + "LISTS_REPEAT_TOOLTIP": "Cr\u00e9e une liste consistant en la valeur fournie r\u00e9p\u00e9t\u00e9e le nombre de fois indiqu\u00e9.", + "LISTS_REPEAT_TITLE": "cr\u00e9er une liste avec l\u2019\u00e9l\u00e9ment %1 r\u00e9p\u00e9t\u00e9 %2 fois", + "LISTS_LENGTH_TITLE": "longueur de %1", + "LISTS_LENGTH_TOOLTIP": "Renvoie la longueur d\u2019une liste.", + "LISTS_IS_EMPTY_TITLE": "%1 est vide", + "LISTS_TOOLTIP": "Renvoie vrai si la liste est vide.", + "LISTS_INLIST": "dans la liste", + "LISTS_INDEX_OF_FIRST": "trouver la premi\u00e8re occurrence de l\u2019\u00e9l\u00e9ment", + "LISTS_INDEX_OF_LAST": "trouver la derni\u00e8re occurrence de l\u2019\u00e9l\u00e9ment", + "LISTS_INDEX_OF_TOOLTIP": "Renvoie l\u2019index de la premi\u00e8re/derni\u00e8re occurrence de l\u2019\u00e9l\u00e9ment dans la liste. Renvoie 0 si le texte n\u2019est pas trouv\u00e9.", + "LISTS_GET_INDEX_GET": "obtenir", + "LISTS_GET_INDEX_GET_REMOVE": "obtenir et supprimer", + "LISTS_GET_INDEX_REMOVE": "supprimer", + "LISTS_GET_INDEX_FROM_END": "# depuis la fin", + "LISTS_GET_INDEX_FIRST": "premier", + "LISTS_GET_INDEX_LAST": "dernier", + "LISTS_GET_INDEX_RANDOM": "al\u00e9atoire", + "LISTS_GET_INDEX_TOOLTIP_GET_FROM_START": "Renvoie l\u2019\u00e9l\u00e9ment \u00e0 la position indiqu\u00e9e dans une liste. #1 est le premier \u00e9l\u00e9ment.", + "LISTS_GET_INDEX_TOOLTIP_GET_FROM_END": "Renvoie l\u2019\u00e9l\u00e9ment \u00e0 la position indiqu\u00e9e dans une liste. #1 est le dernier \u00e9l\u00e9ment.", + "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Renvoie le premier \u00e9l\u00e9ment dans une liste.", + "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Renvoie le dernier \u00e9l\u00e9ment dans une liste.", + "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Renvoie un \u00e9l\u00e9ment au hasard dans une liste.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START": "Supprime et renvoie l\u2019\u00e9l\u00e9ment \u00e0 la position indiqu\u00e9e dans une liste. #1 est le premier \u00e9l\u00e9ment.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END": "Supprime et renvoie l\u2019\u00e9l\u00e9ment \u00e0 la position indiqu\u00e9e dans une liste. #1 est le dernier \u00e9l\u00e9ment.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Supprime et renvoie le premier \u00e9l\u00e9ment dans une liste.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Supprime et renvoie le dernier \u00e9l\u00e9ment dans une liste.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Supprime et renvoie un \u00e9l\u00e9ment au hasard dans une liste.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START": "Supprime l\u2019\u00e9l\u00e9ment \u00e0 la position indiqu\u00e9e dans une liste. #1 est le premier \u00e9l\u00e9ment.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END": "Supprime l\u2019\u00e9l\u00e9ment \u00e0 la position indiqu\u00e9e dans une liste. #1 est le dernier \u00e9l\u00e9ment.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Supprime le premier \u00e9l\u00e9ment dans une liste.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Supprime le dernier \u00e9l\u00e9ment dans une liste.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Supprime un \u00e9l\u00e9ment au hasard dans une liste.", + "LISTS_SET_INDEX_SET": "mettre", + "LISTS_SET_INDEX_INSERT": "ins\u00e9rer en", + "LISTS_SET_INDEX_INPUT_TO": "comme", + "LISTS_SET_INDEX_TOOLTIP_SET_FROM_START": "Fixe l\u2019\u00e9l\u00e9ment \u00e0 la position indiqu\u00e9e dans une liste. #1 est le premier \u00e9l\u00e9ment.", + "LISTS_SET_INDEX_TOOLTIP_SET_FROM_END": "Fixe l\u2019\u00e9l\u00e9ment \u00e0 la position indiqu\u00e9e dans une liste. #1 est le dernier \u00e9l\u00e9ment.", + "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Fixe le premier \u00e9l\u00e9ment dans une liste.", + "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Fixe le dernier \u00e9l\u00e9ment dans une liste.", + "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Fixe un \u00e9l\u00e9ment au hasard dans une liste.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START": "Ins\u00e8re l\u2019\u00e9l\u00e9ment \u00e0 la position indiqu\u00e9e dans une liste. #1 est le premier \u00e9l\u00e9ment.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END": "Ins\u00e8re l\u2019\u00e9l\u00e9ment \u00e0 la position indiqu\u00e9e dans une liste. #1 est le dernier \u00e9l\u00e9ment.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Ins\u00e8re l\u2019\u00e9l\u00e9ment au d\u00e9but d\u2019une liste.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Ajouter l\u2019\u00e9l\u00e9ment \u00e0 la fin d\u2019une liste.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Ins\u00e8re l\u2019\u00e9l\u00e9ment au hasard dans une liste.", + "LISTS_GET_SUBLIST_START_FROM_START": "obtenir la sous-liste depuis #", + "LISTS_GET_SUBLIST_START_FROM_END": "obtenir la sous-liste depuis # depuis la fin", + "LISTS_GET_SUBLIST_START_FIRST": "obtenir la sous-liste depuis le d\u00e9but", + "LISTS_GET_SUBLIST_END_FROM_START": "jusqu\u2019\u00e0 #", + "LISTS_GET_SUBLIST_END_FROM_END": "jusqu\u2019\u00e0 # depuis la fin", + "LISTS_GET_SUBLIST_END_LAST": "jusqu\u2019\u00e0 la fin", + "LISTS_GET_SUBLIST_TOOLTIP": "Cr\u00e9e une copie de la partie sp\u00e9cifi\u00e9e d\u2019une liste.", + "VARIABLES_GET_TOOLTIP": "Renvoie la valeur de cette variable.", + "VARIABLES_GET_CREATE_SET": "Cr\u00e9er 'fixer %1'", + "VARIABLES_SET_TITLE": "fixer", + "VARIABLES_SET_TAIL": "\u00e0", + "VARIABLES_SET_TOOLTIP": "Fixe cette variable pour qu\u2019elle soit \u00e9gale \u00e0 la valeur de l\u2019entr\u00e9e.", + "VARIABLES_SET_CREATE_GET": "Cr\u00e9er 'obtenir %1'", + "PROCEDURES_DEFNORETURN_TITLE": "\u00e0", + "PROCEDURES_DEFNORETURN_PROCEDURE": "faire quelque chose", + "PROCEDURES_BEFORE_PARAMS": "avec :", + "PROCEDURES_DEFNORETURN_TOOLTIP": "Cr\u00e9e une fonction sans sortie.", + "PROCEDURES_DEFRETURN_RETURN": "retour", + "PROCEDURES_DEFRETURN_TOOLTIP": "Cr\u00e9e une fonction avec une sortie.", + "PROCEDURES_DEF_DUPLICATE_WARNING": "Attention : Cette fonction a des param\u00e8tres dupliqu\u00e9s.", + "PROCEDURES_CALLNORETURN_HELPURL": "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29", + "PROCEDURES_CALLNORETURN_TOOLTIP": "Ex\u00e9cuter la fonction '%1' d\u00e9finie par l\u2019utilisateur.", + "PROCEDURES_CALLRETURN_HELPURL": "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29", + "PROCEDURES_CALLRETURN_TOOLTIP": "Ex\u00e9cuter la fonction '%1' d\u00e9finie par l\u2019utilisateur et utiliser son r\u00e9sultat.", + "PROCEDURES_MUTATORCONTAINER_TITLE": "entr\u00e9es", + "PROCEDURES_MUTATORARG_TITLE": "nom de l\u2019entr\u00e9e :", + "PROCEDURES_HIGHLIGHT_DEF": "Surligner la d\u00e9finition de la fonction", + "PROCEDURES_CREATE_DO": "Cr\u00e9er '%1'", + "PROCEDURES_IFRETURN_TOOLTIP": "Si une valeur est vraie, alors renvoyer une seconde valeur.", + "PROCEDURES_IFRETURN_WARNING": "Attention : Ce bloc pourrait n\u2019\u00eatre utilis\u00e9 que dans une d\u00e9finition de fonction." +} \ No newline at end of file diff --git a/msg/json/hu.json b/msg/json/hu.json new file mode 100644 index 000000000..c34ff694b --- /dev/null +++ b/msg/json/hu.json @@ -0,0 +1,283 @@ +{ + "@metadata": [], + "DUPLICATE_BLOCK": "M\u00e1solat", + "ADD_COMMENT": "Megjegyz\u00e9s hozz\u00e1ad\u00e1sa", + "REMOVE_COMMENT": "Megjegyz\u00e9s t\u00f6l\u00e9se", + "EXTERNAL_INPUTS": "K\u00fcls\u0151 kapcsolatok", + "INLINE_INPUTS": "Bels\u0151 kapcsolatok", + "DELETE_BLOCK": "T\u00f6r\u00f6l", + "DELETE_X_BLOCKS": "%1 blokk t\u00f6rl\u00e9se", + "COLLAPSE_BLOCK": "\u00d6sszez\u00e1r", + "EXPAND_BLOCK": "Kibont", + "DISABLE_BLOCK": "Letilt", + "ENABLE_BLOCK": "Enged\u00e9lyez", + "HELP": "Sug\u00f3", + "CHANGE_VALUE_TITLE": "\u00c9rt\u00e9k m\u00f3dos\u00edt\u00e1sa:", + "NEW_VARIABLE": "\u00daj...", + "NEW_VARIABLE_TITLE": "Az \u00faj v\u00e1ltoz\u00f3 neve:", + "RENAME_VARIABLE": "\u00c1tnevez\u00e9s...", + "RENAME_VARIABLE_TITLE": "\"%1\" v\u00e1ltoz\u00f3 \u00e1tnevez\u00e9se:", + "COLOUR_PICKER_HELPURL": "http://hu.wikipedia.org/wiki/Sz\u00edn", + "COLOUR_PICKER_TOOLTIP": "V\u00e1lassz sz\u00ednt a palett\u00e1r\u00f3l.", + "COLOUR_RANDOM_TITLE": "V\u00e9letlen sz\u00edn", + "COLOUR_RANDOM_TOOLTIP": "V\u00e9letlenszer\u0171en kiv\u00e1lasztott sz\u00edn.", + "COLOUR_RGB_TITLE": "Sz\u00edn", + "COLOUR_RGB_RED": "v\u00f6r\u00f6s", + "COLOUR_RGB_GREEN": "z\u00f6ld", + "COLOUR_RGB_BLUE": "k\u00e9k", + "COLOUR_RGB_TOOLTIP": "Sz\u00edn el\u0151\u00e1ll\u00edt\u00e1sa a megadott v\u00f6r\u00f6s, z\u00f6ld, \u00e9s k\u00e9k \u00e9rt\u00e9kekkel. Minden \u00e9rt\u00e9knek 0 \u00e9s 100 k\u00f6z\u00e9 kell esnie.", + "COLOUR_BLEND_TITLE": "Sz\u00ednkever\u00e9s", + "COLOUR_BLEND_COLOUR1": "", + "COLOUR_BLEND_COLOUR2": "+", + "COLOUR_BLEND_RATIO": "ar\u00e1ny:", + "COLOUR_BLEND_TOOLTIP": "K\u00e9t sz\u00ednt kever \u00f6ssze a megadott ar\u00e1nyban (0.0 - 1.0).", + "CONTROLS_REPEAT_HELPURL": "http://hu.wikipedia.org/wiki/Ciklus_(programoz%C3%A1s)#Sz.C3.A1ml.C3.A1l.C3.B3s_.28FOR.29_ciklus", + "CONTROLS_REPEAT_TITLE": "Ism\u00e9teld %1 alkalommal", + "CONTROLS_REPEAT_TITLE_REPEAT": "Ism\u00e9teld", + "CONTROLS_REPEAT_TITLE_TIMES": "alkalommal", + "CONTROLS_REPEAT_INPUT_DO": "", + "CONTROLS_REPEAT_TOOLTIP": "Megadott k\u00f3dr\u00e9szlet ism\u00e9telt v\u00e9grehajt\u00e1sa.", + "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "am\u00edg", + "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "am\u00edg nem", + "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Am\u00edg a felt\u00e9tel igaz, v\u00e9grehajtja az utas\u00edt\u00e1sokat.", + "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Am\u00edg a felt\u00e9tel hamis, v\u00e9grehajtja az utas\u00edt\u00e1sokat.", + "CONTROLS_FOR_TOOLTIP": "V\u00e9ges l\u00e9p\u00e9ssz\u00e1m\u00fa ciklus. A \"%1\" v\u00e1ltoz\u00f3 \u00e9rt\u00e9k\u00e9t sz\u00e1molja ki a kezd\u0151\u00e9rt\u00e9k \u00e9s a v\u00e9g\u00e9rt\u00e9k k\u00f6z\u00f6tt. Minden l\u00e9p\u00e9sben v\u00e9grehajt\u00f3dnak az utas\u00edt\u00e1sok.", + "CONTROLS_FOR_INPUT_WITH": "Sz\u00e1mold ezzel", + "CONTROLS_FOR_INPUT_FROM_TO_BY": "ett\u0151l: %1 eddig: %2 l\u00e9p\u00e9sk\u00f6z: %3", + "CONTROLS_FOREACH_HELPURL": "http://hu.wikipedia.org/wiki/Ciklus_(programoz%C3%A1s)#Iter.C3.A1l.C3.B3_ciklus", + "CONTROLS_FOREACH_INPUT_ITEM": "Minden", + "CONTROLS_FOREACH_INPUT_INLIST": "elemre a", + "CONTROLS_FOREACH_INPUT_INLIST_TAIL": "list\u00e1ban", + "CONTROLS_FOREACH_TOOLTIP": "A lista elemsz\u00e1m\u00e1nak megfelel\u0151 l\u00e9p\u00e9ssz\u00e1m\u00fa ciklus. A \"%1\" v\u00e1ltoz\u00f3 minden l\u00e9p\u00e9sben megkapja a lista adott elem\u00e9nek \u00e9rt\u00e9k\u00e9t. Minden l\u00e9p\u00e9sben v\u00e9grehajt\u00f3dnak az utas\u00edt\u00e1sok.", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "befejezi az ism\u00e9tl\u00e9st", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "folytatja a k\u00f6vetkez\u0151vel", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Megszak\u00edtja v\u00e9gtelen ciklust.", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Megszak\u00edtja az aktu\u00e1lis fut\u00e1st \u00e9s folytatja el\u00f6lr\u0151l.", + "CONTROLS_FLOW_STATEMENTS_WARNING": "Figyelem: Ez a blokk, csak egy ciklusban haszn\u00e1lhat\u00f3.", + "CONTROLS_IF_TOOLTIP_1": "Ha a kifejez\u00e9s igaz, akkor v\u00e9grehajtjuk az utas\u00edt\u00e1sokat.", + "CONTROLS_IF_TOOLTIP_2": "Ha a kifejez\u00e9s igaz, akkor v\u00e9grehajtjuk az els\u0151 utas\u00edt\u00e1s blokkot. K\u00fcl\u00f6nben a m\u00e1sodik utas\u00edt\u00e1s blokk ker\u00fcl v\u00e9grehajt\u00e1sra.", + "CONTROLS_IF_TOOLTIP_3": "Ha az els\u0151 kifejez\u00e9s igaz, akkor v\u00e9grehajtjuk az els\u0151 utas\u00edt\u00e1s blokkot. Ha a m\u00e1sodik kifejez\u00e9s igaz, akkor v\u00e9grehajtjuk a m\u00e1sodik utas\u00edt\u00e1s blokkot.", + "CONTROLS_IF_TOOLTIP_4": "Ha az els\u0151 kifejez\u00e9s igaz, akkor v\u00e9grehajtjuk az els\u0151 utas\u00edt\u00e1s blokkot. Ha a m\u00e1sodik kifejez\u00e9s igaz, akkor v\u00e9grehajtjuk a m\u00e1sodik utas\u00edt\u00e1s blokkot. Amennyiben egyik kifejez\u00e9s sem igaz, akkor az utols\u00f3 utas\u00edt\u00e1s blokk ker\u00fcl v\u00e9grehajt\u00e1sra.", + "CONTROLS_IF_MSG_IF": "Ha", + "CONTROLS_IF_MSG_ELSEIF": "ha", + "CONTROLS_IF_MSG_ELSE": "k\u00fcl\u00f6nben", + "CONTROLS_IF_IF_TOOLTIP": "A felt\u00e9teles el\u00e1gaz\u00e1s (ha) blokk testreszab\u00e1s\u00e1hoz b\u0151v\u00edtsd, t\u00f6r\u00f6ld vagy rendezd \u00e1t a r\u00e9szeit.", + "CONTROLS_IF_ELSEIF_TOOLTIP": "\u00dajabb felt\u00e9teles el\u00e1gaz\u00e1s.", + "LOGIC_COMPARE_TOOLTIP_EQ": "Igaz, ha a kifejez\u00e9s k\u00e9t oldala egyenl\u0151.", + "LOGIC_COMPARE_TOOLTIP_NEQ": "Igaz, ha a kifejez\u00e9s k\u00e9t oldala nem egyenl\u0151..", + "LOGIC_COMPARE_TOOLTIP_LT": "Igaz, ha a bal oldali kifejez\u00e9s kisebb, mint a jobb oldali.", + "LOGIC_COMPARE_TOOLTIP_LTE": "Igaz, ha a bal oldali kifejez\u00e9s kisebb vagy egyenl\u0151, mint a jobb oldali.", + "LOGIC_COMPARE_TOOLTIP_GT": "Igaz, ha a bal oldali kifejez\u00e9s nagyobb, mint a jobb oldali.", + "LOGIC_COMPARE_TOOLTIP_GTE": "Igaz, ha a bal oldali kifejez\u00e9s nagyobb vagy egyenl\u0151, mint a jobb oldali.", + "LOGIC_OPERATION_TOOLTIP_AND": "Igaz, ha mindk\u00e9t kifejez\u00e9s igaz.", + "LOGIC_OPERATION_AND": "\u00e9s", + "LOGIC_OPERATION_TOOLTIP_OR": "Igaz, ha b\u00e1rmelyik kifejez\u00e9s igaz.", + "LOGIC_OPERATION_OR": "vagy", + "LOGIC_NEGATE_TITLE": "nem %1", + "LOGIC_NEGATE_TOOLTIP": "Igaz, ha a kifejez\u00e9s hamis. Hamis, ha a kifejez\u00e9s igaz.", + "LOGIC_BOOLEAN_TRUE": "igaz", + "LOGIC_BOOLEAN_FALSE": "hamis", + "LOGIC_BOOLEAN_TOOLTIP": "Igaz, vagy Hamis \u00e9rt\u00e9k", + "LOGIC_NULL": "null", + "LOGIC_NULL_TOOLTIP": "null \u00e9rt\u00e9k.", + "LOGIC_TERNARY_CONDITION": "kifejez\u00e9s:", + "LOGIC_TERNARY_IF_TRUE": "\u00e9rt\u00e9k, ha igaz:", + "LOGIC_TERNARY_IF_FALSE": "\u00e9rt\u00e9k, ha hamis:", + "LOGIC_TERNARY_TOOLTIP": "Ki\u00e9rt\u00e9keli a kifejez\u00e9st. Ha a kifejez\u00e9s igaz visszat\u00e9r az \"\u00e9rt\u00e9k, ha igaz\" \u00e9rt\u00e9kkel, k\u00fcl\u00f6nben az \"\u00e9rt\u00e9k, ha hamis\" \u00e9rt\u00e9kkel.", + "MATH_NUMBER_TOOLTIP": "Egy sz\u00e1m.", + "MATH_ARITHMETIC_TOOLTIP_ADD": "K\u00e9t sz\u00e1m \u00f6sszege.", + "MATH_ARITHMETIC_TOOLTIP_MINUS": "K\u00e9t sz\u00e1m k\u00fcl\u00f6nbs\u00e9ge.", + "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "K\u00e9t sz\u00e1m szorzata.", + "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "K\u00e9t sz\u00e1m h\u00e1nyadosa.", + "MATH_ARITHMETIC_TOOLTIP_POWER": "Az els\u0151 sz\u00e1mnak a m\u00e1sodik sz\u00e1mmal megyegyez\u0151 hatv\u00e1nya.", + "MATH_SINGLE_OP_ROOT": "N\u00e9gyzetgy\u00f6k", + "MATH_SINGLE_TOOLTIP_ROOT": "A sz\u00e1m n\u00e9gyzetgy\u00f6ke.", + "MATH_SINGLE_OP_ABSOLUTE": "Abszol\u00fat\u00e9rt\u00e9k", + "MATH_SINGLE_TOOLTIP_ABS": "A sz\u00e1m abszol\u00fat\u00e9rt\u00e9ke.", + "MATH_SINGLE_TOOLTIP_NEG": "Return the negation of a number.", + "MATH_SINGLE_TOOLTIP_LN": "A sz\u00e1m term\u00e9szetes alap\u00fa logaritmusa.", + "MATH_SINGLE_TOOLTIP_LOG10": "A sz\u00e1m 10-es alap\u00fa logaritmusa.", + "MATH_SINGLE_TOOLTIP_EXP": "Az e megadott sz\u00e1m\u00fa hatv\u00e1nya.", + "MATH_SINGLE_TOOLTIP_POW10": "A 10 megadott sz\u00e1m\u00fa hatv\u00e1nya.", + "MATH_TRIG_TOOLTIP_SIN": "A fokban megadott sz\u00f6g szinusz \u00e9rt\u00e9ke.", + "MATH_TRIG_TOOLTIP_COS": "A fokban megadott sz\u00f6g koszinusz \u00e9rt\u00e9ke.", + "MATH_TRIG_TOOLTIP_TAN": "A fokban megadott sz\u00f6g tangens \u00e9rt\u00e9ke.", + "MATH_TRIG_TOOLTIP_ASIN": "A fokban megadott sz\u00f6g arkusz szinusz \u00e9rt\u00e9ke.", + "MATH_TRIG_TOOLTIP_ACOS": "A fokban megadott sz\u00f6g arkusz koszinusz \u00e9rt\u00e9ke.", + "MATH_TRIG_TOOLTIP_ATAN": "A fokban megadott sz\u00f6g arkusz tangens \u00e9rt\u00e9ke.", + "MATH_CONSTANT_TOOLTIP": "Ismert matematikai konstans: \u03c0 (3.141\u2026), e (2.718\u2026), \u03c6 (1.618\u2026), gy\u00f6k(2) (1.414\u2026), gy\u00f6k(\u00bd) (0.707\u2026), vagy \u221e (v\u00e9gtelen).", + "MATH_IS_EVEN": "p\u00e1ros sz\u00e1m?", + "MATH_IS_ODD": "p\u00e1ratlan sz\u00e1m?", + "MATH_IS_PRIME": "pr\u00edmsz\u00e1m?", + "MATH_IS_WHOLE": "eg\u00e9sz sz\u00e1m?", + "MATH_IS_POSITIVE": "pozit\u00edv sz\u00e1m?", + "MATH_IS_NEGATIVE": "negat\u00edv sz\u00e1m?", + "MATH_IS_DIVISIBLE_BY": "oszthat\u00f3 a(z)", + "MATH_IS_TOOLTIP": "Megadja a sz\u00e1mr\u00f3l, hogy p\u00e1ros, p\u00e1ratlan, pr\u00edm, eg\u00e9sz, pozit\u00edv vagy negat\u00edv sz\u00e1m, illetve oszthat\u00f3-e a m\u00e1sodikkal. Igaz, vagy Hamis \u00e9rt\u00e9ket ad eredm\u00e9ny\u00fcl.", + "MATH_CHANGE_TITLE_CHANGE": "a", + "MATH_CHANGE_INPUT_BY": "\u00e9rt\u00e9k\u00e9nek n\u00f6vel\u00e9se", + "MATH_CHANGE_TOOLTIP": "A(z) \"%1\" v\u00e1ltoz\u00f3 \u00e9rt\u00e9k\u00e9nek n\u00f6vel\u00e9se.", + "MATH_ROUND_TOOLTIP": "Kerek\u00edt\u00e9s a k\u00f6vetkez\u0151, vagy megel\u0151z\u0151 eg\u00e9sz sz\u00e1mra.", + "MATH_ROUND_OPERATOR_ROUND": "Kerek\u00edt\u00e9s", + "MATH_ROUND_OPERATOR_ROUNDUP": "Kerek\u00edt\u00e9s fel", + "MATH_ROUND_OPERATOR_ROUNDDOWN": "Kerek\u00edt\u00e9s le", + "MATH_ONLIST_OPERATOR_SUM": "lista \u00f6sszege", + "MATH_ONLIST_TOOLTIP_SUM": "A lista elemeinek \u00f6sszeg\u00e9t adja eredm\u00e9ny\u00fcl.", + "MATH_ONLIST_OPERATOR_MIN": "lista minimuma", + "MATH_ONLIST_TOOLTIP_MIN": "A lista elemeinek minimum\u00e1t adja eredm\u00e9ny\u00fcl.", + "MATH_ONLIST_OPERATOR_MAX": "lista maximuma", + "MATH_ONLIST_TOOLTIP_MAX": "A lista elemeinek maximum\u00e1t adja eredm\u00e9ny\u00fcl.", + "MATH_ONLIST_OPERATOR_AVERAGE": "lista \u00e1tlaga", + "MATH_ONLIST_TOOLTIP_AVERAGE": "A lista elemeinek \u00e1tlag\u00e1t adja eredm\u00e9ny\u00fcl.", + "MATH_ONLIST_OPERATOR_MEDIAN": "lista medi\u00e1nja", + "MATH_ONLIST_TOOLTIP_MEDIAN": "A lista elemeinek medi\u00e1nj\u00e1t adja eredm\u00e9ny\u00fcl.", + "MATH_ONLIST_OPERATOR_MODE": "lista m\u00f3dusza", + "MATH_ONLIST_TOOLTIP_MODE": "A lista elemeinek m\u00f3dusz\u00e1t adja eredm\u00e9ny\u00fcl.", + "MATH_ONLIST_OPERATOR_STD_DEV": "lista sz\u00f3r\u00e1sa", + "MATH_ONLIST_TOOLTIP_STD_DEV": "A lista elemeinek sz\u00f3r\u00e1s\u00e1t adja eredm\u00e9ny\u00fcl.", + "MATH_ONLIST_OPERATOR_RANDOM": "lista v\u00e9letlen eleme", + "MATH_ONLIST_TOOLTIP_RANDOM": "A lista elemeinek v\u00e9letlen elem\u00e9t adja eredm\u00e9ny\u00fcl.", + "MATH_MODULO_TITLE": "Marad\u00e9k %1 \u00f7 %2", + "MATH_MODULO_TOOLTIP": "Az eg\u00e9sz oszt\u00e1s marad\u00e9k\u00e1t adja eredm\u00e9yn\u00fcl.", + "MATH_CONSTRAIN_TITLE": "korl\u00e1tozd %1 -t %2 \u00e9s %3 k\u00f6z\u00e9", + "MATH_CONSTRAIN_TOOLTIP": "Egy v\u00e1ltoz\u00f3 \u00e9rt\u00e9k\u00e9nek korl\u00e1toz\u00e1sa a megadott z\u00e1rt intervallumra.", + "MATH_RANDOM_INT_TITLE": "V\u00e9letlen eg\u00e9sz sz\u00e1m %1 k\u00f6z\u00f6tt %2", + "MATH_RANDOM_INT_TOOLTIP": "V\u00e9letlen eg\u00e9sz sz\u00e1m a megadott z\u00e1rt intervallumon bel\u00fcl.", + "MATH_RANDOM_FLOAT_TITLE_RANDOM": "V\u00e9letlen t\u00f6rt", + "MATH_RANDOM_FLOAT_TOOLTIP": "V\u00e9letlen t\u00f6rt \u00e9rt\u00e9k 0.0 \u00e9s 1.0 k\u00f6z\u00f6tt.", + "TEXT_TEXT_TOOLTIP": "Egy bet\u0171, sz\u00f3 vagy sz\u00f6veg egy sora.", + "TEXT_JOIN_TITLE_CREATEWITH": "\u00d6sszef\u0171z", + "TEXT_JOIN_TOOLTIP": "Tetsz\u0151leges sz\u00e1m\u00fa sz\u00f6vegr\u00e9szletet f\u0171z \u00f6ssze egybef\u00fcgg\u0151 sz\u00f6vegg\u00e9.", + "TEXT_CREATE_JOIN_TITLE_JOIN": "\u00d6sszef\u0171z", + "TEXT_CREATE_JOIN_TOOLTIP": "\u00d6sszef\u0171z\u00e9ssel, t\u00f6rl\u00e9ssel vagy rendez\u00e9ssel kapcsolato sblokkok sz\u00f6veg szerkeszt\u00e9s\u00e9hez.", + "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Elem hozz\u00e1f\u0171z\u00e9se a sz\u00f6veghez.", + "TEXT_APPEND_TO": "a", + "TEXT_APPEND_APPENDTEXT": "sz\u00f6veg\u00e9hez f\u0171zd hozz\u00e1", + "TEXT_APPEND_TOOLTIP": "Sz\u00f6veget f\u0171z a \"%1\" v\u00e1ltoz\u00f3 \u00e9rt\u00e9k\u00e9hez.", + "TEXT_LENGTH_TITLE": "Hossz %1", + "TEXT_LENGTH_TOOLTIP": "A megadott sz\u00f6veg karaktereinek sz\u00e1m\u00e1t adja eredm\u00e9ny\u00fcl (bele\u00e9rtve a sz\u00f3k\u00f6z\u00f6ket).", + "TEXT_ISEMPTY_TITLE": "%1 \u00fcres sztring?", + "TEXT_ISEMPTY_TOOLTIP": "Igaz, ha vizsg\u00e1lt sztring \u00fcres.", + "TEXT_INDEXOF_TOOLTIP": "A keresett sz\u00f6veg els\u0151 vagy utols\u00f3 el\u0151fordul\u00e1s\u00e1val t\u00e9r vissza. 0 eset\u00e9n a sz\u00f6vegr\u00e9szlet nem tal\u00e1lhat\u00f3.", + "TEXT_INDEXOF_INPUT_INTEXT": "A(z)", + "TEXT_INDEXOF_OPERATOR_FIRST": "els\u0151 el\u0151fordul\u00e1s\u00e1nak indexe", + "TEXT_INDEXOF_OPERATOR_LAST": "utols\u00f3 el\u0151fordul\u00e1s\u00e1nak indexe", + "TEXT_INDEXOF_TAIL": "sz\u00f6vegnek", + "TEXT_CHARAT_INPUT_INTEXT": "A", + "TEXT_CHARAT_FROM_START": "sz\u00f6vegnek az elej\u00e9t\u0151l sz\u00e1m\u00edtott", + "TEXT_CHARAT_FROM_END": "sz\u00f6vegnek a v\u00e9g\u00e9t\u0151l sz\u00e1m\u00edtott", + "TEXT_CHARAT_FIRST": "sz\u00f6vegnek az els\u0151", + "TEXT_CHARAT_LAST": "sz\u00f6vegnek az utols\u00f3", + "TEXT_CHARAT_RANDOM": "sz\u00f6vegnek tetsz\u0151leges", + "TEXT_CHARAT_TAIL": "karaktere", + "TEXT_CHARAT_TOOLTIP": "A sz\u00f6veg egy megadott karakter\u00e9t adja eredm\u00e9ny\u00fcl.", + "TEXT_GET_SUBSTRING_TOOLTIP": "A megadott sz\u00f6vegr\u00e9szletet adja eredm\u00e9ny\u00fcl.", + "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "a", + "TEXT_GET_SUBSTRING_START_FROM_START": "sz\u00f6vegben v\u00e1laszd ki a(z)", + "TEXT_GET_SUBSTRING_START_FROM_END": "sz\u00f6vegben v\u00e1laszd ki a h\u00e1tulr\u00f3l a(z)", + "TEXT_GET_SUBSTRING_START_FIRST": "sz\u00f6vegben v\u00e1laszd ki az els\u0151", + "TEXT_GET_SUBSTRING_END_FROM_START": "bet\u0171t\u0151l a(z)", + "TEXT_GET_SUBSTRING_END_FROM_END": "bet\u0171t\u0151l a h\u00e1tulr\u00f3l sz\u00e1m\u00edtott", + "TEXT_GET_SUBSTRING_END_LAST": "bet\u0171t\u0151l az utols\u00f3", + "TEXT_GET_SUBSTRING_TAIL": "bet\u0171ig tart\u00f3 bet\u0171sort", + "TEXT_CHANGECASE_TOOLTIP": "Return a copy of the text in a different case.", + "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "NAGYBET\u0170S", + "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "kisbet\u0171s", + "TEXT_CHANGECASE_OPERATOR_TITLECASE": "C\u00edmk\u00e9nt Form\u00e1zott", + "TEXT_TRIM_TOOLTIP": "Lev\u00e1gja a megadott sz\u00f6veg v\u00e9geir\u0151l a sz\u00f3k\u00f6z\u00f6ket.", + "TEXT_TRIM_OPERATOR_BOTH": "a v\u00e9gekr\u0151l", + "TEXT_TRIM_OPERATOR_LEFT": "az elej\u00e9r\u0151l", + "TEXT_TRIM_OPERATOR_RIGHT": "a v\u00e9g\u00e9r\u0151l", + "TEXT_PRINT_TITLE": "\u00dczenet %1", + "TEXT_PRINT_TOOLTIP": "Megejeln\u00edti a megadott kaakterl\u00e1ncot \u00fczenetk\u00e9nt a k\u00e9perny\u0151n.", + "TEXT_PROMPT_TYPE_TEXT": "K\u00e9rj be sz\u00f6veget", + "TEXT_PROMPT_TYPE_NUMBER": "K\u00e9rj be sz\u00e1mot", + "TEXT_PROMPT_TOOLTIP_NUMBER": "Sz\u00e1mot k\u00e9r be a felhaszn\u00e1l\u00f3t\u00f3l.", + "TEXT_PROMPT_TOOLTIP_TEXT": "Sz\u00f6veget k\u00e9r be a felhaszn\u00e1l\u00f3t\u00f3l.", + "LISTS_CREATE_EMPTY_TITLE": "\u00fcres lista", + "LISTS_CREATE_EMPTY_TOOLTIP": "Elemeket nem tartalmaz\u00f3 \u00fcres list\u00e1t ad eredm\u00e9ny\u00fcl", + "LISTS_CREATE_WITH_TOOLTIP": "List\u00e1t k\u00e9sz\u00edt a megadott elemekb\u0151l.", + "LISTS_CREATE_WITH_INPUT_WITH": "Lista k\u00e9sz\u00edt\u00e9s, elemek:", + "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "lista", + "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Add, remove, or reorder sections to reconfigure this list block.", + "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Elem hozz\u00e1ad\u00e1sa list\u00e1hoz.", + "LISTS_REPEAT_TOOLTIP": "A megadtott elem felhaszn\u00e1l\u00e1s\u00e1val n elem\u0171 list\u00e1t k\u00e9sz\u00edt", + "LISTS_REPEAT_TITLE": "Lista k\u00e9sz\u00edt\u00e9se %1 elemet %2 alkalommal hozz\u00e1adva", + "LISTS_LENGTH_TITLE": "hossz %1 list\u00e1ban", + "LISTS_LENGTH_TOOLTIP": "A lista elemsz\u00e1m\u00e1t adja eredm\u00e9ny\u00fcl.", + "LISTS_IS_EMPTY_TITLE": "%1 \u00fcres lista?", + "LISTS_TOOLTIP": "Az eredm\u00e9ny igaz, ha a lista nem tartalmaz elemeket.", + "LISTS_INLIST": "A(z)", + "LISTS_INDEX_OF_FIRST": "list\u00e1ban els\u0151 el\u0151fordul\u00e1s\u00e1nak", + "LISTS_INDEX_OF_LAST": "list\u00e1ban utols\u00f3 el\u0151fordul\u00e1s\u00e1nak", + "LISTS_INDEX_OF_TOOLTIP": "A megadtott elem esl\u0151 vagy utols\u00f3 el\u0151fordul\u00e1s\u00e1val t\u00e9r vissza. 0 eset\u00e9n nincs ilyen eleme a list\u00e1nak.", + "LISTS_GET_INDEX_GET": "list\u00e1ban \u00e9rt\u00e9ke", + "LISTS_GET_INDEX_GET_REMOVE": "list\u00e1b\u00f3l kiv\u00e9tele", + "LISTS_GET_INDEX_REMOVE": "list\u00e1b\u00f3l t\u00f6rl\u00e9se", + "LISTS_GET_INDEX_FROM_START": "az elej\u00e9t\u0151l sz\u00e1m\u00edtott", + "LISTS_GET_INDEX_FROM_END": "a v\u00e9g\u00e9t\u0151l sz\u00e1m\u00edtott", + "LISTS_GET_INDEX_FIRST": "az els\u0151", + "LISTS_GET_INDEX_LAST": "az utols\u00f3", + "LISTS_GET_INDEX_RANDOM": "b\u00e1rmely", + "LISTS_GET_INDEX_TAIL": "elem", + "LISTS_GET_INDEX_TOOLTIP_GET_FROM_START": "A lista megadott sorsz\u00e1m\u00fa elem\u00e9t adja eredm\u00e9ny\u00fcl. 1 az els\u0151 elemet jelenti.", + "LISTS_GET_INDEX_TOOLTIP_GET_FROM_END": "A lista megadott sorsz\u00e1m\u00fa elem\u00e9t adja eredm\u00e9ny\u00fcl. 1 az utols\u00f3 elemet jelenti.", + "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "A lista els\u0151 elem\u00e9t adja eredm\u00e9ny\u00fcl.", + "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "A lista utols\u00f3 elem\u00e9t adja eredm\u00e9ny\u00fcl.", + "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "A lista v\u00e9letlenszer\u0171en v\u00e1lasztott elem\u00e9t adja eredm\u00e9ny\u00fcl.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START": "A megadott sorsz\u00e1m\u00fa elem kiv\u00e9tele a list\u00e1b\u00f3l 1 az els\u0151 elemet jelenti.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END": "A megadott sorsz\u00e1m\u00fa elem kiv\u00e9tele a list\u00e1b\u00f3l 1 az utols\u00f3 elemet jelenti.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Az els\u0151 elem kiv\u00e9tele a list\u00e1b\u00f3l.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Az utols\u00f3 elem kiv\u00e9tele a list\u00e1b\u00f3l.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "V\u00e9letlenszer\u0171en v\u00e1lasztott elem kiv\u00e9tele a list\u00e1b\u00f3l.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START": "A megadott sorsz\u00e1m\u00fa elem t\u00f6rl\u00e9se a list\u00e1b\u00f3l 1 az els\u0151 elemet jelenti.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END": "A megadott sorsz\u00e1m\u00fa elem t\u00f6rl\u00e9se a list\u00e1b\u00f3l 1 az utols\u00f3 elemet jelenti.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Az els\u0151 elem t\u00f6rl\u00e9se a list\u00e1b\u00f3l.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Az utols\u00f3 elem t\u00f6rl\u00e9se a list\u00e1b\u00f3l.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "V\u00e9letlenszer\u0171en v\u00e1lasztott elem t\u00f6rl\u00e9se a list\u00e1b\u00f3l.", + "LISTS_SET_INDEX_SET": "\u00e1ll\u00edtsd be", + "LISTS_SET_INDEX_INSERT": "illeszd be", + "LISTS_SET_INDEX_INPUT_TO": "elemet mint", + "LISTS_SET_INDEX_TOOLTIP_SET_FROM_START": "A megadott sorsz\u00e1m\u00fa elem cser\u00e9je a list\u00e1ban. 1 az els\u0151 elemet jelenti.", + "LISTS_SET_INDEX_TOOLTIP_SET_FROM_END": "A megadott sorsz\u00e1m\u00fa elem cser\u00e9je a list\u00e1ban. 1 az utols\u00f3 elemet jelenti.", + "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Az els\u0151 elem cser\u00e9je a list\u00e1ban.", + "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Az utols\u00f3 elem cser\u00e9je a list\u00e1ban.", + "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "V\u00e9letlenszer\u0171en v\u00e1lasztott elem cser\u00e9je a list\u00e1ban.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START": "Besz\u00far\u00e1s a megadott sorsz\u00e1m\u00fa elem el\u00e9 a list\u00e1ban. 1 az els\u0151 elemet jelenti.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END": "Besz\u00far\u00e1s a megadott sorsz\u00e1m\u00fa elem el\u00e9 a list\u00e1ban. 1 az utols\u00f3 elemet jelenti.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Besz\u00far\u00e1s a lista elej\u00e9re.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Besz\u00far\u00e1s a lista v\u00e9g\u00e9re.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Besz\u00far\u00e1s v\u00e9letlenszer\u0171en v\u00e1lasztott elem el\u00e9 a list\u00e1ban.", + "LISTS_GET_SUBLIST_START_FROM_START": "r\u00e9szlist\u00e1ja az elej\u00e9t\u0151l sz\u00e1m\u00edtott", + "LISTS_GET_SUBLIST_START_FROM_END": "r\u00e9szlist\u00e1ja a v\u00e9g\u00e9t\u0151l sz\u00e1m\u00edtott", + "LISTS_GET_SUBLIST_START_FIRST": "r\u00e9szlist\u00e1ja az els\u0151", + "LISTS_GET_SUBLIST_END_FROM_START": "\u00e9s az elej\u00e9t\u0151l sz\u00e1m\u00edtott", + "LISTS_GET_SUBLIST_END_FROM_END": "\u00e9s a v\u00e9g\u00e9t\u0151l sz\u00e1m\u00edtott", + "LISTS_GET_SUBLIST_END_LAST": "\u00e9s az utols\u00f3", + "LISTS_GET_SUBLIST_TAIL": "elem k\u00f6z\u00f6tt", + "LISTS_GET_SUBLIST_TOOLTIP": "A lista adott r\u00e9sz\u00e9r\u0151l m\u00e1solat.", + "ORDINAL_NUMBER_SUFFIX": ".", + "VARIABLES_GET_TITLE": "", + "VARIABLES_GET_TAIL": "", + "VARIABLES_GET_TOOLTIP": "A v\u00e1ltoz\u00f3 \u00e9rt\u00e9k\u00e9t adja eredm\u00e9ny\u00fcl.", + "VARIABLES_GET_CREATE_SET": "Create \"set %1\"", + "VARIABLES_SET_TITLE": "", + "VARIABLES_SET_TAIL": "", + "VARIABLES_SET_TOOLTIP": "A v\u00e1ltoz\u00f3nak adhatunk \u00e9rt\u00e9ket.", + "VARIABLES_SET_CREATE_GET": "Create \"get %1\"", + "PROCEDURES_DEFNORETURN_PROCEDURE": "Elj\u00e1r\u00e1s", + "PROCEDURES_DEFNORETURN_DO": "", + "PROCEDURES_DEFNORETURN_TOOLTIP": "Elj\u00e1r\u00e1s (nem ad vissza eredm\u00e9nyt).", + "PROCEDURES_DEFRETURN_RETURN": "eredm\u00e9ny", + "PROCEDURES_DEFRETURN_TOOLTIP": "Elj\u00e1r\u00e1s eredm\u00e9nnyel.", + "PROCEDURES_DEF_DUPLICATE_WARNING": "Figyelem: Az elj\u00e1r\u00e1sban azonos elnevez\u00e9s\u0171 param\u00e9tert adt\u00e1l meg.", + "PROCEDURES_CALLNORETURN_CALL": "", + "PROCEDURES_CALLNORETURN_TOOLTIP": "V\u00e9grehajtja az elj\u00e1r\u00e1st.", + "PROCEDURES_CALLRETURN_TOOLTIP": "Megh\u00edvja a f\u00fcggv\u00e9nyt.", + "PROCEDURES_MUTATORCONTAINER_TITLE": "param\u00e9terek", + "PROCEDURES_MUTATORARG_TITLE": "v\u00e1ltoz\u00f3:", + "PROCEDURES_HIGHLIGHT_DEF": "Elj\u00e1r\u00e1s kiemel\u00e9se", + "PROCEDURES_CREATE_DO": "Create \"do %1\"", + "PROCEDURES_IFRETURN_TOOLTIP": "Ha az \u00e9rt\u00e9k igaz, akkor visszat\u00e9r a f\u00fcggv\u00e9ny \u00e9rt\u00e9k\u00e9vel.", + "PROCEDURES_IFRETURN_WARNING": "Figyelem: Ez a blokk csak elj\u00e1r\u00e1son bel\u00fcl haszn\u00e1lhat\u00f3." +} \ No newline at end of file diff --git a/msg/json/ia.json b/msg/json/ia.json new file mode 100644 index 000000000..e540ba2d9 --- /dev/null +++ b/msg/json/ia.json @@ -0,0 +1,111 @@ +{ + "@metadata": { + "authors": [ + "McDutchie" + ] + }, + "VARIABLES_DEFAULT_NAME": "cosa", + "DUPLICATE_BLOCK": "Duplicar", + "ADD_COMMENT": "Adder commento", + "REMOVE_COMMENT": "Remover commento", + "EXTERNAL_INPUTS": "Entrata externe", + "INLINE_INPUTS": "Entrata interne", + "DELETE_BLOCK": "Deler bloco", + "DELETE_X_BLOCKS": "Deler %1 blocos", + "COLLAPSE_BLOCK": "Plicar bloco", + "COLLAPSE_ALL": "Plicar blocos", + "EXPAND_BLOCK": "Displicar bloco", + "EXPAND_ALL": "Displicar blocos", + "DISABLE_BLOCK": "Disactivar bloco", + "ENABLE_BLOCK": "Activar bloco", + "HELP": "Adjuta", + "CHANGE_VALUE_TITLE": "Cambiar valor:", + "NEW_VARIABLE": "Nove variabile...", + "NEW_VARIABLE_TITLE": "Nomine del nove variabile:", + "RENAME_VARIABLE": "Renominar variabile...", + "RENAME_VARIABLE_TITLE": "Renominar tote le variabiles '%1' a:", + "COLOUR_PICKER_HELPURL": "http://ia.wikipedia.org/wiki/Color", + "COLOUR_PICKER_TOOLTIP": "Elige un color del paletta.", + "COLOUR_RANDOM_TITLE": "color aleatori", + "COLOUR_RANDOM_TOOLTIP": "Eliger un color al hasardo.", + "COLOUR_RGB_TITLE": "colorar con", + "COLOUR_RGB_RED": "rubie", + "COLOUR_RGB_GREEN": "verde", + "COLOUR_RGB_BLUE": "blau", + "COLOUR_RGB_TOOLTIP": "Crear un color con le quantitate specificate de rubie, verde e blau. Tote le valores debe esser inter 0 e 100.", + "COLOUR_BLEND_TITLE": "miscer", + "COLOUR_BLEND_COLOUR1": "color 1", + "COLOUR_BLEND_COLOUR2": "color 2", + "COLOUR_BLEND_RATIO": "ration", + "COLOUR_BLEND_TOOLTIP": "Misce duo colores con un ration specificate (0.0 - 1.0).", + "CONTROLS_REPEAT_HELPURL": "http://en.wikipedia.org/wiki/For_loop", + "CONTROLS_REPEAT_TITLE": "repeter %1 vices", + "CONTROLS_REPEAT_TITLE_REPEAT": "repeter", + "CONTROLS_REPEAT_TITLE_TIMES": "vices", + "CONTROLS_REPEAT_INPUT_DO": "face", + "CONTROLS_REPEAT_TOOLTIP": "Exequer certe instructiones plure vices.", + "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "repeter durante que", + "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "repeter usque a", + "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Durante que un valor es ver, exequer certe instructiones.", + "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Durante que un valor es false, exequer certe instructiones.", + "CONTROLS_FOR_TOOLTIP": "Mitter in le variabile %1 le valores ab le numero initial usque al numero final, con passos secundo le intervallo specificate, e exequer le blocos specificate.", + "CONTROLS_FOR_INPUT_WITH": "contar con", + "CONTROLS_FOR_INPUT_FROM_TO_BY": "de %1 a %2 per %3", + "CONTROLS_FOREACH_INPUT_ITEM": "pro cata elemento", + "CONTROLS_FOREACH_INPUT_INLIST": "in lista", + "CONTROLS_FOREACH_TOOLTIP": "Pro cata elemento in un lista, mitter lo in le variabile '%1' e exequer certe instructiones.", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "escappar del bucla", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "continuar con le proxime iteration del bucla", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Escappar del bucla continente.", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Saltar le resto de iste bucla e continuar con le proxime iteration.", + "CONTROLS_FLOW_STATEMENTS_WARNING": "Attention: Iste bloco pote solmente esser usate in un bucla.", + "CONTROLS_IF_TOOLTIP_1": "Si un valor es ver, exequer certe instructiones.", + "CONTROLS_IF_TOOLTIP_2": "Si un valor es ver, exequer le prime bloco de instructiones. Si non, exequer le secunde bloco de instructiones.", + "CONTROLS_IF_TOOLTIP_3": "Si le prime valor es ver, exequer le prime bloco de instructiones. Si non, si le secunde valor es ver, exequer le secunde bloco de instructiones.", + "CONTROLS_IF_TOOLTIP_4": "Si le prime valor es ver, exequer le prime bloco de instructiones. Si non, si le secunde valor es ver, exequer le secunde bloco de instructiones. Si necun del valores es ver, exequer le ultime bloco de instructiones.", + "CONTROLS_IF_MSG_IF": "si", + "CONTROLS_IF_MSG_ELSEIF": "si non si", + "CONTROLS_IF_MSG_ELSE": "si non", + "CONTROLS_IF_IF_TOOLTIP": "Adder, remover o reordinar sectiones pro reconfigurar iste bloco \"si\".", + "CONTROLS_IF_ELSEIF_TOOLTIP": "Adder un condition al bloco \"si\".", + "CONTROLS_IF_ELSE_TOOLTIP": "Adder un condition final de reserva al bloco \"si\".", + "LOGIC_COMPARE_TOOLTIP_EQ": "Retornar ver si le duo entratas es equal.", + "LOGIC_COMPARE_TOOLTIP_NEQ": "Retornar ver si le duo entratas non es equal.", + "LOGIC_COMPARE_TOOLTIP_LT": "Retornar ver si le prime entrata es minor que le secunde.", + "LOGIC_COMPARE_TOOLTIP_LTE": "Retornar ver si le prime entrata es minor que o equal al secunde.", + "LOGIC_COMPARE_TOOLTIP_GT": "Retornar ver si le prime entrata es major que le secunde.", + "LOGIC_COMPARE_TOOLTIP_GTE": "Retornar ver si le prime entrata es major que o equal al secunde.", + "LOGIC_OPERATION_TOOLTIP_AND": "Retornar ver si ambe entratas es ver.", + "LOGIC_OPERATION_AND": "e", + "LOGIC_OPERATION_TOOLTIP_OR": "Retornar ver si al minus un del entratas es ver.", + "LOGIC_OPERATION_OR": "o", + "LOGIC_NEGATE_TITLE": "non %1", + "LOGIC_NEGATE_TOOLTIP": "Retornar ver si le entrata es false. Retornar false si le entrata es ver.", + "LOGIC_BOOLEAN_TRUE": "ver", + "LOGIC_BOOLEAN_FALSE": "false", + "LOGIC_BOOLEAN_TOOLTIP": "Retorna o ver o false.", + "LOGIC_NULL": "nulle", + "LOGIC_NULL_TOOLTIP": "Retorna nulle.", + "LOGIC_TERNARY_CONDITION": "test", + "LOGIC_TERNARY_IF_TRUE": "si ver", + "LOGIC_TERNARY_IF_FALSE": "si false", + "LOGIC_TERNARY_TOOLTIP": "Verificar le condition in 'test'. Si le condition es ver, retorna le valor de 'si ver'; si non, retorna le valor de 'si false'.", + "MATH_NUMBER_HELPURL": "http://ia.wikipedia.org/wiki/Numero", + "MATH_NUMBER_TOOLTIP": "Un numero.", + "MATH_ARITHMETIC_HELPURL": "http://ia.wikipedia.org/wiki/Arithmetica", + "MATH_ARITHMETIC_TOOLTIP_ADD": "Retornar le summa del duo numeros.", + "MATH_ARITHMETIC_TOOLTIP_MINUS": "Retornar le differentia del duo numeros.", + "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Retornar le producto del duo numeros.", + "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Retornar le quotiente del duo numeros.", + "MATH_ARITHMETIC_TOOLTIP_POWER": "Retornar le prime numero elevate al potentia del secunde numero.", + "MATH_SINGLE_HELPURL": "http://ia.wikipedia.org/wiki/Radice_quadrate", + "MATH_SINGLE_OP_ROOT": "radice quadrate", + "MATH_SINGLE_TOOLTIP_ROOT": "Retornar le radice quadrate de un numero.", + "MATH_SINGLE_OP_ABSOLUTE": "absolute", + "MATH_SINGLE_TOOLTIP_ABS": "Retornar le valor absolute de un numero.", + "MATH_SINGLE_TOOLTIP_NEG": "Retornar le negation de un numero.", + "MATH_SINGLE_TOOLTIP_LN": "Retornar le logarithmo natural de un numero.", + "MATH_SINGLE_TOOLTIP_LOG10": "Retornar le logarithmo in base 10 del numero.", + "MATH_SINGLE_TOOLTIP_EXP": "Retornar e elevate al potentia del numero.", + "MATH_SINGLE_TOOLTIP_POW10": "Retornar 10 elevate al potentia de un numero." +} \ No newline at end of file diff --git a/msg/json/it.json b/msg/json/it.json new file mode 100644 index 000000000..426188445 --- /dev/null +++ b/msg/json/it.json @@ -0,0 +1,294 @@ +{ + "@metadata": { + "authors": [ + "Beta16", + "Nerimic" + ] + }, + "VARIABLES_DEFAULT_NAME": "elemento", + "DUPLICATE_BLOCK": "Duplica", + "ADD_COMMENT": "Aggiungi commento", + "REMOVE_COMMENT": "Rimuovi commento", + "EXTERNAL_INPUTS": "Ingressi esterni", + "INLINE_INPUTS": "Ingressi in linea", + "DELETE_BLOCK": "Cancella blocco", + "DELETE_X_BLOCKS": "Cancella %1 blocchi", + "COLLAPSE_BLOCK": "Comprimi blocco", + "COLLAPSE_ALL": "Comprimi blocchi", + "EXPAND_BLOCK": "Espandi blocco", + "EXPAND_ALL": "Espandi blocchi", + "DISABLE_BLOCK": "Disattivare blocco", + "ENABLE_BLOCK": "Attiva blocco", + "HELP": "Aiuto", + "CHANGE_VALUE_TITLE": "Modifica valore:", + "NEW_VARIABLE": "Nuova variabile...", + "NEW_VARIABLE_TITLE": "Nome della nuova variabile:", + "RENAME_VARIABLE": "Rinomina variabile...", + "RENAME_VARIABLE_TITLE": "Rinomina tutte le variabili '%1' in:", + "COLOUR_PICKER_HELPURL": "http://it.wikipedia.org/wiki/Colore", + "COLOUR_PICKER_TOOLTIP": "Scegli un colore dalla tavolozza.", + "COLOUR_RANDOM_TITLE": "colore casuale", + "COLOUR_RANDOM_TOOLTIP": "Scegli un colore a caso.", + "COLOUR_RGB_TITLE": "colora con", + "COLOUR_RGB_RED": "rosso", + "COLOUR_RGB_GREEN": "verde", + "COLOUR_RGB_BLUE": "blu", + "COLOUR_RGB_TOOLTIP": "Crea un colore con la quantit\u00e0 specificata di rosso, verde e blu. Tutti i valori devono essere compresi tra 0 e 100.", + "COLOUR_BLEND_TITLE": "miscela", + "COLOUR_BLEND_COLOUR1": "colore 1", + "COLOUR_BLEND_COLOUR2": "colore 2", + "COLOUR_BLEND_RATIO": "rapporto", + "COLOUR_BLEND_TOOLTIP": "Mescola due colori insieme con un determinato rapporto (0.0 - 1.0).", + "CONTROLS_REPEAT_HELPURL": "http://it.wikipedia.org/wiki/Ciclo_for", + "CONTROLS_REPEAT_TITLE": "ripeti %1 volte", + "CONTROLS_REPEAT_TITLE_REPEAT": "ripeti", + "CONTROLS_REPEAT_TITLE_TIMES": "volte", + "CONTROLS_REPEAT_INPUT_DO": "fai", + "CONTROLS_REPEAT_TOOLTIP": "Esegue alcune istruzione diverse volte.", + "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "ripeti mentre", + "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "ripeti fino a che", + "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Finch\u00e9 un valore \u00e8 vero, esegue alcune istruzioni.", + "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Finch\u00e9 un valore \u00e8 falso, esegue alcune istruzioni.", + "CONTROLS_FOR_TOOLTIP": "Fa s\u00ec che la variabile %1 prenda tutti i valori a partire dal numero di partenza fino a quello di arrivo, con passo pari all'intervallo specificato, ed esegue il blocco indicato.", + "CONTROLS_FOR_INPUT_WITH": "conta con", + "CONTROLS_FOR_INPUT_FROM_TO_BY": "da %1 a %2 per %3", + "CONTROLS_FOREACH_INPUT_ITEM": "per ogni elemento", + "CONTROLS_FOREACH_INPUT_INLIST": "nella lista", + "CONTROLS_FOREACH_TOOLTIP": "Per ogni elemento in una lista, imposta la variabile '%1' pari all'elemento e quindi esegue alcune istruzioni.", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "esce dal ciclo", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "prosegui con la successiva iterazione del ciclo", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Esce dal ciclo.", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Salta il resto di questo ciclo e prosegue con la successiva iterazione.", + "CONTROLS_FLOW_STATEMENTS_WARNING": "Attenzione\u02d0 Questo blocco pu\u00f2 essere usato solo in un ciclo.", + "CONTROLS_IF_TOOLTIP_1": "Se un valore \u00e8 vero allora esegue alcune istruzioni.", + "CONTROLS_IF_TOOLTIP_2": "Se un valore \u00e8 vero allora esegue il primo blocco di istruzioni. Altrimenti esegue il secondo blocco di istruzioni.", + "CONTROLS_IF_TOOLTIP_3": "Se il primo valore \u00e8 vero allora esegue un primo blocco di istruzioni. Altrimenti, se il secondo valore \u00e8 vero, esegue un secondo blocco di istruzioni.", + "CONTROLS_IF_TOOLTIP_4": "Se il primo valore \u00e8 vero allora esegue un primo blocco di istruzioni. Altrimenti, se il secondo valore \u00e8 vero, esegue un secondo blocco di istruzioni. Se nessuno dei valori \u00e8 vero esegue l'ultimo blocco di istruzioni.", + "CONTROLS_IF_MSG_IF": "se", + "CONTROLS_IF_MSG_ELSEIF": "altrimenti se", + "CONTROLS_IF_MSG_ELSE": "altrimenti", + "CONTROLS_IF_IF_TOOLTIP": "Aggiungi, elimina o riordina le sezioni per riconfigurare questo blocco se.", + "CONTROLS_IF_ELSEIF_TOOLTIP": "Aggiungi una condizione al blocco se.", + "CONTROLS_IF_ELSE_TOOLTIP": "Aggiungi una condizione finale pigliatutto al blocco se.", + "LOGIC_COMPARE_HELPURL": "http://it.wikipedia.org/wiki/Disuguaglianza", + "LOGIC_COMPARE_TOOLTIP_EQ": "Restituisce vero se gli input sono uno uguale all'altro.", + "LOGIC_COMPARE_TOOLTIP_NEQ": "Restituisce vero se gli input non sono uno uguale all'altro.", + "LOGIC_COMPARE_TOOLTIP_LT": "Restituisce vero se il primo input \u00e8 minore del secondo.", + "LOGIC_COMPARE_TOOLTIP_LTE": "Restituisce vero se il primo input \u00e8 minore o uguale al secondo.", + "LOGIC_COMPARE_TOOLTIP_GT": "Restituisce vero se il primo input \u00e8 maggiore o uguale al secondo.", + "LOGIC_COMPARE_TOOLTIP_GTE": "Restituisce uguale se il primo input \u00e8 maggiore o uguale al secondo input.", + "LOGIC_OPERATION_TOOLTIP_AND": "Restituisce vero se entrambi gli input sono veri.", + "LOGIC_OPERATION_AND": "e", + "LOGIC_OPERATION_TOOLTIP_OR": "Restituisce vero se almeno uno degli input \u00e8 vero.", + "LOGIC_OPERATION_OR": "o", + "LOGIC_NEGATE_TITLE": "non %1", + "LOGIC_NEGATE_TOOLTIP": "Restituisce vero se l'input \u00e8 falso. Restituisce falso se l'input \u00e8 vero.", + "LOGIC_BOOLEAN_TRUE": "vero", + "LOGIC_BOOLEAN_FALSE": "falso", + "LOGIC_BOOLEAN_TOOLTIP": "Restituisce vero o falso.", + "LOGIC_NULL": "nullo", + "LOGIC_NULL_TOOLTIP": "Restituisce valore nullo.", + "LOGIC_TERNARY_CONDITION": "test", + "LOGIC_TERNARY_IF_TRUE": "se vero", + "LOGIC_TERNARY_IF_FALSE": "se falso", + "LOGIC_TERNARY_TOOLTIP": "Verifica la condizione in 'test'. Se questa \u00e8 vera restituisce il valore 'se vero' altrimenti restituisce il valore 'se falso'.", + "MATH_NUMBER_HELPURL": "http://it.wikipedia.org/wiki/Numero", + "MATH_NUMBER_TOOLTIP": "Un numero.", + "MATH_ARITHMETIC_HELPURL": "http://it.wikipedia.org/wiki/Aritmetica", + "MATH_ARITHMETIC_TOOLTIP_ADD": "Restituisce la somma dei due numeri.", + "MATH_ARITHMETIC_TOOLTIP_MINUS": "Restituisce la differenza dei due numeri.", + "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Restituisce il prodotto dei due numeri.", + "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Restituisce il quoziente dei due numeri.", + "MATH_ARITHMETIC_TOOLTIP_POWER": "Restituisce il primo numero elevato alla potenza del secondo numero.", + "MATH_SINGLE_HELPURL": "http://it.wikipedia.org/wiki/Radice_quadrata", + "MATH_SINGLE_OP_ROOT": "radice quadrata", + "MATH_SINGLE_TOOLTIP_ROOT": "Restituisce la radice quadrata del numero.", + "MATH_SINGLE_OP_ABSOLUTE": "assoluto", + "MATH_SINGLE_TOOLTIP_ABS": "Restituisce il valore assoluto del numero.", + "MATH_SINGLE_TOOLTIP_NEG": "Restituisce l'opposto del numero.", + "MATH_SINGLE_TOOLTIP_LN": "Restituisce il logaritmo naturale del numero.", + "MATH_SINGLE_TOOLTIP_LOG10": "Restituisce il logaritmo in base 10 del numero.", + "MATH_SINGLE_TOOLTIP_EXP": "Restituisce e elevato alla potenza del numero.", + "MATH_SINGLE_TOOLTIP_POW10": "Restituisce 10 elevato alla potenza del numero.", + "MATH_TRIG_HELPURL": "http://it.wikipedia.org/wiki/Funzione_trigonometrica", + "MATH_TRIG_TOOLTIP_SIN": "Restituisce il seno di un angolo espresso in gradi (non radianti).", + "MATH_TRIG_TOOLTIP_COS": "Restituisce il coseno di un angolo espresso in gradi (non radianti).", + "MATH_TRIG_TOOLTIP_TAN": "Restituisce la tangente di un angolo espresso in gradi (non radianti).", + "MATH_TRIG_TOOLTIP_ASIN": "Restituisce l'arco-seno di un numero.", + "MATH_TRIG_TOOLTIP_ACOS": "Restituisce l'arco-coseno di un numero.", + "MATH_TRIG_TOOLTIP_ATAN": "Restituisce l'arco-tangente di un numero.", + "MATH_CONSTANT_HELPURL": "http://it.wikipedia.org/wiki/Costante_matematica", + "MATH_CONSTANT_TOOLTIP": "Restituisce una delle costanti comuni\u02d0 \u03c0 (3.141\u2026), e (2.718\u2026), \u03c6 (1.618\u2026), radq(2) (1.414\u2026), radq(\u00bd) (0.707\u2026) o \u221e (infinito).", + "MATH_IS_EVEN": "\u00e8 pari", + "MATH_IS_ODD": "\u00e8 dispari", + "MATH_IS_PRIME": "\u00e8 primo", + "MATH_IS_WHOLE": "\u00e8 intero", + "MATH_IS_POSITIVE": "\u00e8 positivo", + "MATH_IS_NEGATIVE": "\u00e8 negativo", + "MATH_IS_DIVISIBLE_BY": "\u00e8 divisibile per", + "MATH_IS_TOOLTIP": "Verifica se un numero \u00e8 pari, dispari, primo, intero, positivo, negativo o se \u00e8 divisibile per un certo numero. Restituisce vero o falso.", + "MATH_CHANGE_TITLE_CHANGE": "cambia", + "MATH_CHANGE_INPUT_BY": "di", + "MATH_CHANGE_TOOLTIP": "Aggiunge un numero alla variabile '%1'.", + "MATH_ROUND_HELPURL": "http://it.wikipedia.org/wiki/Arrotondamento", + "MATH_ROUND_TOOLTIP": "Arrotonda un numero verso l'alto o verso il basso.", + "MATH_ROUND_OPERATOR_ROUND": "arrotonda", + "MATH_ROUND_OPERATOR_ROUNDUP": "arrotonda verso l'alto", + "MATH_ROUND_OPERATOR_ROUNDDOWN": "arrotonda verso il basso", + "MATH_ONLIST_OPERATOR_SUM": "somma la lista", + "MATH_ONLIST_TOOLTIP_SUM": "Restituisce la somma si tutti i numeri nella lista.", + "MATH_ONLIST_OPERATOR_MIN": "minimo della lista", + "MATH_ONLIST_TOOLTIP_MIN": "Restituisce il pi\u00f9 piccolo numero della lista.", + "MATH_ONLIST_OPERATOR_MAX": "massimo della lista", + "MATH_ONLIST_TOOLTIP_MAX": "Restituisce il pi\u00f9 grande numero della lista.", + "MATH_ONLIST_OPERATOR_AVERAGE": "media della lista", + "MATH_ONLIST_TOOLTIP_AVERAGE": "Restituisce la media (media aritmetica) dei valori numerici nella lista.", + "MATH_ONLIST_OPERATOR_MEDIAN": "mediana della lista", + "MATH_ONLIST_TOOLTIP_MEDIAN": "Restituisce il valore mediano della lista.", + "MATH_ONLIST_OPERATOR_MODE": "mode della lista", + "MATH_ONLIST_TOOLTIP_MODE": "Restituisce una lista degli elementi pi\u00f9 frequenti nella lista.", + "MATH_ONLIST_OPERATOR_STD_DEV": "deviazione standard della lista", + "MATH_ONLIST_TOOLTIP_STD_DEV": "Restituisce la deviazione standard della lista.", + "MATH_ONLIST_OPERATOR_RANDOM": "elemento casuale della lista", + "MATH_ONLIST_TOOLTIP_RANDOM": "Restituisce un elemento casuale della lista.", + "MATH_MODULO_HELPURL": "http://it.wikipedia.org/wiki/Resto", + "MATH_MODULO_TITLE": "resto di %1 \u00f7 %2", + "MATH_MODULO_TOOLTIP": "Restituisce il resto della divisione di due numeri.", + "MATH_CONSTRAIN_TITLE": "costringi %1 da %2 a %3", + "MATH_CONSTRAIN_TOOLTIP": "Costringe un numero all'interno dei limiti indicati (compresi).", + "MATH_RANDOM_INT_HELPURL": "http://it.wikipedia.org/wiki/Numeri_pseudo-casuali", + "MATH_RANDOM_INT_TITLE": "intero casuale da %1 a %2", + "MATH_RANDOM_INT_TOOLTIP": "Restituisce un numero intero casuale compreso tra i due limiti indicati (inclusi).", + "MATH_RANDOM_FLOAT_HELPURL": "http://it.wikipedia.org/wiki/Numeri_pseudo-casuali", + "MATH_RANDOM_FLOAT_TITLE_RANDOM": "frazione casuale", + "MATH_RANDOM_FLOAT_TOOLTIP": "Restituisce una frazione compresa fra 0.0 (incluso) e 1.0 (escluso).", + "TEXT_TEXT_HELPURL": "http://it.wikipedia.org/wiki/Stringa_(informatica)", + "TEXT_TEXT_TOOLTIP": "Una lettera, una parola o una linea di testo.", + "TEXT_JOIN_TITLE_CREATEWITH": "crea testo con", + "TEXT_JOIN_TOOLTIP": "Crea un blocco di testo unendo un certo numero di elementi.", + "TEXT_CREATE_JOIN_TITLE_JOIN": "unisci", + "TEXT_CREATE_JOIN_TOOLTIP": "Aggiungi, rimuovi o riordina le sezioni per riconfigurare questo blocco testo.", + "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Aggiungi un elemento al testo.", + "TEXT_APPEND_TO": "a", + "TEXT_APPEND_APPENDTEXT": "aggiungi il testo", + "TEXT_APPEND_TOOLTIP": "Aggiunge del testo alla variabile '%1'.", + "TEXT_LENGTH_TITLE": "lunghezza di %1", + "TEXT_LENGTH_TOOLTIP": "Restituisce il numero di lettere (inclusi gli spazi) nel testo fornito.", + "TEXT_ISEMPTY_TITLE": "%1 \u00e8 vuoto", + "TEXT_ISEMPTY_TOOLTIP": "Restituisce vero se il testo fornito \u00e8 vuoto.", + "TEXT_INDEXOF_TOOLTIP": "Restituisce l'indice della prima occorrenza del primo testo all'interno del secondo testo. Restituisce 0 se il testo non viene trovato.", + "TEXT_INDEXOF_INPUT_INTEXT": "nel testo", + "TEXT_INDEXOF_OPERATOR_FIRST": "trova la prima occorrenza del testo", + "TEXT_INDEXOF_OPERATOR_LAST": "trova l'ultima occorrenza del testo", + "TEXT_CHARAT_INPUT_INTEXT": "nel testo", + "TEXT_CHARAT_FROM_START": "prendi la lettera #", + "TEXT_CHARAT_FROM_END": "prendi la lettera # dalla fine", + "TEXT_CHARAT_FIRST": "prendi la prima lettera", + "TEXT_CHARAT_LAST": "prendi l'ultima lettera", + "TEXT_CHARAT_RANDOM": "prendi lettera casuale", + "TEXT_CHARAT_TOOLTIP": "Restituisce la lettera nella posizione indicata.", + "TEXT_GET_SUBSTRING_TOOLTIP": "Restituisce la porzione di testo indicata.", + "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "nel testo", + "TEXT_GET_SUBSTRING_START_FROM_START": "prendi sotto-stringa dalla lettera #", + "TEXT_GET_SUBSTRING_START_FROM_END": "prendi sotto-stringa dalla lettera # dalla fine", + "TEXT_GET_SUBSTRING_START_FIRST": "prendi sotto-stringa dalla prima lettera", + "TEXT_GET_SUBSTRING_END_FROM_START": "alla lettera #", + "TEXT_GET_SUBSTRING_END_FROM_END": "alla lettera # dalla fine", + "TEXT_GET_SUBSTRING_END_LAST": "all'ultima lettera", + "TEXT_CHANGECASE_TOOLTIP": "Restituisce una copia del testo in un diverso formato maiuscole/minuscole.", + "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "in MAIUSCOLO", + "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "in minuscolo", + "TEXT_CHANGECASE_OPERATOR_TITLECASE": "con Iniziali Maiuscole", + "TEXT_TRIM_TOOLTIP": "Restituisce una copia del testo con gli spazi rimossi ad uno o entrambe le estremit\u00e0.", + "TEXT_TRIM_OPERATOR_BOTH": "rimuovi spazi da entrambi gli estremi", + "TEXT_TRIM_OPERATOR_LEFT": "rimuovi spazi a sinistra", + "TEXT_TRIM_OPERATOR_RIGHT": "rimuovi spazi a destra", + "TEXT_PRINT_TITLE": "scrivi %1", + "TEXT_PRINT_TOOLTIP": "Scrive il testo, numero o altro valore indicato.", + "TEXT_PROMPT_TYPE_TEXT": "richiedi testo con messaggio", + "TEXT_PROMPT_TYPE_NUMBER": "richiedi numero con messaggio", + "TEXT_PROMPT_TOOLTIP_NUMBER": "Richiedi un numero all'utente.", + "TEXT_PROMPT_TOOLTIP_TEXT": "Richiede del testo da parte dell'utente.", + "LISTS_CREATE_EMPTY_TITLE": "crea lista vuota", + "LISTS_CREATE_EMPTY_TOOLTIP": "Restituisce una lista, di lunghezza 0, contenente nessun record di dati", + "LISTS_CREATE_WITH_TOOLTIP": "Crea una lista con un certo numero di elementi.", + "LISTS_CREATE_WITH_INPUT_WITH": "crea lista con", + "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "lista", + "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Aggiungi, rimuovi o riordina le sezioni per riconfigurare il blocco lista.", + "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Aggiunge un elemento alla lista.", + "LISTS_REPEAT_TOOLTIP": "Crea una lista costituita dal valore indicato ripetuto per il numero di volte specificato.", + "LISTS_REPEAT_TITLE": "crea una lista con l'elemento %1 ripetuto %2 volte", + "LISTS_LENGTH_TITLE": "lunghezza di %1", + "LISTS_LENGTH_TOOLTIP": "Restituisce la lunghezza della lista", + "LISTS_IS_EMPTY_TITLE": "%1 \u00e8 vuota", + "LISTS_TOOLTIP": "Restituisce vero se la lista \u00e8 vuota.", + "LISTS_INLIST": "nella lista", + "LISTS_INDEX_OF_FIRST": "trova la prima occorrenza dell'elemento", + "LISTS_INDEX_OF_LAST": "trova l'ultima occorrenza dell'elemento", + "LISTS_INDEX_OF_TOOLTIP": "Restituisce l'indice della prima/ultima occorrenza dell'elemento nella lista. Restituisce 0 se il testo non viene trovato.", + "LISTS_GET_INDEX_GET": "prendi", + "LISTS_GET_INDEX_GET_REMOVE": "prendi e rimuovi", + "LISTS_GET_INDEX_REMOVE": "rimuovi", + "LISTS_GET_INDEX_FROM_END": "# dalla fine", + "LISTS_GET_INDEX_FIRST": "primo", + "LISTS_GET_INDEX_LAST": "ultimo", + "LISTS_GET_INDEX_RANDOM": "casuale", + "LISTS_GET_INDEX_TOOLTIP_GET_FROM_START": "Restituisce l'elemento nella posizione indicata della lista. 1 corrisponde al primo elemento della lista.", + "LISTS_GET_INDEX_TOOLTIP_GET_FROM_END": "Restituisce l'elemento nella posizione indicata della lista. 1 corrisponde all'ultimo elemento.", + "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Restituisce il primo elemento in una lista.", + "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Restituisce l'ultimo elemento in una lista.", + "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Restituisce un elemento casuale in una lista.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START": "Rimuove e restituisce l'elemento nella posizione indicata in una lista. 1 corrisponde al primo elemento.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END": "Rimuove e restituisce l'elemento nella posizione indicata in una lista. 1 corrisponde all'ultimo elemento.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Rimuove e restituisce il primo elemento in una lista.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Restituisce e rimuove l'ultimo elemento in una lista.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Restituisce e rimuove un elemento casuale in una lista.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START": "Rimuove l'elemento nella posizione indicata in una lista. 1 corrisponde al primo elemento.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END": "Rimuove l'elemento nella posizione indicata in una lista. 1 corrisponde all'ultimo elemento.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Rimuove il primo elemento in una lista.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Rimuove l'ultimo elemento in una lista.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Rimuove un elemento casuale in una lista.", + "LISTS_SET_INDEX_SET": "imposta", + "LISTS_SET_INDEX_INSERT": "inserisci in", + "LISTS_SET_INDEX_INPUT_TO": "come", + "LISTS_SET_INDEX_TOOLTIP_SET_FROM_START": "Imposta l'elemento nella posizione indicata di una lista. 1 corrisponde al primo elemento.", + "LISTS_SET_INDEX_TOOLTIP_SET_FROM_END": "Imposta l'elemento nella posizione indicata di una lista. 1 corrisponde all'ultimo elemento.", + "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Imposta il primo elemento in una lista.", + "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Imposta l'ultimo elemento in una lista.", + "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Imposta un elemento casuale in una lista.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START": "Inserisci un elemento nella posizione indicata in una lista. #1 corrisponde al primo elemento.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END": "Inserisci l'elemento nella posizione indicata in una lista. #1 corrisponde all'ultimo elemento.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Inserisci l'elemento all'inizio della lista.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Aggiungi un elemento alla fine di una lista", + "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Inserisce l'elemento casualmente in una lista.", + "LISTS_GET_SUBLIST_START_FROM_START": "prendi sotto-lista da #", + "LISTS_GET_SUBLIST_START_FROM_END": "prendi sotto-lista da # dalla fine", + "LISTS_GET_SUBLIST_START_FIRST": "prendi sotto-lista dall'inizio", + "LISTS_GET_SUBLIST_END_FROM_START": "fino a #", + "LISTS_GET_SUBLIST_END_FROM_END": "da # dalla fine", + "LISTS_GET_SUBLIST_END_LAST": "dagli ultimi", + "LISTS_GET_SUBLIST_TOOLTIP": "Crea una copia della porzione specificata di una lista.", + "VARIABLES_GET_TOOLTIP": "Restituisce il valore di una variabile.", + "VARIABLES_GET_CREATE_SET": "Crea 'imposta %1'", + "VARIABLES_SET_TITLE": "imposta", + "VARIABLES_SET_TAIL": "a", + "VARIABLES_SET_TOOLTIP": "Imposta questa variabile ad essere pari all'input.", + "VARIABLES_SET_CREATE_GET": "Crea 'prendi %1'", + "PROCEDURES_DEFNORETURN_TITLE": "per", + "PROCEDURES_DEFNORETURN_PROCEDURE": "fai qualcosa", + "PROCEDURES_BEFORE_PARAMS": "con\u02d0", + "PROCEDURES_DEFNORETURN_TOOLTIP": "Crea una funzione senza output.", + "PROCEDURES_DEFRETURN_RETURN": "ritorna", + "PROCEDURES_DEFRETURN_TOOLTIP": "Crea una funzione con un output.", + "PROCEDURES_DEF_DUPLICATE_WARNING": "Attenzione\u02d0 Questa funzione ha parametri duplicati.", + "PROCEDURES_CALLNORETURN_HELPURL": "http://it.wikipedia.org/wiki/Funzione_(informatica)", + "PROCEDURES_CALLNORETURN_TOOLTIP": "Esegue la funzione definita dall'utente '%1'.", + "PROCEDURES_CALLRETURN_HELPURL": "http://it.wikipedia.org/wiki/Funzione_(informatica)", + "PROCEDURES_CALLRETURN_TOOLTIP": "Esegue la funzione definita dall'utente '%1' ed usa il suo output.", + "PROCEDURES_MUTATORCONTAINER_TITLE": "input", + "PROCEDURES_MUTATORARG_TITLE": "nome input\u02d0", + "PROCEDURES_HIGHLIGHT_DEF": "Evidenzia definizione di funzione", + "PROCEDURES_CREATE_DO": "Crea '%1'", + "PROCEDURES_IFRETURN_TOOLTIP": "Se un valore \u00e8 vero allora restituisce un secondo valore.", + "PROCEDURES_IFRETURN_WARNING": "Attenzione\u02d0 Questo blocco pu\u00f2 essere usato solo all'interno di una definizione di funzione." +} \ No newline at end of file diff --git a/msg/json/keys.json b/msg/json/keys.json new file mode 100644 index 000000000..98232c64f --- /dev/null +++ b/msg/json/keys.json @@ -0,0 +1 @@ +{ diff --git a/msg/json/nl.json b/msg/json/nl.json new file mode 100644 index 000000000..209da973e --- /dev/null +++ b/msg/json/nl.json @@ -0,0 +1,138 @@ +{ + "@metadata": { + "authors": [ + "Siebrand" + ] + }, + "VARIABLES_DEFAULT_NAME": "item", + "DUPLICATE_BLOCK": "Duplicaat", + "ADD_COMMENT": "Reactie toevoegen", + "REMOVE_COMMENT": "Opmerking verwijderen", + "EXTERNAL_INPUTS": "Externe invoer", + "INLINE_INPUTS": "Inline invoer", + "DELETE_BLOCK": "Blok verwijderen", + "DELETE_X_BLOCKS": "%1 blokken verwijderen", + "COLLAPSE_BLOCK": "Blok inklappen", + "COLLAPSE_ALL": "Blokken inklappen", + "EXPAND_BLOCK": "Blok uitvouwen", + "EXPAND_ALL": "Blokken uitvouwen", + "DISABLE_BLOCK": "Blok uitschakelen", + "ENABLE_BLOCK": "Blok inschakelen", + "HELP": "Hulp", + "CHANGE_VALUE_TITLE": "Waarde wijzigen:", + "NEW_VARIABLE": "Nieuwe variabele...", + "NEW_VARIABLE_TITLE": "Nieuwe variabelenaam:", + "RENAME_VARIABLE": "Variabele hernoemen...", + "RENAME_VARIABLE_TITLE": "Alle variabelen \"%1\" hernoemen naar:", + "COLOUR_PICKER_HELPURL": "https://nl.wikipedia.org/wiki/Kleur", + "COLOUR_PICKER_TOOLTIP": "Kies een kleur in het palet.", + "COLOUR_RANDOM_TITLE": "willekeurige kleur", + "COLOUR_RANDOM_TOOLTIP": "Kies een willekeurige kleur.", + "COLOUR_RGB_TITLE": "kleuren met", + "COLOUR_RGB_RED": "rood", + "COLOUR_RGB_GREEN": "groen", + "COLOUR_RGB_BLUE": "blauw", + "COLOUR_RGB_TOOLTIP": "Maak een kleur met de opgegeven hoeveelheid rood, groen en blauw. Alle waarden moeten tussen 0 en 100 liggen.", + "COLOUR_BLEND_TITLE": "mengen", + "COLOUR_BLEND_COLOUR1": "kleur 1", + "COLOUR_BLEND_COLOUR2": "kleur 2", + "COLOUR_BLEND_RATIO": "verhouding", + "COLOUR_BLEND_TOOLTIP": "Mengt twee kleuren samen met een bepaalde verhouding (0.0 - 1.0).", + "CONTROLS_REPEAT_HELPURL": "http://en.wikipedia.org/wiki/For_loop", + "CONTROLS_REPEAT_TITLE": "%1 keer herhalen", + "CONTROLS_REPEAT_TITLE_REPEAT": "herhalen", + "CONTROLS_REPEAT_TITLE_TIMES": "keer", + "CONTROLS_REPEAT_INPUT_DO": "voer uit", + "CONTROLS_REPEAT_TOOLTIP": "Voer een aantal opdrachten meerdere keren uit.", + "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "herhalen terwijl", + "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "herhalen totdat", + "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Terwijl een waarde waar is de volgende opdrachten uitvoeren.", + "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Terwijl een waarde onwaar is de volgende opdrachten uitvoeren.", + "CONTROLS_FOR_TOOLTIP": "Laat de variabele %1 de waarden van het beginnummer tot het laatste nummer, tellende met het opgegeven interval, en met uitvoering van de opgegeven blokken.", + "CONTROLS_FOR_INPUT_WITH": "rekenen met", + "CONTROLS_FOR_INPUT_FROM_TO_BY": "van %1 tot %2 in stappen van %3", + "CONTROLS_FOREACH_INPUT_ITEM": "voor ieder item", + "CONTROLS_FOREACH_INPUT_INLIST": "in lijst", + "CONTROLS_FOREACH_TOOLTIP": "Voor ieder item in een lijst, stel de variabele \"%1\" in op het item en voer daarna opdrachten uit.", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "uit lus breken", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "doorgaan met de volgende iteratie van de lus", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "uit de bovenliggende lus breken", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "De rest van deze lus overslaan en doorgaan met de volgende iteratie.", + "CONTROLS_FLOW_STATEMENTS_WARNING": "Waarschuwing: dit blok mag alleen gebruikt worden in een lus.", + "CONTROLS_IF_TOOLTIP_1": "Als een waarde waar is, voer dan opdrachten uit.", + "CONTROLS_IF_TOOLTIP_2": "Als een waarde waar is, voert dan het eerste blok met opdrachten uit. Voer andere het tweede blok met opdrachten uit.", + "CONTROLS_IF_TOOLTIP_3": "Als de eerste waarde waar is, voer dan het eerste blok met opdrachten uit. Voer anders, als de tweede waarde waar is, het tweede blok met opdrachten uit.", + "CONTROLS_IF_MSG_IF": "als", + "CONTROLS_IF_MSG_ELSEIF": "anders als", + "CONTROLS_IF_MSG_ELSE": "anders", + "LOGIC_COMPARE_HELPURL": "https://nl.wikipedia.org/wiki/Ongelijkheid", + "LOGIC_OPERATION_AND": "en", + "LOGIC_OPERATION_OR": "of", + "LOGIC_NEGATE_TITLE": "not %1", + "LOGIC_BOOLEAN_TRUE": "waar", + "LOGIC_BOOLEAN_FALSE": "onwaar", + "LOGIC_NULL": "null", + "LOGIC_TERNARY_CONDITION": "test", + "LOGIC_TERNARY_IF_TRUE": "als waar", + "LOGIC_TERNARY_IF_FALSE": "als onwaar", + "MATH_NUMBER_HELPURL": "https://nl.wikipedia.org/wiki/Getal_%28wiskunde%29", + "MATH_NUMBER_TOOLTIP": "Een getal.", + "MATH_ARITHMETIC_HELPURL": "https://nl.wikipedia.org/wiki/Rekenen", + "MATH_SINGLE_HELPURL": "https://nl.wikipedia.org/wiki/Vierkantswortel", + "MATH_SINGLE_OP_ROOT": "wortel", + "MATH_SINGLE_OP_ABSOLUTE": "absoluut", + "MATH_TRIG_HELPURL": "https://nl.wikipedia.org/wiki/Goniometrische_functie", + "MATH_CONSTANT_HELPURL": "https://nl.wikipedia.org/wiki/Wiskundige_constante", + "MATH_IS_EVEN": "is even", + "MATH_IS_ODD": "is oneven", + "MATH_IS_PRIME": "is priemgetal", + "MATH_IS_WHOLE": "is geheel getal", + "MATH_IS_POSITIVE": "is positief", + "MATH_IS_NEGATIVE": "is negatief", + "MATH_IS_DIVISIBLE_BY": "is deelbaar door", + "MATH_CHANGE_TITLE_CHANGE": "wijzigen", + "MATH_CHANGE_INPUT_BY": "met", + "MATH_CHANGE_TOOLTIP": "Voegt een getal toe aan variabele \"%1\".", + "MATH_ROUND_HELPURL": "https://nl.wikipedia.org/wiki/Afronden", + "MATH_ROUND_TOOLTIP": "Rondt een getal af omhoog of naar beneden.", + "MATH_ROUND_OPERATOR_ROUND": "afronden", + "MATH_ROUND_OPERATOR_ROUNDUP": "omhoog afronden", + "MATH_ROUND_OPERATOR_ROUNDDOWN": "naar beneden afronden", + "MATH_ONLIST_OPERATOR_SUM": "som van lijst", + "MATH_ONLIST_OPERATOR_MIN": "laagste uit lijst", + "MATH_ONLIST_OPERATOR_MAX": "hoogste uit lijst", + "MATH_ONLIST_OPERATOR_AVERAGE": "gemiddelde van lijst", + "MATH_ONLIST_OPERATOR_MEDIAN": "mediaan van lijst", + "MATH_ONLIST_OPERATOR_MODE": "modi van lijst", + "MATH_ONLIST_OPERATOR_STD_DEV": "standaarddeviatie van lijst", + "MATH_ONLIST_OPERATOR_RANDOM": "willekeurige item van lijst", + "MATH_MODULO_HELPURL": "https://nl.wikipedia.org/wiki/Modulair_rekenen", + "MATH_RANDOM_INT_HELPURL": "https://nl.wikipedia.org/wiki/Toevalsgenerator", + "MATH_RANDOM_FLOAT_HELPURL": "https://nl.wikipedia.org/wiki/Toevalsgenerator", + "TEXT_TEXT_HELPURL": "https://nl.wikipedia.org/wiki/String_%28informatica%29", + "TEXT_CHARAT_INPUT_INTEXT": "in tekst", + "TEXT_CHARAT_FROM_START": "haal letter # op", + "TEXT_CHARAT_FROM_END": "haal letter # op vanaf einde", + "TEXT_CHARAT_FIRST": "haal eerste letter op", + "TEXT_CHARAT_LAST": "haal laatste letter op", + "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "naar HOOFDLETTERS", + "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "naar kleine letters", + "TEXT_CHANGECASE_OPERATOR_TITLECASE": "naar Hoofdletter Per Woord", + "LISTS_LENGTH_TITLE": "lengte van %1", + "LISTS_LENGTH_TOOLTIP": "Geeft de lengte van een lijst terug.", + "LISTS_IS_EMPTY_TITLE": "%1 is leeg", + "LISTS_TOOLTIP": "Geeft waar terug als de lijst leeg is.", + "LISTS_INLIST": "in lijst", + "LISTS_INDEX_OF_FIRST": "zoek eerste voorkomen van item", + "LISTS_INDEX_OF_LAST": "zoek laatste voorkomen van item", + "LISTS_INDEX_OF_TOOLTIP": "Geeft de index van het eerste of laatste voorkomen van een item in de lijst terug. Geeft 0 terug als de tekst niet is gevonden.", + "LISTS_GET_INDEX_GET": "haal op", + "LISTS_GET_INDEX_GET_REMOVE": "haal op en verwijder", + "LISTS_GET_INDEX_REMOVE": "verwijder", + "LISTS_GET_INDEX_FROM_END": "# van einde", + "LISTS_GET_INDEX_FIRST": "eerste", + "LISTS_GET_INDEX_LAST": "laatste", + "LISTS_GET_INDEX_RANDOM": "willekeurig", + "PROCEDURES_CALLNORETURN_HELPURL": "https://nl.wikipedia.org/wiki/Subprogramma", + "PROCEDURES_CALLRETURN_HELPURL": "https://nl.wikipedia.org/wiki/Subprogramma" +} \ No newline at end of file diff --git a/msg/json/pt_br.json b/msg/json/pt_br.json new file mode 100644 index 000000000..a2fb8a377 --- /dev/null +++ b/msg/json/pt_br.json @@ -0,0 +1,287 @@ +{ +"DUPLICATE_BLOCK": "Duplicado", +"REMOVE_COMMENT": "Remover Comentário", +"ADD_COMMENT": "Criar Comentário", +"EXTERNAL_INPUTS": "Entradas Externas", +"INLINE_INPUTS": "Entradas Internas", +"DELETE_BLOCK": "Excluir Bloco", +"DELETE_X_BLOCKS": "Excluir %1 Blocos", +"COLLAPSE_BLOCK": "Recolher Bloco", +"EXPAND_BLOCK": "Expandir Bloco", +"DISABLE_BLOCK": "Desabilitar Bloco", +"ENABLE_BLOCK": "Habilitar Bloco", +"HELP": "Ajuda", +"COLLAPSE_ALL": "Recolher Blocos", +"EXPAND_ALL": "Expandir Blocos", +"CHANGE_VALUE_TITLE": "Alterar valor:", +"NEW_VARIABLE": "Nova variável...", +"NEW_VARIABLE_TITLE": "Novo nome de variável:", +"RENAME_VARIABLE": "Renomear variável...", +"RENAME_VARIABLE_TITLE": "Renomear todas as \"%1\" variáveis para:", +"COLOUR_PICKER_HELPURL": "http://pt.wikipedia.org/wiki/Cor", +"COLOUR_PICKER_TOOLTIP": "Escolha uma cor da palheta de cores.", +"COLOUR_RANDOM_TITLE": "cor aleatória", +"COLOUR_RANDOM_TOOLTIP": "Escolher uma cor aleatoriamente.", +"COLOUR_RGB_TITLE": "cor com", +"COLOUR_RGB_RED": "vermelho", +"COLOUR_RGB_GREEN": "verde", +"COLOUR_RGB_BLUE": "azul", +"COLOUR_RGB_TOOLTIP": "Crie uma cor com os valores especificados de vermelho, verde e azul. Todos os valores devem estar entre 0 e 100.", +"COLOUR_BLEND_TITLE": "misturar", +"COLOUR_BLEND_COLOUR1": "cor 1", +"COLOUR_BLEND_COLOUR2": "cor 2", +"COLOUR_BLEND_RATIO": "razão", +"COLOUR_BLEND_TOOLTIP": "Mistura duas cores usando uma razão dada (0.0 - 1.0).", +"CONTROLS_REPEAT_TITLE": "repetir %1 vezes", +"CONTROLS_REPEAT_TITLE_REPEAT": "repetir", +"CONTROLS_REPEAT_TITLE_TIMES": "vezes", +"CONTROLS_REPEAT_INPUT_DO": "faça", +"CONTROLS_REPEAT_TOOLTIP": "Realiza os passos várias vezes.", +"CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "repita enquanto", +"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "repita até", +"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Enquanto um valor é verdadeiro, então realize alguns passos.", +"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Enquanto um valor é falso, então realize alguns passos.", +"CONTROLS_FOR_INPUT_WITH": "contar com", +"CONTROLS_FOR_INPUT_FROM_TO_BY": "de %1 ate %2 por %3", +"CONTROLS_FOR_TOOLTIP": "Conta de um número inicial até um número final pelo intervalo especificado. Para cada contagem, define o contador atual para a variável \"%1\", e então realiza alguns passos.", +"CONTROLS_FOREACH_INPUT_ITEM": "para cada item", +"CONTROLS_FOREACH_INPUT_INLIST": "na lista", +"CONTROLS_FOREACH_INPUT_INLIST_TAIL": "", +"CONTROLS_FOREACH_TOOLTIP": "Para cada item em uma lista, define o item para a variável \"%1\", e então realiza alguns passos.", +"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "encerra o laço", +"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "continua com a próxima iteração do laço", +"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Encerra o laço.", +"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Ignora o resto deste laço, e continua com a próxima iteração.", +"CONTROLS_FLOW_STATEMENTS_WARNING": "Atenção: Este bloco só pode ser usado dentro de um laço.", +"CONTROLS_IF_TOOLTIP_1": "Se um valor é verdadeiro, então realize alguns passos.", +"CONTROLS_IF_TOOLTIP_2": "Se um valor é verdadeiro, então realize o primeiro bloco de passos. Senão, realize o segundo bloco de passos.", +"CONTROLS_IF_TOOLTIP_3": "Se o primeiro valor é verdadeiro, então realize o primeiro bloco de passos. Senão, se o segundo valor é verdadeiro, realize o segundo bloco de passos.", +"CONTROLS_IF_TOOLTIP_4": "Se o primeiro valor é verdadeiro, então realize o primeiro bloco de passos. Senão, se o segundo valor é verdadeiro, realize o segundo bloco de passos. Se nenhum dos blocos for verdadeiro, realize o último bloco de passos.", +"CONTROLS_IF_MSG_IF": "se", +"CONTROLS_IF_MSG_ELSEIF": "senão se", +"CONTROLS_IF_MSG_ELSE": "senão", +"CONTROLS_IF_IF_TOOLTIP": "Acrescente, remova ou reordene seções para reconfigurar este bloco.", +"CONTROLS_IF_ELSEIF_TOOLTIP": "Acrescente uma condição para o bloco se.", +"CONTROLS_IF_ELSE_TOOLTIP": "Acrescente uma condição final para o bloco se.", +"LOGIC_COMPARE_TOOLTIP_EQ": "Retorna verdadeiro se ambas as entradas forem iguais.", +"LOGIC_COMPARE_TOOLTIP_NEQ": "Retorna verdadeiro se ambas as entradas forem diferentes.", +"LOGIC_COMPARE_TOOLTIP_LT": "Retorna verdadeiro se a primeira entrada for menor que a segunda entrada.", +"LOGIC_COMPARE_TOOLTIP_LTE": "Retorna verdadeiro se a primeira entrada for menor ou igual à segunda entrada.", +"LOGIC_COMPARE_TOOLTIP_GT": "Retorna verdadeiro se a primeira entrada for maior que a segunda entrada.", +"LOGIC_COMPARE_TOOLTIP_GTE": "Retorna verdadeiro se a primeira entrada for maior ou igual à segunda entrada.", +"LOGIC_OPERATION_AND": "e", +"LOGIC_OPERATION_OR": "ou", +"LOGIC_OPERATION_TOOLTIP_AND": "Retorna verdadeiro se ambas as entradas forem verdadeiras.", +"LOGIC_OPERATION_TOOLTIP_OR": "Retorna verdadeiro se uma das estradas for verdadeira.", +"LOGIC_NEGATE_TITLE": "não %1", +"LOGIC_NEGATE_TOOLTIP": "Retorna verdadeiro se a entrada for falsa. Retorna false se a entrada for verdadeira.", +"LOGIC_BOOLEAN_TRUE": "verdadeiro", +"LOGIC_BOOLEAN_FALSE": "falso", +"LOGIC_BOOLEAN_TOOLTIP": "Retorna verdadeiro ou falso.", +"LOGIC_NULL": "nulo", +"LOGIC_NULL_TOOLTIP": "Retorna nulo.", +"LOGIC_TERNARY_CONDITION": "teste", +"LOGIC_TERNARY_IF_TRUE": "se verdadeiro", +"LOGIC_TERNARY_IF_FALSE": "se falso", +"LOGIC_TERNARY_TOOLTIP": "Avalia a condição em \"teste\". Se a condição for verdadeira retorna o valor \"se verdadeiro\", senão retorna o valor \"se falso\".", +"MATH_NUMBER_TOOLTIP": "Um número.", +"MATH_ARITHMETIC_TOOLTIP_ADD": "Retorna a soma de dois números.", +"MATH_ARITHMETIC_TOOLTIP_MINUS": "Retorna a diferença de dois números.", +"MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Retorna o produto de dois números.", +"MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Retorna o quociente da divisão de dois números.", +"MATH_ARITHMETIC_TOOLTIP_POWER": "Retorna o primeiro número elevado à potência do segundo número.", +"MATH_SINGLE_OP_ROOT": "raíz quadrada", +"MATH_SINGLE_OP_ABSOLUTE": "absoluto", +"MATH_SINGLE_TOOLTIP_ROOT": "Retorna a raiz quadrada de um número.", +"MATH_SINGLE_TOOLTIP_ABS": "Retorna o valor absoluto de um número.", +"MATH_SINGLE_TOOLTIP_NEG": "Retorna o oposto de um número.", +"MATH_SINGLE_TOOLTIP_LN": "Retorna o logarítmo natural de um número.", +"MATH_SINGLE_TOOLTIP_LOG10": "Retorna o logarítmo em base 10 de um número.", +"MATH_SINGLE_TOOLTIP_EXP": "Retorna o número e elevado à potência de um número.", +"MATH_SINGLE_TOOLTIP_POW10": "Retorna 10 elevado à potência de um número.", +"MATH_TRIG_TOOLTIP_SIN": "Retorna o seno de um grau (não radiano).", +"MATH_TRIG_TOOLTIP_COS": "Retorna o cosseno de um grau (não radiano).", +"MATH_TRIG_TOOLTIP_TAN": "Retorna a tangente de um grau (não radiano).", +"MATH_TRIG_TOOLTIP_ASIN": "Retorna o arco seno de um número.", +"MATH_TRIG_TOOLTIP_ACOS": "Retorna o arco cosseno de um número.", +"MATH_TRIG_TOOLTIP_ATAN": "Retorna o arco tangente de um número.", +"MATH_CONSTANT_TOOLTIP": "Retorna uma das constantes comuns: \u03c0 (3.141\u2026), e (2.718\u2026), \u03c6 (1.618\u2026), sqrt(2) (1.414\u2026), sqrt(\u00bd) (0.707\u2026), ou \u221e (infinito).", +"MATH_IS_EVEN": "é par", +"MATH_IS_ODD": "é impar", +"MATH_IS_PRIME": "é primo", +"MATH_IS_WHOLE": "é inteiro", +"MATH_IS_POSITIVE": "é positivo", +"MATH_IS_NEGATIVE": "é negativo", +"MATH_IS_DIVISIBLE_BY": "é divisível por", +"MATH_IS_TOOLTIP": "Verifica se um número é par, impar, inteiro, positivo, negativo, ou se é divisível por outro número. Retorna verdadeiro ou falso.", +"MATH_CHANGE_TITLE_CHANGE": "alterar", +"MATH_CHANGE_TITLE_ITEM": "item", +"MATH_CHANGE_INPUT_BY": "por", +"MATH_CHANGE_TOOLTIP": "Soma um número à variável \"%1\".", +"MATH_ROUND_TOOLTIP": "Arredonda um número para cima ou para baixo.", +"MATH_ROUND_OPERATOR_ROUND": "arredonda", +"MATH_ROUND_OPERATOR_ROUNDUP": "arredonda para cima", +"MATH_ROUND_OPERATOR_ROUNDDOWN": "arredonda para baixo", +"MATH_ONLIST_HELPURL": "", +"MATH_ONLIST_OPERATOR_SUM": "soma de uma lista", +"MATH_ONLIST_OPERATOR_MIN": "menor de uma lista", +"MATH_ONLIST_OPERATOR_MAX": "maior de uma lista", +"MATH_ONLIST_OPERATOR_AVERAGE": "média de uma lista", +"MATH_ONLIST_OPERATOR_MEDIAN": "mediana de uma lista", +"MATH_ONLIST_OPERATOR_MODE": "modo de uma lista", +"MATH_ONLIST_OPERATOR_STD_DEV": "desvio padrão de uma lista", +"MATH_ONLIST_OPERATOR_RANDOM": "item aleatório de uma lista", +"MATH_ONLIST_TOOLTIP_SUM": "Retorna a soma de todos os números em uma lista.", +"MATH_ONLIST_TOOLTIP_MIN": "Retorna o menor número de uma lista.", +"MATH_ONLIST_TOOLTIP_MAX": "Retorna o maior número de uma lista.", +"MATH_ONLIST_TOOLTIP_AVERAGE": "Retorna a média aritmética de os números de uma lista.", +"MATH_ONLIST_TOOLTIP_MEDIAN": "Retorna a mediana de os números em uma lista.", +"MATH_ONLIST_TOOLTIP_MODE": "Retorna a lista de item(ns) mais comum(ns) de uma lista.", +"MATH_ONLIST_TOOLTIP_STD_DEV": "Retorna o desvio padrão de os números de uma lista.", +"MATH_ONLIST_TOOLTIP_RANDOM": "Retorna um elemento aleatório de uma lista.", +"MATH_MODULO_TITLE": "resto da divisão de %1 \u00f7 %2", +"MATH_MODULO_TOOLTIP": "Retorna o resto da divisão de dois números.", +"MATH_CONSTRAIN_TITLE": "restringe %1 inferior %2 superior %3", +"MATH_CONSTRAIN_TOOLTIP": "Restringe um número entre os limites especificados (inclusive).", +"MATH_RANDOM_INT_TITLE": "inteiro aleatório entre %1 ate %2", +"MATH_RANDOM_INT_TOOLTIP": "Retorna um número inteiro entre os dois limites informados, inclusive.", +"MATH_RANDOM_FLOAT_TITLE_RANDOM": "random fraction", +"MATH_RANDOM_FLOAT_TOOLTIP": "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive).", +"TEXT_TEXT_TOOLTIP": "Uma letra, palavra ou linha de texto.", +"TEXT_JOIN_HELPURL": "", +"TEXT_JOIN_TITLE_CREATEWITH": "criar texto com", +"TEXT_JOIN_TOOLTIP": "Criar um pedaço de texto juntando qualquer número de itens.", +"TEXT_CREATE_JOIN_TITLE_JOIN": "unir", +"TEXT_CREATE_JOIN_TOOLTIP": "Acrescenta, remove ou reordena seções para reconfigurar este bloco de texto.", +"TEXT_CREATE_JOIN_ITEM_TITLE_ITEM": "item", +"TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Acrescentar um item ao texto.", +"TEXT_APPEND_TO": "para", +"TEXT_APPEND_APPENDTEXT": "acrescentar texto", +"TEXT_APPEND_VARIABLE": "item", +"TEXT_APPEND_TOOLTIP": "Acrescentar um pedaço de texto à variável \"%1\".", +"TEXT_LENGTH_TITLE": "tamanho de %1", +"TEXT_LENGTH_TOOLTIP": "Conta o número de letras (incluindo espaços) no texto fornecido.", +"TEXT_ISEMPTY_TITLE": "%1 é vazio", +"TEXT_ISEMPTY_TOOLTIP": "Retorna verdadeiro se o texto fornecido for vazio.", +"TEXT_INDEXOF_INPUT_INTEXT": "no texto", +"TEXT_INDEXOF_OPERATOR_FIRST": "primeira ocorrência do texto", +"TEXT_INDEXOF_OPERATOR_LAST": "última ocorrência do texto", +"TEXT_INDEXOF_TOOLTIP": "Retorna a posição da primeira/última ocorrência do primeiro texto no segundo texto. Retorna 0 se o texto não for encontrado.", +"TEXT_CHARAT_INPUT_INTEXT": "no texto", +"TEXT_CHARAT_FROM_START": "obter letra nº", +"TEXT_CHARAT_FROM_END": "obter letra nº a partir do final", +"TEXT_CHARAT_FIRST": "obter primeira letra", +"TEXT_CHARAT_LAST": "obter última letra", +"TEXT_CHARAT_RANDOM": "obter letra aleatória", +"TEXT_CHARAT_TAIL": "", +"TEXT_CHARAT_TOOLTIP": "Retorna a letra na posição especificada.", +"TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "no texto", +"TEXT_GET_SUBSTRING_START_FROM_START": "obter trecho de letra nº", +"TEXT_GET_SUBSTRING_START_FROM_END": "obter trecho de letra nº a partir do final", +"TEXT_GET_SUBSTRING_END_FROM_START": "até letra nº", +"TEXT_GET_SUBSTRING_END_FROM_END": "até letra nº a partir do final", +"TEXT_GET_SUBSTRING_START_FIRST": "obter trecho de primeira letra", +"TEXT_GET_SUBSTRING_END_LAST": "até última letra", +"TEXT_GET_SUBSTRING_TAIL": "", +"TEXT_GET_SUBSTRING_TOOLTIP": "Retorna o trecho de texto especificado.", +"TEXT_CHANGECASE_OPERATOR_UPPERCASE": "para MAIÚSCULAS", +"TEXT_CHANGECASE_OPERATOR_LOWERCASE": "para minúsculas", +"TEXT_CHANGECASE_OPERATOR_TITLECASE": "para Nomes Próprios", +"TEXT_CHANGECASE_TOOLTIP": "Retorna uma cópia do texto em um formato diferente.", +"TEXT_TRIM_OPERATOR_BOTH": "remover espaços de ambos os lados", +"TEXT_TRIM_OPERATOR_LEFT": "remover espaços à esquerda", +"TEXT_TRIM_OPERATOR_RIGHT": "remover espaços à direita", +"TEXT_TRIM_TOOLTIP": "Retorna uma cópia do texto com os espaços removidos de uma ou ambas extremidades.", +"TEXT_PRINT_TITLE": "imprime %1", +"TEXT_PRINT_TOOLTIP": "Imprime o texto, número ou valor especificado.", +"TEXT_PROMPT_TYPE_TEXT": "Pede um texto com uma mensagem", +"TEXT_PROMPT_TYPE_NUMBER": "Pede um número com uma mensagem", +"TEXT_PROMPT_TOOLTIP_NUMBER": "Pede ao usuário um número.", +"TEXT_PROMPT_TOOLTIP_TEXT": "Pede ao usuário um texto.", +"LISTS_CREATE_EMPTY_TITLE": "criar lista vazia", +"LISTS_CREATE_EMPTY_TOOLTIP": "Retorna uma lista, de tamanho 0, contendo nenhum registro", +"LISTS_CREATE_WITH_INPUT_WITH": "criar lista com", +"LISTS_CREATE_WITH_TOOLTIP": "Cria uma lista com a quantidade de itens informada.", +"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "lista", +"LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Acrescente, remova ou reordene as seções para reconfigurar este bloco.", +"LISTS_CREATE_WITH_ITEM_TITLE": "item", +"LISTS_CREATE_WITH_ITEM_TOOLTIP": "Acrescenta um item à lista.", +"LISTS_REPEAT_TITLE": "criar lista com item %1 repetido %2 vezes", +"LISTS_REPEAT_TOOLTIP": "Cria uma lista consistida pelo valor informado repetido o número de vezes especificado.", +"LISTS_LENGTH_TITLE": "tamanho de %1", +"LISTS_LENGTH_TOOLTIP": "Retorna o tamanho de uma lista.", +"LISTS_IS_EMPTY_TITLE": "%1 é vazia", +"LISTS_TOOLTIP": "Retona verdadeiro se a lista estiver vazia.", +"LISTS_INDEX_OF_FIRST": "encontre a primeira ocorrência do item", +"LISTS_INDEX_OF_LAST": "encontre a última ocorrência do item", +"LISTS_INDEX_OF_TOOLTIP": "Retorna a posição da primeira/última ocorrência do item na lista. Retorna 0 se o texto não for encontrado.", +"LISTS_GET_INDEX_GET": "obter", +"LISTS_GET_INDEX_GET_REMOVE": "obter e remover", +"LISTS_GET_INDEX_REMOVE": "remover", +"LISTS_GET_INDEX_FROM_START": "nº", +"LISTS_GET_INDEX_FROM_END": "nº a partir do final", +"LISTS_GET_INDEX_FIRST": "primeiro", +"LISTS_GET_INDEX_LAST": "último", +"LISTS_GET_INDEX_RANDOM": "aleatório", +"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START": "Retorna o item da lista na posição especificada. #1 é o primeiro item.", +"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END": "Retorna o item da lista na posição especificada. #1 é o último item.", +"LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Retorna o primeiro item em uma lista.", +"LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Retorna o último item em uma lista.", +"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Retorna um item aleatório de uma lista.", +"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START": "Remove and retorna o item na posição especificada em uma lista. #1 é o primeiro item.", +"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END": "Remove and retorna o item na posição especificada em uma lista. #1 é o último item.", +"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Remove e retorna o primeiro item de uma lista.", +"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Remove e retorna o último item de uma lista.", +"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Remove e retorna um item aleatório de uma lista.", +"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START": "Remove e retorna o item na posição especificada em uma lista. #1 é o primeiro item.", +"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END": "Removes the item at the specified position em uma lista. #1 é o último item.", +"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Remove o primeiro item de uma lista.", +"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Remove o último item de uma lista.", +"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Remove um item aleatório de uma lista.", +"LISTS_SET_INDEX_SET": "definir", +"LISTS_SET_INDEX_INSERT": "inserir em", +"LISTS_SET_INDEX_INPUT_TO": "como", +"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START": "Define o item da posição especificada de uma lista. #1 é o primeiro item.", +"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END": "Define o item da posição especificada de uma lista. #1 é o último item.", +"LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Define o primeiro item de uma lista.", +"LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Define o último item de uma lista.", +"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Define um item aleatório de uma lista.", +"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START": "Insere o item na posição especificada em uma lista. #1 é o primeiro item.", +"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END": "Insere o item na posição especificada em uma lista. #1 é o último item.", +"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Insere o item no início da lista.", +"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Insere o item no final da lista.", +"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Insere o item em uma posição qualquer da lista.", +"LISTS_GET_SUBLIST_START_FROM_START": "obtem sublista de nº", +"LISTS_GET_SUBLIST_START_FROM_END": "obtem sublista de nº a partir do final", +"LISTS_GET_SUBLIST_START_FIRST": "obtem sublista primeiro", +"LISTS_GET_SUBLIST_END_FROM_START": "até nº", +"LISTS_GET_SUBLIST_END_FROM_END": "até nº a partir do final", +"LISTS_GET_SUBLIST_END_LAST": "até último", + +"LISTS_GET_SUBLIST_TOOLTIP": "Cria uma cópia da porção especificada de uma lista.", +"VARIABLES_GET_TITLE": "", +"VARIABLES_GET_TAIL": "", +"VARIABLES_GET_TOOLTIP": "Retorna o valor desta variável.", +"VARIABLES_GET_CREATE_SET": "Criar \"definir %1\"", +"VARIABLES_SET_TITLE": "definir", +"VARIABLES_SET_TAIL": "para", +"VARIABLES_SET_TOOLTIP": "Define esta variável para o valor informado.", +"VARIABLES_SET_CREATE_GET": "Criar \"obter %1\"", +"PROCEDURES_DEFNORETURN_TITLE": "para", +"PROCEDURES_DEFNORETURN_PROCEDURE": "faça algo", +"PROCEDURES_BEFORE_PARAMS": "com:", +"PROCEDURES_DEFNORETURN_DO": "", +"PROCEDURES_DEFNORETURN_TOOLTIP": "Cria uma função que não tem retorno.", +"PROCEDURES_DEFRETURN_RETURN": "retorna", +"PROCEDURES_DEFRETURN_TOOLTIP": "Cria uma função que possui um valor de retorno.", +"PROCEDURES_DEF_DUPLICATE_WARNING": "Atenção: Esta função tem parâmetros duplicados.", +"PROCEDURES_CALLNORETURN_CALL": "", +"PROCEDURES_CALLNORETURN_TOOLTIP": "Executa a função \"%1\".", +"PROCEDURES_CALLRETURN_TOOLTIP": "Executa a função \"%1\" e usa seu retorno.", +"PROCEDURES_MUTATORCONTAINER_TITLE": "entradas", +"PROCEDURES_MUTATORARG_TITLE": "nome da entrada:", +"PROCEDURES_HIGHLIGHT_DEF": "Destacar definição de procedimento", +"PROCEDURES_CREATE_DO": "Criar \"%1\"", +"PROCEDURES_IFRETURN_TOOLTIP": "Se o valor é verdadeiro, então retorna um valor.", +"PROCEDURES_IFRETURN_WARNING": "Atenção: Este bloco só pode ser utilizado dentro da definição de uma função." +} diff --git a/msg/json/qqq.json b/msg/json/qqq.json new file mode 100644 index 000000000..a016ce199 --- /dev/null +++ b/msg/json/qqq.json @@ -0,0 +1,355 @@ +{ + "@metadata": { + "authors": [ + "Espertus", + "Shirayuki" + ] + }, + "VARIABLES_DEFAULT_NAME": "default name - A simple, general default name for a variable, preferably short. For more context, see [[Translating:Blockly#infrequent_message_types]].", + "DUPLICATE_BLOCK": "context menu - Make a copy of the selected block (and any blocks it contains).", + "ADD_COMMENT": "context menu - Add a descriptive comment to the selected block.", + "REMOVE_COMMENT": "context menu - Remove the descriptive comment from the selected block.", + "EXTERNAL_INPUTS": "context menu - Change from 'external' to 'inline' mode for displaying blocks used as inputs to the selected block. See [[Translating:Blockly#context_menus]].", + "INLINE_INPUTS": "context menu - Change from 'internal' to 'external' mode for displaying blocks used as inputs to the selected block. See [[Translating:Blockly#context_menus]].", + "DELETE_BLOCK": "context menu - Permanently delete the selected block.", + "DELETE_X_BLOCKS": "context menu - Permanently delete the %1 selected blocks.\n\nParameters:\n* %1 - an integer greater than 1.", + "COLLAPSE_BLOCK": "context menu - Make the appearance of the selected block smaller by hiding some information about it.", + "COLLAPSE_ALL": "context menu - Make the appearance of the selected blocks smaller by hiding some information about it. Use the same terminology as in the previous message.", + "EXPAND_BLOCK": "context menu - Restore the appearance of the selected block by showing information about it that was hidden (collapsed) earlier.", + "EXPAND_ALL": "context menu - Restore the appearance of the selected block by showing information about it that was hidden (collapsed) earlier. Use the same terminology as in the previous message.", + "DISABLE_BLOCK": "context menu - Make the selected block have no effect (unless reenabled).", + "ENABLE_BLOCK": "context menu - Make the selected block have effect (after having been disabled earlier).", + "HELP": "context menu - Provide helpful information about the selected block.\n{{Identical|Help}}", + "CHANGE_VALUE_TITLE": "prompt - This message is only seen in the Opera browser. With most browsers, users can edit numeric values in blocks by just clicking and typing. Opera does not allows this, so we have to open a new window and prompt users with this message to chanage a value.", + "NEW_VARIABLE": "dropdown choice - When the user clicks on a variable block, this is one of the dropdown menu choices. It is used to define a new variable. See [https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu].", + "NEW_VARIABLE_TITLE": "prompt - Prompts the user to enter the name for a new variable. See [https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu].", + "RENAME_VARIABLE": "dropdown choice - When the user clicks on a variable block, this is one of the dropdown menu choices. It is used to rename the current variable. See [https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu].", + "RENAME_VARIABLE_TITLE": "prompt - Prompts the user to enter the new name for the selected variable. See [https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu].\n\nParameters:\n* %1 - the name of the variable to be renamed.", + "COLOUR_PICKER_HELPURL": "url - Information about colour.", + "COLOUR_PICKER_TOOLTIP": "tooltip - See [https://code.google.com/p/blockly/wiki/Colour#Picking_a_colour_from_a_palette https://code.google.com/p/blockly/wiki/Colour#Picking_a_colour_from_a_palette].", + "COLOUR_RANDOM_HELPURL": "url - A link that displays a random colour each time you visit it.", + "COLOUR_RANDOM_TITLE": "block text - Title of block that generates a colour at random.", + "COLOUR_RANDOM_TOOLTIP": "tooltip - See [https://code.google.com/p/blockly/wiki/Colour#Generating_a_random_colour https://code.google.com/p/blockly/wiki/Colour#Generating_a_random_colour].", + "COLOUR_RGB_HELPURL": "url - A link for color codes with percentages (0-100%) for each component, instead of the more common 0-255, which may be more difficult for beginners.", + "COLOUR_RGB_TITLE": "block text - Title of block for [https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components].", + "COLOUR_RGB_RED": "block input text - The amount of red (from 0 to 100) to use when [https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components].\n{{Identical|Red}}", + "COLOUR_RGB_GREEN": "block input text - The amount of green (from 0 to 100) to use when [https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components].", + "COLOUR_RGB_BLUE": "block input text - The amount of blue (from 0 to 100) to use when [https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components].\n{{Identical|Blue}}", + "COLOUR_RGB_TOOLTIP": "tooltip - See [https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components].", + "COLOUR_BLEND_HELPURL": "url - A useful link that displays blending of two colors.", + "COLOUR_BLEND_TITLE": "block text - A verb for blending two shades of paint.", + "COLOUR_BLEND_COLOUR1": "block input text - The first of two colours to [https://code.google.com/p/blockly/wiki/Colour#Blending_colours blend].", + "COLOUR_BLEND_COLOUR2": "block input text - The second of two colours to [https://code.google.com/p/blockly/wiki/Colour#Blending_colours blend].", + "COLOUR_BLEND_RATIO": "block input text - The proportion of the [https://code.google.com/p/blockly/wiki/Colour#Blending_colours blend] containing the first color; the remaining proportion is of the second colour. For example, if the first colour is red and the second color blue, a ratio of 1 would yield pure red, a ratio of .5 would yield purple (equal amounts of red and blue), and a ratio of 0 would yield pure blue.", + "COLOUR_BLEND_TOOLTIP": "tooltip - See [https://code.google.com/p/blockly/wiki/Colour#Blending_colours https://code.google.com/p/blockly/wiki/Colour#Blending_colours].", + "CONTROLS_REPEAT_HELPURL": "url - Describes 'repeat loops' in computer programs; consider using the translation of the page [http://en.wikipedia.org/wiki/Control_flow http://en.wikipedia.org/wiki/Control_flow].", + "CONTROLS_REPEAT_TITLE": "block input text - Title of [https://code.google.com/p/blockly/wiki/Loops#repeat repeat block].\n\nParameters:\n* %1 - the number of times the body of the loop should be repeated.", + "CONTROLS_REPEAT_TITLE_REPEAT": "block text - Text preceding the number of repetitions in a [https://code.google.com/p/blockly/wiki/Loops#repeat repeat block]. (This is redundant with the previous message but is needed to support older code.)", + "CONTROLS_REPEAT_TITLE_TIMES": "block text - Text following the number of times a [https://code.google.com/p/blockly/wiki/Loops#repeat repeat loop] should be repeated. (This is redundant but is needed to support older code.)", + "CONTROLS_REPEAT_INPUT_DO": "block text - Preceding the blocks in the body of the loop. See [https://code.google.com/p/blockly/wiki/Loops https://code.google.com/p/blockly/wiki/Loops].", + "CONTROLS_REPEAT_TOOLTIP": "tooltip - See [https://code.google.com/p/blockly/wiki/Loops#repeat https://code.google.com/p/blockly/wiki/Loops#repeat].", + "CONTROLS_WHILEUNTIL_HELPURL": "url - Describes 'while loops' in computer programs; consider using the translation of [http://en.wikipedia.org/wiki/While_loop http://en.wikipedia.org/wiki/While_loop], if present, or [http://en.wikipedia.org/wiki/Control_flow http://en.wikipedia.org/wiki/Control_flow].", + "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "dropdown - Specifies that a loop should [https://code.google.com/p/blockly/wiki/Loops#Repeat_while repeat while] the following condition is true.", + "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "dropdown - Specifies that a loop should [https://code.google.com/p/blockly/wiki/Loops#Repeat_until repeat until] the following condition becomes true.", + "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "tooltip - See [https://code.google.com/p/blockly/wiki/Loops#repeat_while Loops#repeat_while https://code.google.com/p/blockly/wiki/Loops#repeat_while Loops#repeat_while].", + "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "tooltip - See [https://code.google.com/p/blockly/wiki/Loops#repeat_until https://code.google.com/p/blockly/wiki/Loops#repeat_until].", + "CONTROLS_FOR_HELPURL": "url - Describes 'for loops' in computer programs. Consider using your language's translation of [http://en.wikipedia.org/wiki/For_loop http://en.wikipedia.org/wiki/For_loop], if present.", + "CONTROLS_FOR_TOOLTIP": "tooltip - See [https://code.google.com/p/blockly/wiki/Loops#count_with https://code.google.com/p/blockly/wiki/Loops#count_with].\n\nParameters:\n* %1 - the name of the loop variable.", + "CONTROLS_FOR_INPUT_WITH": "block title - Title of [https://code.google.com/p/blockly/wiki/Loops#count_with count with] blocks. [[File:Blockly-count-with.png]]", + "CONTROLS_FOR_INPUT_FROM_TO_BY": "block text - Starting with a (usually lower) number in a range (%1), ending with a (usually higher) number in a range (%2), and counting the iterations by a number of steps (%3). As in [https://code.google.com/p/blockly/wiki/Loops#count_with https://code.google.com/p/blockly/wiki/Loops#count_with]. [[File:Blockly-count-with.png]]", + "CONTROLS_FOREACH_HELPURL": "url - Describes 'for-each loops' in computer programs. Consider using your language's translation of [http://en.wikipedia.org/wiki/Foreach http://en.wikipedia.org/wiki/Foreach] if present.", + "CONTROLS_FOREACH_INPUT_ITEM": "block text - Title of [https://code.google.com/p/blockly/wiki/Loops#for_each for each block].", + "CONTROLS_FOREACH_INPUT_INLIST": "block text - Preceding the list that should be iterated over in a [https://code.google.com/p/blockly/wiki/Loops#for_each for each loop].", + "CONTROLS_FOREACH_INPUT_INLIST_TAIL": "block text - Following the list that should be iterated over in a [https://code.google.com/p/blockly/wiki/Loops#for_each for each loop]. This is empty in most, but not all, languages.", + "CONTROLS_FOREACH_TOOLTIP": "block text - Description of [https://code.google.com/p/blockly/wiki/Loops#for_each for each blocks].\n\nParameters:\n* %1 - the name of the loop variable.", + "CONTROLS_FLOW_STATEMENTS_HELPURL": "url - Describes control flow in computer programs. Consider using your language's translation of [http://en.wikipedia.org/wiki/Control_flow http://en.wikipedia.org/wiki/Control_flow], if it exists.", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "dropdown - The current loop should be exited. See [https://code.google.com/p/blockly/wiki/Loops#break https://code.google.com/p/blockly/wiki/Loops#break].", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "dropdown - The current iteration of the loop should be ended and the next should begin. See [https://code.google.com/p/blockly/wiki/Loops#continue_with_next_iteration https://code.google.com/p/blockly/wiki/Loops#continue_with_next_iteration].", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "tooltip - See [https://code.google.com/p/blockly/wiki/Loops#break_out_of_loop https://code.google.com/p/blockly/wiki/Loops#break_out_of_loop].", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "tooltip - See [https://code.google.com/p/blockly/wiki/Loops#continue_with_next_iteration https://code.google.com/p/blockly/wiki/Loops#continue_with_next_iteration].", + "CONTROLS_FLOW_STATEMENTS_WARNING": "warning - The user has tried placing a block outside of a loop (for each, while, repeat, etc.), but this type of block may only be used within a loop. See [https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks].", + "CONTROLS_IF_HELPURL": "url - Describes conditional statements (if-then-else) in computer programs. Consider using your language's translation of [http://en.wikipedia.org/wiki/If_else http://en.wikipedia.org/wiki/If_else], if present.", + "CONTROLS_IF_TOOLTIP_1": "tooltip - Describes [https://code.google.com/p/blockly/wiki/IfElse#If_blocks 'if' blocks]. Consider using your language's translation of [http://en.wikipedia.org/wiki/If_statement http://en.wikipedia.org/wiki/If_statement], if present.", + "CONTROLS_IF_TOOLTIP_2": "tooltip - Describes [https://code.google.com/p/blockly/wiki/IfElse#If-Else_blocks if-else blocks]. Consider using your language's translation of [http://en.wikipedia.org/wiki/If_statement http://en.wikipedia.org/wiki/If_statement], if present.", + "CONTROLS_IF_TOOLTIP_3": "tooltip - Describes [https://code.google.com/p/blockly/wiki/IfElse#If-Else-If_blocks if-else-if blocks]. Consider using your language's translation of [http://en.wikipedia.org/wiki/If_statement http://en.wikipedia.org/wiki/If_statement], if present.", + "CONTROLS_IF_TOOLTIP_4": "tooltip - Describes [https://code.google.com/p/blockly/wiki/IfElse#If-Else-If-Else_blocks if-else-if-else blocks]. Consider using your language's translation of [http://en.wikipedia.org/wiki/If_statement http://en.wikipedia.org/wiki/If_statement], if present.", + "CONTROLS_IF_MSG_IF": "block text - See [https://code.google.com/p/blockly/wiki/IfElse https://code.google.com/p/blockly/wiki/IfElse]. It is recommended, but not essential, that this have text in common with the translation of 'else if'", + "CONTROLS_IF_MSG_ELSEIF": "block text - See [https://code.google.com/p/blockly/wiki/IfElse https://code.google.com/p/blockly/wiki/IfElse]. The English words 'otherwise if' would probably be clearer than 'else if', but the latter is used because it is traditional and shorter.", + "CONTROLS_IF_MSG_ELSE": "block text - See [https://code.google.com/p/blockly/wiki/IfElse https://code.google.com/p/blockly/wiki/IfElse]. The English word 'otherwise' would probably be superior to 'else', but the latter is used because it is traditional and shorter.", + "CONTROLS_IF_IF_TOOLTIP": "tooltip - Describes [https://code.google.com/p/blockly/wiki/IfElse#Block_Modification if block modification].", + "CONTROLS_IF_ELSEIF_TOOLTIP": "tooltip - Describes the 'else if' subblock during [https://code.google.com/p/blockly/wiki/IfElse#Block_Modification if block modification].", + "CONTROLS_IF_ELSE_TOOLTIP": "tooltip - Describes the 'else' subblock during [https://code.google.com/p/blockly/wiki/IfElse#Block_Modification if block modification].", + "LOGIC_COMPARE_HELPURL": "url - Information about comparisons.", + "LOGIC_COMPARE_TOOLTIP_EQ": "tooltip - Describes the equals (=) block.", + "LOGIC_COMPARE_TOOLTIP_NEQ": "tooltip - Describes the equals (\u0026ne;) block.", + "LOGIC_COMPARE_TOOLTIP_LT": "tooltip - Describes the equals (\u0026lt;) block.", + "LOGIC_COMPARE_TOOLTIP_LTE": "tooltip - Describes the equals (\u0026le;) block.", + "LOGIC_COMPARE_TOOLTIP_GT": "tooltip - Describes the equals (\u0026gt;) block.", + "LOGIC_COMPARE_TOOLTIP_GTE": "tooltip - Describes the equals (\u0026ge;) block.", + "LOGIC_OPERATION_HELPURL": "url - Information about the Boolean conjunction ('and') and disjunction ('or') operators. Consider using the translation of [http://en.wikipedia.org/wiki/Boolean_logic http://en.wikipedia.org/wiki/Boolean_logic], if it exists in your language.", + "LOGIC_OPERATION_TOOLTIP_AND": "tooltip - See [http://en.wikipedia.org/wiki/Logical_conjunction http://en.wikipedia.org/wiki/Logical_conjunction].", + "LOGIC_OPERATION_AND": "block text - See [http://en.wikipedia.org/wiki/Logical_conjunction http://en.wikipedia.org/wiki/Logical_conjunction].", + "LOGIC_OPERATION_TOOLTIP_OR": "block text - See [http://en.wikipedia.org/wiki/Disjunction http://en.wikipedia.org/wiki/Disjunction].", + "LOGIC_OPERATION_OR": "block text - See [http://en.wikipedia.org/wiki/Disjunction http://en.wikipedia.org/wiki/Disjunction].", + "LOGIC_NEGATE_HELPURL": "url - Information about logical negation. The translation of [http://en.wikipedia.org/wiki/Logical_negation http://en.wikipedia.org/wiki/Logical_negation] is recommended if it exists in the target language.", + "LOGIC_NEGATE_TITLE": "block text - This is a unary operator that returns ''false'' when the input is ''true'', and ''true'' when the input is ''false''. \n\nParameters:\n* %1 - the input (which should be either the value 'true' or 'false')", + "LOGIC_NEGATE_TOOLTIP": "tooltip - See [http://en.wikipedia.org/wiki/Logical_negation http://en.wikipedia.org/wiki/Logical_negation].", + "LOGIC_BOOLEAN_HELPURL": "url - Information about the logic values ''true'' and ''false''. Consider using the translation of [http://en.wikipedia.org/wiki/Truth_value http://en.wikipedia.org/wiki/Truth_value] if it exists in your language.", + "LOGIC_BOOLEAN_TRUE": "block text - The word for the [http://en.wikipedia.org/wiki/Truth_value logical value] ''true''.", + "LOGIC_BOOLEAN_FALSE": "block text - The word for the [http://en.wikipedia.org/wiki/Truth_value logical value] ''false''.", + "LOGIC_BOOLEAN_TOOLTIP": "tooltip - Indicates that the block returns either of the two possible [http://en.wikipedia.org/wiki/Truth_value logical values].", + "LOGIC_NULL_HELPURL": "url - Provide a link to the translation of [http://en.wikipedia.org/wiki/Nullable_type http://en.wikipedia.org/wiki/Nullable_type], if it exists in your language; otherwise, do not worry about translating this advanced concept.", + "LOGIC_NULL": "block text - In computer languages, ''null'' is a special value that indicates that no value has been set. You may use your language's word for 'nothing' or 'invalid'.", + "LOGIC_NULL_TOOLTIP": "tooltip - This should use the word from the previous message.", + "LOGIC_TERNARY_HELPURL": "url - Describes the programming language operator known as the ''ternary'' or ''conditional'' operator. It is recommended that you use the translation of [http://en.wikipedia.org/wiki/%3F: http://en.wikipedia.org/wiki/%3F:] if it exists.", + "LOGIC_TERNARY_CONDITION": "block input text - Label for the input whose value determines which of the other two inputs is returned. In some programming languages, this is called a ''''predicate''''.", + "LOGIC_TERNARY_IF_TRUE": "block input text - Indicates that the following input should be returned (used as output) if the test input is true. Remember to try to keep block text terse (short).", + "LOGIC_TERNARY_IF_FALSE": "block input text - Indicates that the following input should be returned (used as output) if the test input is false.", + "LOGIC_TERNARY_TOOLTIP": "tooltip - See [http://en.wikipedia.org/wiki/%3F: http://en.wikipedia.org/wiki/%3F:].", + "MATH_NUMBER_HELPURL": "url - Information about (real) numbers.", + "MATH_NUMBER_TOOLTIP": "tooltip - Any positive or negative number, not necessarily an integer.", + "MATH_ADDITION_SYMBOL": "math - The symbol for the binary operation addition.", + "MATH_SUBTRACTION_SYMBOL": "math - The symbol for the binary operation indicating that the right operand should be subtracted from the left operand.", + "MATH_DIVISION_SYMBOL": "math - The binary operation indicating that the left operand should be divided by the right operand.", + "MATH_MULTIPLICATION_SYMBOL": "math - The symbol for the binary operation multiplication.", + "MATH_POWER_SYMBOL": "math - The symbol for the binary operation exponentiation. Specifically, if the value of the left operand is L and the value of the right operand (the exponent) is R, multiply L by itself R times. (Fractional and negative exponents are also legal.)", + "MATH_TRIG_SIN": "math - The short name of the trigonometric function [http://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent sine].", + "MATH_TRIG_COS": "math - The short name of the trigonometric function [http://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent cosine].", + "MATH_TRIG_TAN": "math - The short name of the trigonometric function [http://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent tangent].", + "MATH_TRIG_ASIN": "math - The short name of the ''inverse of'' the trigonometric function [http://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent sine].", + "MATH_TRIG_ACOS": "math - The short name of the ''inverse of'' the trigonometric function [http://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent cosine].", + "MATH_TRIG_ATAN": "math - The short name of the ''inverse of'' the trigonometric function [http://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent tangent].", + "MATH_ARITHMETIC_HELPURL": "url - Information about addition, subtraction, multiplication, division, and exponentiation.", + "MATH_ARITHMETIC_TOOLTIP_ADD": "tooltip - See [http://en.wikipedia.org/wiki/Addition http://en.wikipedia.org/wiki/Addition].", + "MATH_ARITHMETIC_TOOLTIP_MINUS": "tooltip - See [http://en.wikipedia.org/wiki/Subtraction http://en.wikipedia.org/wiki/Subtraction].", + "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "tooltip - See [http://en.wikipedia.org/wiki/Multiplication http://en.wikipedia.org/wiki/Multiplication].", + "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "tooltip - See [http://en.wikipedia.org/wiki/Division_(mathematics) http://en.wikipedia.org/wiki/Division_(mathematics)].", + "MATH_ARITHMETIC_TOOLTIP_POWER": "tooltip - See [http://en.wikipedia.org/wiki/Exponentiation http://en.wikipedia.org/wiki/Exponentiation].", + "MATH_SINGLE_HELPURL": "url - Information about the square root operation.", + "MATH_SINGLE_OP_ROOT": "dropdown - This computes the positive [http://en.wikipedia.org/wiki/Square_root square root] of its input. For example, the square root of 16 is 4.", + "MATH_SINGLE_TOOLTIP_ROOT": "tooltip - Please use the same term as in the previous message.", + "MATH_SINGLE_OP_ABSOLUTE": "dropdown - This leaves positive numeric inputs changed and inverts negative inputs. For example, the absolute value of 5 is 5; the absolute value of -5 is also 5. For more information, see [http://en.wikipedia.org/wiki/Absolute_value http://en.wikipedia.org/wiki/Absolute_value].", + "MATH_SINGLE_TOOLTIP_ABS": "tooltip - Please use the same term as in the previous message.", + "MATH_SINGLE_TOOLTIP_NEG": "tooltip - Calculates '''0-n''', where '''n''' is the single numeric input.", + "MATH_SINGLE_TOOLTIP_LN": "tooltip - Calculates the [http://en.wikipedia.org/wiki/Natural_logarithm|natural logarithm] of its single numeric input.", + "MATH_SINGLE_TOOLTIP_LOG10": "tooltip - Calculates the [http://en.wikipedia.org/wiki/Common_logarithm common logarithm] of its single numeric input.", + "MATH_SINGLE_TOOLTIP_EXP": "tooltip - Multiplies [http://en.wikipedia.org/wiki/E_%28mathematical_constant%29 e] by itself n times, where n is the single numeric input.", + "MATH_SINGLE_TOOLTIP_POW10": "tooltip - Multiplies 10 by itself n times, where n is the single numeric input.", + "MATH_TRIG_HELPURL": "url - Information about the trigonometric functions sine, cosine, tangent, and their inverses (ideally using degrees, not radians).", + "MATH_TRIG_TOOLTIP_SIN": "tooltip - Return the [http://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent sine] of an [http://en.wikipedia.org/wiki/Degree_(angle) angle in degrees], not radians.", + "MATH_TRIG_TOOLTIP_COS": "tooltip - Return the [http://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent cosine] of an [http://en.wikipedia.org/wiki/Degree_(angle) angle in degrees], not radians.", + "MATH_TRIG_TOOLTIP_TAN": "tooltip - Return the [http://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent tangent] of an [http://en.wikipedia.org/wiki/Degree_(angle) angle in degrees], not radians.", + "MATH_TRIG_TOOLTIP_ASIN": "tooltip - The [http://en.wikipedia.org/wiki/Inverse_trigonometric_functions inverse] of the [http://en.wikipedia.org/wiki/Cosine#Sine.2C_cosine_and_tangent sine function], using [http://en.wikipedia.org/wiki/Degree_(angle) degrees], not radians.", + "MATH_TRIG_TOOLTIP_ACOS": "tooltip - The [http://en.wikipedia.org/wiki/Inverse_trigonometric_functions inverse] of the [http://en.wikipedia.org/wiki/Cosine#Sine.2C_cosine_and_tangent cosine] function, using [http://en.wikipedia.org/wiki/Degree_(angle) degrees], not radians.", + "MATH_TRIG_TOOLTIP_ATAN": "tooltip - The [http://en.wikipedia.org/wiki/Inverse_trigonometric_functions inverse] of the [http://en.wikipedia.org/wiki/Cosine#Sine.2C_cosine_and_tangent tangent] function, using [http://en.wikipedia.org/wiki/Degree_(angle) degrees], not radians.", + "MATH_CONSTANT_HELPURL": "url - Information about the mathematical constants \u0026pi;, e, the golden ratio (\u0026phi;), \u0026radic; 2, \u0026radic; 1/2, and infinity (\u0026infin;).", + "MATH_CONSTANT_TOOLTIP": "tooltip - Provides the specified [http://en.wikipedia.org/wiki/Mathematical_constant mathematical constant].", + "MATH_IS_EVEN": "dropdown - A number is '''even''' if it is a multiple of 2. For example, 4 is even (yielding true), but 3 is not (false).", + "MATH_IS_ODD": "dropdown - A number is '''odd''' if it is not a multiple of 2. For example, 3 is odd (yielding true), but 4 is not (false). The opposite of 'odd' is 'even'.", + "MATH_IS_PRIME": "dropdown - A number is [http://en.wikipedia.org/wiki/Prime prime] if it cannot be evenly divided by any positive integers except for 1 and itself. For example, 5 is prime, but 6 is not because 2 \u0026times; 3 = 6.", + "MATH_IS_WHOLE": "dropdown - A number is '''whole''' if it is an [http://en.wikipedia.org/wiki/Integer integer]. For example, 5 is whole, but 5.1 is not.", + "MATH_IS_POSITIVE": "dropdown - A number is '''positive''' if it is greater than 0. (0 is neither negative nor positive.)", + "MATH_IS_NEGATIVE": "dropdown - A number is '''negative''' if it is less than 0. (0 is neither negative nor positive.)", + "MATH_IS_DIVISIBLE_BY": "dropdown - A number x is divisible by y if y goes into x evenly. For example, 10 is divisible by 5, but 10 is not divisible by 3.", + "MATH_IS_TOOLTIP": "tooltip - This block lets the user specify via a dropdown menu whether to check if the numeric input is even, odd, prime, whole, positive, negative, or divisible by a given value.", + "MATH_CHANGE_HELPURL": "url - Information about incrementing (increasing the value of) a variable.", + "MATH_CHANGE_TITLE_CHANGE": "- As in: '''change''' [the value of variable] ''item by'' 1 (e.g., if the variable named 'item' had the value 5, change it to 6).", + "MATH_CHANGE_INPUT_BY": "- As in: ''change'' [the value of variable] ''item'' '''by''' 1 (e.g., if the variable named 'item' had the value 5, change it to 6).", + "MATH_CHANGE_TOOLTIP": "tooltip - This updates the value of the variable by adding to it the following numeric input.\n\nParameters:\n* %1 - the name of the variable whose value should be increased.", + "MATH_ROUND_HELPURL": "url - Information about how numbers are rounded to the nearest integer", + "MATH_ROUND_TOOLTIP": "tooltip - See [http://en.wikipedia.org/wiki/Rounding http://en.wikipedia.org/wiki/Rounding].", + "MATH_ROUND_OPERATOR_ROUND": "dropdown - This rounds its input to the nearest whole number. For example, 3.4 is rounded to 3.", + "MATH_ROUND_OPERATOR_ROUNDUP": "dropdown - This rounds its input up to the nearest whole number. For example, if the input was 2.2, the result would be 3.", + "MATH_ROUND_OPERATOR_ROUNDDOWN": "dropdown - This rounds its input down to the nearest whole number. For example, if the input was 3.8, the result would be 3.", + "MATH_ONLIST_HELPURL": "url - Information about applying a function to a list of numbers. (We were unable to find such information in English. Feel free to skip this and any other URLs that are difficult.)", + "MATH_ONLIST_OPERATOR_SUM": "dropdown - This computes the sum of the numeric elements in the list. For example, the sum of the list {1, 4} is 5.", + "MATH_ONLIST_TOOLTIP_SUM": "tooltip - Please use the same term for 'sum' as in the previous message.", + "MATH_ONLIST_OPERATOR_MIN": "dropdown - This finds the smallest (minimum) number in a list. For example, the smallest number in the list [-5, 0, 3] is -5.", + "MATH_ONLIST_TOOLTIP_MIN": "tooltip - Please use the same term for 'min' or 'minimum' as in the previous message.", + "MATH_ONLIST_OPERATOR_MAX": "dropdown - This finds the largest (maximum) number in a list. For example, the largest number in the list [-5, 0, 3] is 3.", + "MATH_ONLIST_TOOLTIP_MAX": "tooltip", + "MATH_ONLIST_OPERATOR_AVERAGE": "dropdown - This adds up all of the numbers in a list and divides the sum by the number of elements in the list. For example, the [http://en.wikipedia.org/wiki/Arithmetic_mean average] of the list [1, 2, 3, 4] is 2.5 (10/4).", + "MATH_ONLIST_TOOLTIP_AVERAGE": "tooltip - See [http://en.wikipedia.org/wiki/Arithmetic_mean http://en.wikipedia.org/wiki/Arithmetic_mean] for more informatin.", + "MATH_ONLIST_OPERATOR_MEDIAN": "dropdown - This finds the [http://en.wikipedia.org/wiki/Median median] of the numeric values in a list. For example, the median of the list {1, 2, 7, 12, 13} is 7.", + "MATH_ONLIST_TOOLTIP_MEDIAN": "tooltip - See [http://en.wikipedia.org/wiki/Median median http://en.wikipedia.org/wiki/Median median] for more information.", + "MATH_ONLIST_OPERATOR_MODE": "dropdown - This finds the most common numbers ([http://en.wikipedia.org/wiki/Mode_(statistics) modes]) in a list. For example, the modes of the list {1, 3, 9, 3, 9} are {3, 9}.", + "MATH_ONLIST_TOOLTIP_MODE": "tooltip - See [http://en.wikipedia.org/wiki/Mode_(statistics) http://en.wikipedia.org/wiki/Mode_(statistics)] for more information.", + "MATH_ONLIST_OPERATOR_STD_DEV": "dropdown - This finds the [http://en.wikipedia.org/wiki/Standard_deviation standard deviation] of the numeric values in a list.", + "MATH_ONLIST_TOOLTIP_STD_DEV": "tooltip - See [http://en.wikipedia.org/wiki/Standard_deviation http://en.wikipedia.org/wiki/Standard_deviation] for more information.", + "MATH_ONLIST_OPERATOR_RANDOM": "dropdown - This choose an element at random from a list. Each element is chosen with equal probability.", + "MATH_ONLIST_TOOLTIP_RANDOM": "tooltip - Please use same term for 'random' as in previous entry.", + "MATH_MODULO_HELPURL": "url - information about the modulo (remainder) operation.", + "MATH_MODULO_TITLE": "block text - Title of block providing the remainder when dividing the first numerical input by the second. For example, the remainder of 10 divided by 3 is 1.\n\nParameters:\n* %1 - the dividend (10, in our example)\n* %2 - the divisor (3 in our example).", + "MATH_MODULO_TOOLTIP": "tooltip - For example, the remainder of 10 divided by 3 is 1.", + "MATH_CONSTRAIN_HELPURL": "url - Information about constraining a numeric value to be in a specific range. (The English URL is not ideal. Recall that translating URLs is the lowest priority.)", + "MATH_CONSTRAIN_TITLE": "block text - The title of the block that '''constrain'''s (forces) a number to be in a given range. For example, if the number 150 is constrained to be between 5 and 100, the result will be 100. \n\nParameters:\n* %1 - the value to constrain (e.g., 150)\n* %2 - the minimum value (e.g., 5)\n* %3 - the maximum value (e.g., 100).", + "MATH_CONSTRAIN_TOOLTIP": "tooltip - This compares a number ''x'' to a low value ''L'' and a high value ''H''. If ''x'' is less then ''L'', the result is ''L''. If ''x'' is greater than ''H'', the result is ''H''. Otherwise, the result is ''x''.", + "MATH_RANDOM_INT_HELPURL": "url - Information about how computers generate random numbers.", + "MATH_RANDOM_INT_TITLE": "block text - The title of the block that generates a random integer (whole number) in the specified range. For example, if the range is from 5 to 7, this returns 5, 6, or 7 with equal likelihood. %1 is a placeholder for the lower number, %2 is the placeholder for the larger number.", + "MATH_RANDOM_INT_TOOLTIP": "tooltip - Return a random integer between two values specified as inputs. For example, if one input was 7 and another 9, any of the numbers 7, 8, or 9 could be produced.", + "MATH_RANDOM_FLOAT_HELPURL": "url - Information about how computers generate random numbers (specifically, numbers in the range from 0 to just below 1).", + "MATH_RANDOM_FLOAT_TITLE_RANDOM": "block text - The title of the block that generates a random number greater than or equal to 0 and less than 1.", + "MATH_RANDOM_FLOAT_TOOLTIP": "tooltip - Return a random fraction between 0 and 1. The value may be equal to 0 but must be less than 1.", + "TEXT_TEXT_HELPURL": "url - Information about how computers represent text (sometimes referred to as ''string''s).", + "TEXT_TEXT_TOOLTIP": "tooltip - See [https://code.google.com/p/blockly/wiki/Text#Introduction https://code.google.com/p/blockly/wiki/Text#Introduction].", + "TEXT_JOIN_HELPURL": "url - Information on concatenating/appending pieces of text.", + "TEXT_JOIN_TITLE_CREATEWITH": "block text - See [https://code.google.com/p/blockly/wiki/Text#Text_creation https://code.google.com/p/blockly/wiki/Text#Text_creation].", + "TEXT_JOIN_TOOLTIP": "tooltip - See [https://code.google.com/p/blockly/wiki/Text#Text_creation create text with] for more information.", + "TEXT_CREATE_JOIN_TITLE_JOIN": "block text - This is shown when the programmer wants to change the number of pieces of text being joined together. See [https://code.google.com/p/blockly/wiki/Text#Text_creation https://code.google.com/p/blockly/wiki/Text#Text_creation], specifically the last picture in the 'Text creation' section.", + "TEXT_CREATE_JOIN_TOOLTIP": "tooltip - See [https://code.google.com/p/blockly/wiki/Text#Text_creation https://code.google.com/p/blockly/wiki/Text#Text_creation], specifically the last picture in the 'Text creation' section.", + "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "block text - See [https://code.google.com/p/blockly/wiki/Text#Text_creation https://code.google.com/p/blockly/wiki/Text#Text_creation], specifically the last picture in the 'Text creation' section.", + "TEXT_APPEND_HELPURL": "url - This and the other text-related URLs are going to be hard to translate. As always, it is okay to leave untranslated or paste in the English-language URL. For these URLs, you might also consider a general URL about how computers represent text (such as the translation of [http://en.wikipedia.org/wiki/String_(computer_science) this Wikipedia page]).", + "TEXT_APPEND_TO": "block input text - Message preceding the name of a variable to which text should be appended. [[File:blockly-append-text.png]]", + "TEXT_APPEND_APPENDTEXT": "block input text - Message following the variable and preceding the piece of text that should be appended, as shown below. [[File:blockly-append-text.png]]", + "TEXT_APPEND_TOOLTIP": "tooltip - See [https://code.google.com/p/blockly/wiki/Text#Text_modification https://code.google.com/p/blockly/wiki/Text#Text_modification] for more information.\n\nParameters:\n* %1 - the name of the variable to which text should be appended", + "TEXT_LENGTH_HELPURL": "url - Information about text on computers (usually referred to as 'strings').", + "TEXT_LENGTH_TITLE": "block text - See [https://code.google.com/p/blockly/wiki/Text#Text_length https://code.google.com/p/blockly/wiki/Text#Text_length]. \n\nParameters:\n* %1 - the piece of text to take the length of", + "TEXT_LENGTH_TOOLTIP": "tooltip - See [https://code.google.com/p/blockly/wiki/Text#Text_length https://code.google.com/p/blockly/wiki/Text#Text_length].", + "TEXT_ISEMPTY_HELPURL": "url - Information about empty pieces of text on computers (usually referred to as 'empty strings').", + "TEXT_ISEMPTY_TITLE": "block text - See [https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text]. \n\nParameters:\n* %1 - the piece of text to test for emptiness", + "TEXT_ISEMPTY_TOOLTIP": "tooltip - See [https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text].", + "TEXT_INDEXOF_HELPURL": "url - Information about finding a character in a piece of text.", + "TEXT_INDEXOF_TOOLTIP": "tooltip - See [https://code.google.com/p/blockly/wiki/Text#Finding_text https://code.google.com/p/blockly/wiki/Text#Finding_text].", + "TEXT_INDEXOF_INPUT_INTEXT": "block text - Title of blocks allowing users to find text. See [https://code.google.com/p/blockly/wiki/Text#Finding_text https://code.google.com/p/blockly/wiki/Text#Finding_text]. [[File:Blockly-find-text.png]].", + "TEXT_INDEXOF_OPERATOR_FIRST": "dropdown - See [https://code.google.com/p/blockly/wiki/Text#Finding_text https://code.google.com/p/blockly/wiki/Text#Finding_text]. [[File:Blockly-find-text.png]].", + "TEXT_INDEXOF_OPERATOR_LAST": "dropdown - See [https://code.google.com/p/blockly/wiki/Text#Finding_text https://code.google.com/p/blockly/wiki/Text#Finding_text]. This would replace 'find first occurrence of text' below. (For more information on how common text is factored out of dropdown menus, see [http://translatewiki.net/wiki/Translating:Blockly#Drop-Down_Menus http://translatewiki.net/wiki/Translating:Blockly#Drop-Down_Menus)].) [[File:Blockly-find-text.png]].", + "TEXT_INDEXOF_TAIL": "block text - Optional text to follow the rightmost block in a [https://code.google.com/p/blockly/wiki/Text#Finding_text https://code.google.com/p/blockly/wiki/Text#Finding_text in text ... find block] (after the 'a' in the below picture). This will be the empty string in most languages. [[File:Blockly-find-text.png]].", + "TEXT_CHARAT_HELPURL": "url - Information about extracting characters (letters, number, symbols, etc.) from text.", + "TEXT_CHARAT_INPUT_INTEXT": "block text - Appears before the piece of text from which a letter (or number, punctuation character, etc.) should be extracted, as shown below. See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character]. [[File:Blockly-text-get.png]]", + "TEXT_CHARAT_FROM_START": "dropdown - Indicates that the letter (or number, punctuation character, etc.) with the specified index should be obtained from the preceding piece of text. See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character]. [[File:Blockly-text-get.png]]", + "TEXT_CHARAT_FROM_END": "block text - Indicates that the letter (or number, punctuation character, etc.) with the specified index from the end of a given piece of text should be obtained. See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character]. [[File:Blockly-text-get.png]]", + "TEXT_CHARAT_FIRST": "block text - Indicates that the first letter of the following piece of text should be retrieved. See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character]. [[File:Blockly-text-get.png]]", + "TEXT_CHARAT_LAST": "block text - Indicates that the last letter (or number, punctuation mark, etc.) of the following piece of text should be retrieved. See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character]. [[File:Blockly-text-get.png]]", + "TEXT_CHARAT_RANDOM": "block text - Indicates that any letter (or number, punctuation mark, etc.) in the following piece of text should be randomly selected. See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character]. [[File:Blockly-text-get.png]]", + "TEXT_CHARAT_TAIL": "block text - Text that goes after the rightmost block/dropdown when getting a single letter from a piece of text, as in [http://blockly-demo.appspot.com/static/apps/code/index.html#3m23km these blocks] or shown below. For most languages, this will be blank. [[File:Blockly-text-get.png]]", + "TEXT_CHARAT_TOOLTIP": "tooltip - See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character]. [[File:Blockly-text-get.png]]", + "TEXT_GET_SUBSTRING_TOOLTIP": "See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text].", + "TEXT_GET_SUBSTRING_HELPURL": "url - Information about extracting characters from text. Reminder: urls are the lowest priority translations. Feel free to skip.", + "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "block text - Precedes a piece of text from which a portion should be extracted. [[File:Blockly-get-substring.png]]", + "TEXT_GET_SUBSTRING_START_FROM_START": "dropdown - Indicates that the following number specifies the position (relative to the start position) of the beginning of the region of text that should be obtained from the preceding piece of text. See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text]. [[File:Blockly-get-substring.png]]", + "TEXT_GET_SUBSTRING_START_FROM_END": "dropdown - Indicates that the following number specifies the position (relative to the end position) of the beginning of the region of text that should be obtained from the preceding piece of text. See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text]. Note: If {{msg-Blockly|ORDINAL_NUMBER_SUFFIX}} is defined, it will automatically appear ''after'' this and any other [http://translatewiki.net/wiki/Translating:Blockly#Ordinal_numbers ordinal numbers] on this block. [[File:Blockly-get-substring.png]]", + "TEXT_GET_SUBSTRING_START_FIRST": "block text - Indicates that a region starting with the first letter of the preceding piece of text should be extracted. See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text]. [[File:Blockly-get-substring.png]]", + "TEXT_GET_SUBSTRING_END_FROM_START": "dropdown - Indicates that the following number specifies the position (relative to the start position) of the end of the region of text that should be obtained from the preceding piece of text. See [ https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text]. [[File:Blockly-get-substring.png]]", + "TEXT_GET_SUBSTRING_END_FROM_END": "dropdown - Indicates that the following number specifies the position (relative to the end position) of the end of the region of text that should be obtained from the preceding piece of text. See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text]. [[File:Blockly-get-substring.png]]", + "TEXT_GET_SUBSTRING_END_LAST": "block text - Indicates that a region ending with the last letter of the preceding piece of text should be extracted. See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text]. [[File:Blockly-get-substring.png]]", + "TEXT_GET_SUBSTRING_TAIL": "block text - Text that should go after the rightmost block/dropdown when [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text extracting a region of text]. In most languages, this will be the empty string. [[File:Blockly-get-substring.png]]", + "TEXT_CHANGECASE_HELPURL": "url - Information about the case of letters (upper-case and lower-case).", + "TEXT_CHANGECASE_TOOLTIP": "tooltip - Describes a block to adjust the case of letters. For more information on this block, see [https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case].", + "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "block text - Indicates that all of the letters in the following piece of text should be capitalized. If your language does not use case, you may indicate that this is not applicable to your language. For more information on this block, see [https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case].", + "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "block text - Indicates that all of the letters in the following piece of text should be converted to lower-case. If your language does not use case, you may indicate that this is not applicable to your language. For more information on this block, see [https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case].", + "TEXT_CHANGECASE_OPERATOR_TITLECASE": "block text - Indicates that the first letter of each of the following words should be capitalized and the rest converted to lower-case. If your language does not use case, you may indicate that this is not applicable to your language. For more information on this block, see [https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case].", + "TEXT_TRIM_HELPURL": "url - Information about trimming (removing) text off the beginning and ends of pieces of text.", + "TEXT_TRIM_TOOLTIP": "tooltip - See [https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces].", + "TEXT_TRIM_OPERATOR_BOTH": "dropdown - Removes spaces from the beginning and end of a piece of text. See [https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces]. Note that neither this nor the other options modify the original piece of text (that appears to the right); the block just returns a version of the text without the specified spaces.", + "TEXT_TRIM_OPERATOR_LEFT": "dropdown - Removes spaces from the beginning of a piece of text. See [https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces]. Note that in right-to-left scripts, this will remove spaces from the right side.", + "TEXT_TRIM_OPERATOR_RIGHT": "dropdown - Removes spaces from the end of a piece of text. See [https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces]. Note that in right-to-left scripts, this will remove spaces from the left side.", + "TEXT_PRINT_HELPURL": "url - Information about displaying text on computers.", + "TEXT_PRINT_TITLE": "block text - Display the input on the screen. See [https://code.google.com/p/blockly/wiki/Text#Printing_text https://code.google.com/p/blockly/wiki/Text#Printing_text]. \n\nParameters:\n* %1 - the value to print", + "TEXT_PRINT_TOOLTIP": "tooltip - See [https://code.google.com/p/blockly/wiki/Text#Printing_text https://code.google.com/p/blockly/wiki/Text#Printing_text].", + "TEXT_PROMPT_HELPURL": "url - Information about getting text from users.", + "TEXT_PROMPT_TYPE_TEXT": "dropdown - Specifies that a piece of text should be requested from the user with the following message. See [https://code.google.com/p/blockly/wiki/Text#Printing_text https://code.google.com/p/blockly/wiki/Text#Printing_text].", + "TEXT_PROMPT_TYPE_NUMBER": "dropdown - Specifies that a number should be requested from the user with the following message. See [https://code.google.com/p/blockly/wiki/Text#Printing_text https://code.google.com/p/blockly/wiki/Text#Printing_text].", + "TEXT_PROMPT_TOOLTIP_NUMBER": "dropdown - Precedes the message with which the user should be prompted for a number. See [https://code.google.com/p/blockly/wiki/Text#Printing_text https://code.google.com/p/blockly/wiki/Text#Printing_text].", + "TEXT_PROMPT_TOOLTIP_TEXT": "dropdown - Precedes the message with which the user should be prompted for some text. See [https://code.google.com/p/blockly/wiki/Text#Printing_text https://code.google.com/p/blockly/wiki/Text#Printing_text].", + "LISTS_CREATE_EMPTY_HELPURL": "url - Information on empty lists.", + "LISTS_CREATE_EMPTY_TITLE": "block text - See [https://code.google.com/p/blockly/wiki/Lists#create_empty_list https://code.google.com/p/blockly/wiki/Lists#create_empty_list].", + "LISTS_CREATE_EMPTY_TOOLTIP": "block text - See [https://code.google.com/p/blockly/wiki/Lists#create_empty_list https://code.google.com/p/blockly/wiki/Lists#create_empty_list].", + "LISTS_CREATE_WITH_TOOLTIP": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#create_list_with https://code.google.com/p/blockly/wiki/Lists#create_list_with].", + "LISTS_CREATE_WITH_INPUT_WITH": "block text - See [https://code.google.com/p/blockly/wiki/Lists#create_list_with https://code.google.com/p/blockly/wiki/Lists#create_list_with].", + "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "block text - This appears in a sub-block when [https://code.google.com/p/blockly/wiki/Lists#changing_number_of_inputs changing the number of inputs in a ''''create list with'''' block].", + "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#changing_number_of_inputs https://code.google.com/p/blockly/wiki/Lists#changing_number_of_inputs].", + "LISTS_CREATE_WITH_ITEM_TOOLTIP": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#changing_number_of_inputs https://code.google.com/p/blockly/wiki/Lists#changing_number_of_inputs].", + "LISTS_REPEAT_HELPURL": "url - Information about [https://code.google.com/p/blockly/wiki/Lists#create_list_with creating a list with multiple copies of a single item].", + "LISTS_REPEAT_TOOLTIP": "url - See [https://code.google.com/p/blockly/wiki/Lists#create_list_with creating a list with multiple copies of a single item].", + "LISTS_REPEAT_TITLE": "block text - See [https://code.google.com/p/blockly/wiki/Lists#create_list_with https://code.google.com/p/blockly/wiki/Lists#create_list_with]. \n\nParameters:\n* %1 - the item (text) to be repeated\n* %2 - the number of times to repeat it", + "LISTS_LENGTH_HELPURL": "url - Information about how the length of a list is computed (i.e., by the total number of elements, not the number of different elements).", + "LISTS_LENGTH_TITLE": "block text - See [https://code.google.com/p/blockly/wiki/Lists#length_of https://code.google.com/p/blockly/wiki/Lists#length_of]. \n\nParameters:\n* %1 - the list whose length is desired", + "LISTS_LENGTH_TOOLTIP": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#length_of https://code.google.com/p/blockly/wiki/Lists#length_of Blockly:Lists:length of].", + "LISTS_IS_EMPTY_HELPURL": "url - See [https://code.google.com/p/blockly/wiki/Lists#is_empty https://code.google.com/p/blockly/wiki/Lists#is_empty].", + "LISTS_IS_EMPTY_TITLE": "block text - See [https://code.google.com/p/blockly/wiki/Lists#is_empty https://code.google.com/p/blockly/wiki/Lists#is_empty]. \n\nParameters:\n* %1 - the list to test", + "LISTS_TOOLTIP": "block tooltip - See [https://code.google.com/p/blockly/wiki/Lists#is_empty https://code.google.com/p/blockly/wiki/Lists#is_empty].", + "LISTS_INLIST": "block text - Title of blocks operating on [https://code.google.com/p/blockly/wiki/Lists lists].", + "LISTS_INDEX_OF_HELPURL": "url - See [https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List].", + "LISTS_INDEX_OF_FIRST": "dropdown - See [https://code.google.com/p/blockly/wiki/Lists#Finding_Items_in_a_List Lists#Finding_Items_in_a_List]. [[File:Blockly-list-find.png]]", + "LISTS_INDEX_OF_LAST": "dropdown - See [https://code.google.com/p/blockly/wiki/Lists#Finding_Items_in_a_List https://code.google.com/p/blockly/wiki/Lists#Finding_Items_in_a_List]. [[File:Blockly-list-find.png]]", + "LISTS_INDEX_OF_TOOLTIP": "dropdown - See [https://code.google.com/p/blockly/wiki/Lists#Finding_Items_in_a_List https://code.google.com/p/blockly/wiki/Lists#Finding_Items_in_a_List]. [[File:Blockly-list-find.png]]", + "LISTS_GET_INDEX_GET": "dropdown - Indicates that the user wishes to [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item get an item from a list] without removing it from the list.", + "LISTS_GET_INDEX_GET_REMOVE": "dropdown - Indicates that the user wishes to [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item get and remove an item from a list], as opposed to merely getting it without modifying the list.", + "LISTS_GET_INDEX_REMOVE": "dropdown - Indicates that the user wishes to [https://code.google.com/p/blockly/wiki/Lists#Removing_an_item remove an item from a list].", + "LISTS_GET_INDEX_FROM_START": "dropdown - Indicates that an index relative to the front of the list should be used to [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item get and/or remove an item from a list]. Note: If {{msg-Blockly|ORDINAL_NUMBER_SUFFIX}} is defined, it will automatically appear ''after'' this number (and any other ordinal numbers on this block). See [[Translating:Blockly#Ordinal_numbers]] for more information on ordinal numbers in Blockly. [[File:Blockly-list-get-item.png]]", + "LISTS_GET_INDEX_FROM_END": "dropdown - Indicates that an index relative to the end of the list should be used to [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item access an item in a list]. [[File:Blockly-list-get-item.png]]", + "LISTS_GET_INDEX_FIRST": "dropdown - Indicates that the '''first''' item should be [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item accessed in a list]. [[File:Blockly-list-get-item.png]]", + "LISTS_GET_INDEX_LAST": "dropdown - Indicates that the '''last''' item should be [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item accessed in a list]. [[File:Blockly-list-get-item.png]]", + "LISTS_GET_INDEX_RANDOM": "dropdown - Indicates that a '''random''' item should be [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item accessed in a list]. [[File:Blockly-list-get-item.png]]", + "LISTS_GET_INDEX_TAIL": "block text - Text that should go after the rightmost block/dropdown when [http://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item accessing an item from a list]. In most languages, this will be the empty string. [[File:Blockly-list-get-item.png]]", + "LISTS_GET_INDEX_TOOLTIP_GET_FROM_START": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for more information.", + "LISTS_GET_INDEX_TOOLTIP_GET_FROM_END": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for more information.", + "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for more information.", + "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for more information.", + "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for more information.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for '# from start'.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for '# from end'.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'first'.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'last'.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'random'.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for '# from start'.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for '# from end'.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'first'.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'last'.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'random'.", + "LISTS_SET_INDEX_HELPURL": "url - Information about putting items in lists.", + "LISTS_SET_INDEX_SET": "block text - [https://code.google.com/p/blockly/wiki/Lists#in_list_..._set Replaces an item in a list]. [[File:Blockly-in-list-set-insert.png]]", + "LISTS_SET_INDEX_INSERT": "block text - [https://code.google.com/p/blockly/wiki/Lists#in_list_..._insert_at Inserts an item into a list]. [[File:Blockly-in-list-set-insert.png]]", + "LISTS_SET_INDEX_INPUT_TO": "block text - The word(s) after the position in the list and before the item to be set/inserted. [[File:Blockly-in-list-set-insert.png]]", + "LISTS_SET_INDEX_TOOLTIP_SET_FROM_START": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the 'get' block, the idea is the same for the 'set' block).", + "LISTS_SET_INDEX_TOOLTIP_SET_FROM_END": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the 'get' block, the idea is the same for the 'set' block).", + "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the 'get' block, the idea is the same for the 'set' block).", + "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the 'get' block, the idea is the same for the 'set' block).", + "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the 'get' block, the idea is the same for the 'set' block).", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the 'get' block, the idea is the same for the 'insert' block).", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the 'get' block, the idea is the same for the 'insert' block).", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the 'get' block, the idea is the same for the 'insert' block).", + "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the 'get' block, the idea is the same for the 'insert' block).", + "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the 'get' block, the idea is the same for the 'insert' block).", + "LISTS_GET_SUBLIST_HELPURL": "url - Information describing extracting a sublist from an existing list.", + "LISTS_GET_SUBLIST_START_FROM_START": "dropdown - Indicates that an index relative to the front of the list should be used to specify the beginning of the range from which to [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist get a sublist]. [[File:Blockly-get-sublist.png]] Note: If {{msg-Blockly|ORDINAL_NUMBER_SUFFIX}} is defined, it will automatically appear ''after'' this number (and any other ordinal numbers on this block). See [[Translating:Blockly#Ordinal_numbers]] for more information on ordinal numbers in Blockly.", + "LISTS_GET_SUBLIST_START_FROM_END": "dropdown - Indicates that an index relative to the end of the list should be used to specify the beginning of the range from which to [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist get a sublist].", + "LISTS_GET_SUBLIST_START_FIRST": "dropdown - Indicates that the [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist sublist to extract] should begin with the list's first item.", + "LISTS_GET_SUBLIST_END_FROM_START": "dropdown - Indicates that an index relative to the front of the list should be used to specify the end of the range from which to [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist get a sublist]. [[File:Blockly-get-sublist.png]]", + "LISTS_GET_SUBLIST_END_FROM_END": "dropdown - Indicates that an index relative to the end of the list should be used to specify the end of the range from which to [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist get a sublist]. [[File:Blockly-get-sublist.png]]", + "LISTS_GET_SUBLIST_END_LAST": "dropdown - Indicates that the '''last''' item in the given list should be [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist the end of the selected sublist]. [[File:Blockly-get-sublist.png]]", + "LISTS_GET_SUBLIST_TAIL": "block text - This appears in the rightmost position ('tail') of the sublist block, as described at [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist]. In English and most other languages, this is the empty string. [[File:Blockly-get-sublist.png]]", + "LISTS_GET_SUBLIST_TOOLTIP": "tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist] for more information. [[File:Blockly-get-sublist.png]]", + "ORDINAL_NUMBER_SUFFIX": "grammar - Text that follows an ordinal number (a number that indicates position relative to other numbers). In most languages, such text appears before the number, so this should be blank. An exception is Hungarian. See [[Translating:Blockly#Ordinal_numbers]] for more information.", + "VARIABLES_GET_HELPURL": "url - Information about ''variables'' in computer programming. Consider using your language's translation of [http://en.wikipedia.org/wiki/Variable_(computer_science) http://en.wikipedia.org/wiki/Variable_(computer_science)], if it exists.", + "VARIABLES_GET_TITLE": "block text - This precedes the name of a variable when getting its values. In most (all?) languages, it should be the empty string. If unsure, ask yourself if any word should go before 'x' in the expression 'x + 1'.", + "VARIABLES_GET_TAIL": "block text - This follows the name of a variable. In most (all?) languages, it should be the empty string. If unsure, ask yourself if any word should go after 'x' in the expression 'x + 1'.", + "VARIABLES_GET_TOOLTIP": "tooltip - This gets the value of the named variable without modifying it.", + "VARIABLES_GET_CREATE_SET": "context menu - Selecting this creates a block to set (change) the value of this variable. \n\nParameters:\n* %1 - the name of the variable.", + "VARIABLES_SET_HELPURL": "url - Information about ''variables'' in computer programming. Consider using your language's translation of [http://en.wikipedia.org/wiki/Variable_(computer_science) http://en.wikipedia.org/wiki/Variable_(computer_science)], if it exists.", + "VARIABLES_SET_TITLE": "block text - The imperative or infinitive form of the verb 'set', as in: '''set''' [the value of] x to 7.", + "VARIABLES_SET_TAIL": "block text - The word that goes after the name of the variable and before its new value in: set [the value of] x '''to''' 7.", + "VARIABLES_SET_TOOLTIP": "tooltip - This initializes or changes the value of the named variable.", + "VARIABLES_SET_CREATE_GET": "context menu - Selecting this creates a block to get (change) the value of this variable.\n\nParameters:\n* %1 - the name of the variable.", + "PROCEDURES_DEFNORETURN_HELPURL": "url - Information about defining [http://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that do not have return values.", + "PROCEDURES_DEFNORETURN_TITLE": "block text - This precedes the name of the procedure when defining it. See [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#c84aoc this sample procedure definition].", + "PROCEDURES_DEFNORETURN_PROCEDURE": "default name - This acts as a placeholder for the name of a function on a function definition block, as shown on [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#w7cfju this block]. The user will replace it with the function's name.", + "PROCEDURES_BEFORE_PARAMS": "block text - This precedes the list of parameters to a function. See [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#6ot5y5 this sample function with parameters].", + "PROCEDURES_DEFNORETURN_DO": "block text - This appears next to the function's 'body', the blocks that should be run when the function is called, as shown in [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#c84aoc this sample procedure definition].", + "PROCEDURES_DEFNORETURN_TOOLTIP": "tooltip", + "PROCEDURES_DEFRETURN_HELPURL": "url - Information about defining [http://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that have return values.", + "PROCEDURES_DEFRETURN_RETURN": "block text - This imperative or infinite verb precedes the value that is used as the return value (output) of this function. See [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#6ot5y5 this sample function that returns a value].", + "PROCEDURES_DEFRETURN_TOOLTIP": "tooltip", + "PROCEDURES_DEF_DUPLICATE_WARNING": "alert - The user has created a function with two parameters that have the same name. Every parameter must have a different name.", + "PROCEDURES_CALLNORETURN_HELPURL": "url - Information about calling [http://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that do not return values.", + "PROCEDURES_CALLNORETURN_CALL": "block text - In most (if not all) languages, this will be the empty string. It precedes the name of the function that should be run. See, for example, the 'draw square' block in [https://blockly-demo.appspot.com/static/apps/turtle/index.html#ztz96g].", + "PROCEDURES_CALLNORETURN_TOOLTIP": "tooltip - This block causes the body (blocks inside) of the named function definition to be run.", + "PROCEDURES_CALLRETURN_HELPURL": "url - Information about calling [http://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that return values.", + "PROCEDURES_CALLRETURN_TOOLTIP": "tooltip - This block causes the body (blocks inside) of the named function definition to be run.\n\nParameters:\n* %1 - the name of the function.", + "PROCEDURES_MUTATORCONTAINER_TITLE": "block text - This text appears on a block in a window that appears when the user clicks on the plus sign or star on a function definition block. It refers to the set of parameters (referred to by the simpler term 'inputs') to the function. See [[Translating:Blockly#function_definitions]].", + "PROCEDURES_MUTATORARG_TITLE": "block text - This text appears on a block in a window that appears when the user clicks on the plus sign or star on a function definition block]. It appears on the block for adding an individual parameter (referred to by the simpler term 'inputs') to the function. See [[Translating:Blockly#function_definitions]].", + "PROCEDURES_HIGHLIGHT_DEF": "context menu - This appears on the context menu for function calls. Selecting it causes the corresponding function definition to be highlighted (as shown at [[Translating:Blockly#context_menus]].", + "PROCEDURES_CREATE_DO": "context menu - This appears on the context menu for function definitions. Selecting it creates a block to call the function. \n\nParameters:\n* %1 - the name of the function.", + "PROCEDURES_IFRETURN_TOOLTIP": "tooltip - If the first value is true, this causes the second value to be returned immediately from the enclosing function.", + "PROCEDURES_IFRETURN_WARNING": "warning - This appears if the user tries to use this block outside of a function definition." +} \ No newline at end of file diff --git a/msg/json/ru.json b/msg/json/ru.json new file mode 100644 index 000000000..a957b9c17 --- /dev/null +++ b/msg/json/ru.json @@ -0,0 +1,296 @@ +{ + "@metadata": { + "authors": [ + "MS", + "Okras" + ] + }, + "VARIABLES_DEFAULT_NAME": "\u044d\u043b\u0435\u043c\u0435\u043d\u0442", + "DUPLICATE_BLOCK": "\u0421\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c", + "ADD_COMMENT": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439", + "REMOVE_COMMENT": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439", + "EXTERNAL_INPUTS": "\u0412\u0441\u0442\u0430\u0432\u043a\u0438 \u0441\u043d\u0430\u0440\u0443\u0436\u0438", + "INLINE_INPUTS": "\u0412\u0441\u0442\u0430\u0432\u043a\u0438 \u0432\u043d\u0443\u0442\u0440\u0438", + "DELETE_BLOCK": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0431\u043b\u043e\u043a", + "DELETE_X_BLOCKS": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c %1 \u0431\u043b\u043e\u043a\u043e\u0432", + "COLLAPSE_BLOCK": "\u0421\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0431\u043b\u043e\u043a", + "COLLAPSE_ALL": "\u0421\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0431\u043b\u043e\u043a\u0438", + "EXPAND_BLOCK": "\u0420\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0431\u043b\u043e\u043a", + "EXPAND_ALL": "\u0420\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0431\u043b\u043e\u043a\u0438", + "DISABLE_BLOCK": "\u041e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0431\u043b\u043e\u043a", + "ENABLE_BLOCK": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0431\u043b\u043e\u043a", + "HELP": "\u0421\u043f\u0440\u0430\u0432\u043a\u0430", + "CHANGE_VALUE_TITLE": "\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435:", + "NEW_VARIABLE": "\u041d\u043e\u0432\u0430\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f\u2026", + "NEW_VARIABLE_TITLE": "\u0418\u043c\u044f \u043d\u043e\u0432\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439:", + "RENAME_VARIABLE": "\u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e\u2026", + "RENAME_VARIABLE_TITLE": "\u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 '%1' \u0432:", + "COLOUR_PICKER_HELPURL": "http://ru.wikipedia.org/wiki/\u0426\u0432\u0435\u0442", + "COLOUR_PICKER_TOOLTIP": "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0446\u0432\u0435\u0442 \u0438\u0437 \u043f\u0430\u043b\u0438\u0442\u0440\u044b.", + "COLOUR_RANDOM_TITLE": "\u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0439 \u0446\u0432\u0435\u0442", + "COLOUR_RANDOM_TOOLTIP": "\u0412\u044b\u0431\u0438\u0440\u0430\u0435\u0442 \u0446\u0432\u0435\u0442 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c.", + "COLOUR_RGB_TITLE": "\u0446\u0432\u0435\u0442 \u0438\u0437", + "COLOUR_RGB_RED": "\u043a\u0440\u0430\u0441\u043d\u043e\u0433\u043e", + "COLOUR_RGB_GREEN": "\u0437\u0435\u043b\u0451\u043d\u043e\u0433\u043e", + "COLOUR_RGB_BLUE": "\u0441\u0438\u043d\u0435\u0433\u043e", + "COLOUR_RGB_TOOLTIP": "\u0421\u043e\u0437\u0434\u0430\u0451\u0442 \u0446\u0432\u0435\u0442 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u043f\u0440\u043e\u043f\u043e\u0440\u0446\u0438\u0435\u0439 \u043a\u0440\u0430\u0441\u043d\u043e\u0433\u043e, \u0437\u0435\u043b\u0435\u043d\u043e\u0433\u043e \u0438 \u0441\u0438\u043d\u0435\u0433\u043e. \u0412\u0441\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u043c\u0435\u0436\u0434\u0443 0 \u0438 100.", + "COLOUR_BLEND_TITLE": "\u0441\u043c\u0435\u0448\u0430\u0442\u044c", + "COLOUR_BLEND_COLOUR1": "\u0446\u0432\u0435\u0442 1", + "COLOUR_BLEND_COLOUR2": "\u0446\u0432\u0435\u0442 2", + "COLOUR_BLEND_RATIO": "\u0434\u043e\u043b\u044f \u0446\u0432\u0435\u0442\u0430 1", + "COLOUR_BLEND_TOOLTIP": "\u0421\u043c\u0435\u0448\u0438\u0432\u0430\u0435\u0442 \u0434\u0432\u0430 \u0446\u0432\u0435\u0442\u0430 \u0432 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0438 (0.0 - 1.0).", + "CONTROLS_REPEAT_HELPURL": "http://ru.wikipedia.org/wiki/\u0426\u0438\u043a\u043b_(\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435)", + "CONTROLS_REPEAT_TITLE": "\u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c %1 \u0440\u0430\u0437", + "CONTROLS_REPEAT_TITLE_REPEAT": "\u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c", + "CONTROLS_REPEAT_TITLE_TIMES": "\u0440\u0430\u0437", + "CONTROLS_REPEAT_INPUT_DO": "\u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c", + "CONTROLS_REPEAT_TOOLTIP": "\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437.", + "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "\u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c, \u043f\u043e\u043a\u0430", + "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "\u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c, \u043f\u043e\u043a\u0430 \u043d\u0435", + "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "\u041f\u043e\u043a\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u0438\u043d\u043d\u043e, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b.", + "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "\u041f\u043e\u043a\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043b\u043e\u0436\u043d\u043e, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b", + "CONTROLS_FOR_TOOLTIP": "\u041f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 %1 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043e\u0442 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0434\u043e \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0433\u043e \u0441 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c \u0448\u0430\u0433\u043e\u043c \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b.", + "CONTROLS_FOR_INPUT_WITH": "\u0446\u0438\u043a\u043b \u043f\u043e", + "CONTROLS_FOR_INPUT_FROM_TO_BY": "\u043e\u0442 %1 \u0434\u043e %2 \u0441 \u0448\u0430\u0433\u043e\u043c %3", + "CONTROLS_FOREACH_INPUT_ITEM": "\u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430", + "CONTROLS_FOREACH_INPUT_INLIST": "\u0432 \u0441\u043f\u0438\u0441\u043a\u0435", + "CONTROLS_FOREACH_TOOLTIP": "\u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0432 \u0441\u043f\u0438\u0441\u043a\u0435, \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 '%1' \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b.", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "\u0432\u044b\u0439\u0442\u0438 \u0438\u0437 \u0446\u0438\u043a\u043b\u0430", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "\u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c\u0443 \u0448\u0430\u0433\u0443 \u0446\u0438\u043a\u043b\u0430", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "\u041f\u0440\u0435\u0440\u044b\u0432\u0430\u0435\u0442 \u044d\u0442\u043e\u0442 \u0446\u0438\u043a\u043b.", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "\u041f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043e\u0441\u0442\u0430\u0442\u043e\u043a \u0446\u0438\u043a\u043b\u0430 \u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442 \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c\u0443 \u0448\u0430\u0433\u0443.", + "CONTROLS_FLOW_STATEMENTS_WARNING": "\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435: \u044d\u0442\u043e\u0442 \u0431\u043b\u043e\u043a \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u0446\u0438\u043a\u043b\u0430.", + "CONTROLS_IF_TOOLTIP_1": "\u0415\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u0438\u043d\u043d\u043e, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b.", + "CONTROLS_IF_TOOLTIP_2": "\u0415\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u0438\u043d\u043d\u043e, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043f\u0435\u0440\u0432\u044b\u0439 \u0431\u043b\u043e\u043a \u043a\u043e\u043c\u0430\u043d\u0434. \u0418\u043d\u0430\u0447\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432\u0442\u043e\u0440\u043e\u0439 \u0431\u043b\u043e\u043a \u043a\u043e\u043c\u0430\u043d\u0434.", + "CONTROLS_IF_TOOLTIP_3": "\u0415\u0441\u043b\u0438 \u043f\u0435\u0440\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u0438\u043d\u043d\u043e, \u0442\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043f\u0435\u0440\u0432\u044b\u0439 \u0431\u043b\u043e\u043a \u043a\u043e\u043c\u0430\u043d\u0434.\n\u0418\u043d\u0430\u0447\u0435, \u0435\u0441\u043b\u0438 \u0432\u0442\u043e\u0440\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u0438\u043d\u043d\u043e, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0432\u0442\u043e\u0440\u043e\u0439 \u0431\u043b\u043e\u043a \u043a\u043e\u043c\u0430\u043d\u0434.", + "CONTROLS_IF_TOOLTIP_4": "\u0415\u0441\u043b\u0438 \u043f\u0435\u0440\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u0438\u043d\u043d\u043e, \u0442\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043f\u0435\u0440\u0432\u044b\u0439 \u0431\u043b\u043e\u043a \u043a\u043e\u043c\u0430\u043d\u0434. \u0412 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u0432\u0442\u043e\u0440\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u0438\u043d\u043d\u043e, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0432\u0442\u043e\u0440\u043e\u0439 \u0431\u043b\u043e\u043a \u043a\u043e\u043c\u0430\u043d\u0434. \u0415\u0441\u043b\u0438 \u043d\u0438 \u043e\u0434\u043d\u043e \u0438\u0437 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043d\u0435 \u0438\u0441\u0442\u0438\u043d\u043d\u043e, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0431\u043b\u043e\u043a \u043a\u043e\u043c\u0430\u043d\u0434.", + "CONTROLS_IF_MSG_IF": "\u0435\u0441\u043b\u0438", + "CONTROLS_IF_MSG_ELSEIF": "\u0438\u043d\u0430\u0447\u0435 \u0435\u0441\u043b\u0438", + "CONTROLS_IF_MSG_ELSE": "\u0438\u043d\u0430\u0447\u0435", + "CONTROLS_IF_IF_TOOLTIP": "\u0414\u043e\u0431\u0430\u0432\u044c\u0442\u0435, \u0443\u0434\u0430\u043b\u0438\u0442\u0435, \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u043a\u0438 \u0431\u043b\u043e\u043a\u0430 \"\u0435\u0441\u043b\u0438\".", + "CONTROLS_IF_ELSEIF_TOOLTIP": "\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u043a \u0431\u043b\u043e\u043a\u0443 \"\u0435\u0441\u043b\u0438\"", + "CONTROLS_IF_ELSE_TOOLTIP": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u043a\u043e\u043d\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0435, \u043e\u0431\u043e\u0431\u0449\u0430\u044e\u0449\u0435\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u0434\u043b\u044f \u0431\u043b\u043e\u043a\u0430 \u00ab\u0435\u0441\u043b\u0438\u00bb.", + "LOGIC_COMPARE_HELPURL": "http://en.wikipedia.org/wiki/Inequality_(mathematics)", + "LOGIC_COMPARE_TOOLTIP_EQ": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u0438\u043d\u0430, \u0435\u0441\u043b\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0440\u0430\u0432\u043d\u044b.", + "LOGIC_COMPARE_TOOLTIP_NEQ": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u0438\u043d\u0430, \u0435\u0441\u043b\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043d\u0435 \u0440\u0430\u0432\u043d\u044b.", + "LOGIC_COMPARE_TOOLTIP_LT": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u0438\u043d\u0430, \u0435\u0441\u043b\u0438 \u043f\u0435\u0440\u0432\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043c\u0435\u043d\u044c\u0448\u0435 \u0432\u0442\u043e\u0440\u043e\u0433\u043e.", + "LOGIC_COMPARE_TOOLTIP_LTE": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u0438\u043d\u0430, \u0435\u0441\u043b\u0438 \u043f\u0435\u0440\u0432\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043c\u0435\u043d\u044c\u0448\u0435 \u0438\u043b\u0438 \u0440\u0430\u0432\u0435\u043d \u0432\u0442\u043e\u0440\u043e\u043c\u0443.", + "LOGIC_COMPARE_TOOLTIP_GT": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u0438\u043d\u0430, \u0435\u0441\u043b\u0438 \u043f\u0435\u0440\u0432\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0442\u043e\u0440\u043e\u0433\u043e.", + "LOGIC_COMPARE_TOOLTIP_GTE": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u0438\u043d\u0430, \u0435\u0441\u043b\u0438 \u043f\u0435\u0440\u0432\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0431\u043e\u043b\u044c\u0448\u0435 \u0438\u043b\u0438 \u0440\u0430\u0432\u0435\u043d \u0432\u0442\u043e\u0440\u043e\u043c\u0443.", + "LOGIC_OPERATION_TOOLTIP_AND": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u0438\u043d\u0430, \u0435\u0441\u043b\u0438 \u043e\u0431\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u0438\u0441\u0442\u0438\u043d\u043d\u044b.", + "LOGIC_OPERATION_AND": "\u0438", + "LOGIC_OPERATION_TOOLTIP_OR": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u0438\u043d\u0430, \u0435\u0441\u043b\u0438 \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u0438\u043d \u0438\u0437 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0438\u0441\u0442\u0438\u043d\u043d\u0435\u043d.", + "LOGIC_OPERATION_OR": "\u0438\u043b\u0438", + "LOGIC_NEGATE_TITLE": "\u043d\u0435 %1", + "LOGIC_NEGATE_TOOLTIP": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u0438\u043d\u0430, \u0435\u0441\u043b\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043b\u043e\u0436\u0435\u043d. \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043b\u043e\u0436\u044c, \u0435\u0441\u043b\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0438\u0441\u0442\u0438\u043d\u043d\u0435\u043d.", + "LOGIC_BOOLEAN_TRUE": "\u0438\u0441\u0442\u0438\u043d\u0430", + "LOGIC_BOOLEAN_FALSE": "\u043b\u043e\u0436\u044c", + "LOGIC_BOOLEAN_TOOLTIP": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u0438\u043d\u0430 \u0438\u043b\u0438 \u043b\u043e\u0436\u044c.", + "LOGIC_NULL_HELPURL": "http://en.wikipedia.org/wiki/Nullable_type", + "LOGIC_NULL": "\u043d\u0438\u0447\u0442\u043e", + "LOGIC_NULL_TOOLTIP": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u0438\u0447\u0442\u043e.", + "LOGIC_TERNARY_HELPURL": "http://ru.wikipedia.org/wiki/\u0422\u0435\u0440\u043d\u0430\u0440\u043d\u0430\u044f_\u0443\u0441\u043b\u043e\u0432\u043d\u0430\u044f_\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f", + "LOGIC_TERNARY_CONDITION": "\u0432\u044b\u0431\u043e\u0440", + "LOGIC_TERNARY_IF_TRUE": "\u0435\u0441\u043b\u0438 \u0438\u0441\u0442\u0438\u043d\u0430", + "LOGIC_TERNARY_IF_FALSE": "\u0435\u0441\u043b\u0438 \u043b\u043e\u0436\u044c", + "LOGIC_TERNARY_TOOLTIP": "\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u0432\u044b\u0431\u043e\u0440\u0430. \u0415\u0441\u043b\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u0438\u0441\u0442\u0438\u043d\u043d\u043e, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u0435\u0440\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0432\u0442\u043e\u0440\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435.", + "MATH_NUMBER_HELPURL": "http://ru.wikipedia.org/wiki/\u0427\u0438\u0441\u043b\u043e", + "MATH_NUMBER_TOOLTIP": "\u0427\u0438\u0441\u043b\u043e.", + "MATH_ARITHMETIC_HELPURL": "http://ru.wikipedia.org/wiki/\u0410\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u043a\u0430", + "MATH_ARITHMETIC_TOOLTIP_ADD": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0443\u043c\u043c\u0443 \u0434\u0432\u0443\u0445 \u0447\u0438\u0441\u0435\u043b.", + "MATH_ARITHMETIC_TOOLTIP_MINUS": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0440\u0430\u0437\u043d\u043e\u0441\u0442\u044c \u0434\u0432\u0443\u0445 \u0447\u0438\u0441\u0435\u043b.", + "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0434\u0432\u0443\u0445 \u0447\u0438\u0441\u0435\u043b.", + "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0447\u0430\u0441\u0442\u043d\u043e\u0435 \u043e\u0442 \u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 \u043d\u0430 \u0432\u0442\u043e\u0440\u043e\u0435.", + "MATH_ARITHMETIC_TOOLTIP_POWER": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u0435\u0440\u0432\u043e\u0435 \u0447\u0438\u0441\u043b\u043e, \u0432\u043e\u0437\u0432\u0435\u0434\u0451\u043d\u043d\u043e\u0435 \u0432 \u0441\u0442\u0435\u043f\u0435\u043d\u044c \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430.", + "MATH_SINGLE_HELPURL": "http://ru.wikipedia.org/wiki/\u041a\u0432\u0430\u0434\u0440\u0430\u0442\u043d\u044b\u0439_\u043a\u043e\u0440\u0435\u043d\u044c", + "MATH_SINGLE_OP_ROOT": "\u043a\u0432\u0430\u0434\u0440\u0430\u0442\u043d\u044b\u0439 \u043a\u043e\u0440\u0435\u043d\u044c", + "MATH_SINGLE_TOOLTIP_ROOT": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u043d\u044b\u0439 \u043a\u043e\u0440\u0435\u043d\u044c \u0447\u0438\u0441\u043b\u0430.", + "MATH_SINGLE_OP_ABSOLUTE": "\u043c\u043e\u0434\u0443\u043b\u044c", + "MATH_SINGLE_TOOLTIP_ABS": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043c\u043e\u0434\u0443\u043b\u044c \u0447\u0438\u0441\u043b\u0430", + "MATH_SINGLE_TOOLTIP_NEG": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u0440\u043e\u0442\u0438\u0432\u043e\u043f\u043e\u043b\u043e\u0436\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e.", + "MATH_SINGLE_TOOLTIP_LN": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u0430\u0442\u0443\u0440\u0430\u043b\u044c\u043d\u044b\u0439 \u043b\u043e\u0433\u0430\u0440\u0438\u0444\u043c \u0447\u0438\u0441\u043b\u0430.", + "MATH_SINGLE_TOOLTIP_LOG10": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0434\u0435\u0441\u044f\u0442\u0438\u0447\u043d\u044b\u0439 \u043b\u043e\u0433\u0430\u0440\u0438\u0444\u043c \u0447\u0438\u0441\u043b\u0430.", + "MATH_SINGLE_TOOLTIP_EXP": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0435 \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0435\u043f\u0435\u043d\u0438.", + "MATH_SINGLE_TOOLTIP_POW10": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 10 \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0435\u043f\u0435\u043d\u0438.", + "MATH_TRIG_HELPURL": "http://ru.wikipedia.org/wiki/\u0422\u0440\u0438\u0433\u043e\u043d\u043e\u043c\u0435\u0442\u0440\u0438\u0447\u0435\u0441\u043a\u0438\u0435_\u0444\u0443\u043d\u043a\u0446\u0438\u0438", + "MATH_TRIG_TOOLTIP_SIN": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0438\u043d\u0443\u0441 \u0443\u0433\u043b\u0430 \u0432 \u0433\u0440\u0430\u0434\u0443\u0441\u0430\u0445.", + "MATH_TRIG_TOOLTIP_COS": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043a\u043e\u0441\u0438\u043d\u0443\u0441 \u0443\u0433\u043b\u0430 \u0432 \u0433\u0440\u0430\u0434\u0443\u0441\u0430\u0445.", + "MATH_TRIG_TOOLTIP_TAN": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0430\u043d\u0433\u0435\u043d\u0441 \u0443\u0433\u043b\u0430 \u0432 \u0433\u0440\u0430\u0434\u0443\u0441\u0430\u0445.", + "MATH_TRIG_TOOLTIP_ASIN": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0430\u0440\u043a\u0441\u0438\u043d\u0443\u0441 (\u0432 \u0433\u0440\u0430\u0434\u0443\u0441\u0430\u0445).", + "MATH_TRIG_TOOLTIP_ACOS": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0430\u0440\u043a\u043a\u043e\u0441\u0438\u043d\u0443\u0441 (\u0432 \u0433\u0440\u0430\u0434\u0443\u0441\u0430\u0445).", + "MATH_TRIG_TOOLTIP_ATAN": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0430\u0440\u043a\u0442\u0430\u043d\u0433\u0435\u043d\u0441 (\u0432 \u0433\u0440\u0430\u0434\u0443\u0441\u0430\u0445)", + "MATH_CONSTANT_HELPURL": "http://ru.wikipedia.org/wiki/\u041c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f_\u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430", + "MATH_CONSTANT_TOOLTIP": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0434\u043d\u0443 \u0438\u0437 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0445 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442: \u03c0 (3.141...), e (2.718...), \u03c6 (1.618...), sqrt(2) (1.414...), sqrt(\u00bd) (0.707...) \u0438\u043b\u0438 \u221e (\u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0441\u0442\u044c).", + "MATH_IS_EVEN": "\u0447\u0451\u0442\u043d\u043e\u0435", + "MATH_IS_ODD": "\u043d\u0435\u0447\u0451\u0442\u043d\u043e\u0435", + "MATH_IS_PRIME": "\u043f\u0440\u043e\u0441\u0442\u043e\u0435", + "MATH_IS_WHOLE": "\u0446\u0435\u043b\u043e\u0435", + "MATH_IS_POSITIVE": "\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435", + "MATH_IS_NEGATIVE": "\u043e\u0442\u0440\u0438\u0446\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0435", + "MATH_IS_DIVISIBLE_BY": "\u0434\u0435\u043b\u0438\u0442\u0441\u044f \u043d\u0430", + "MATH_IS_TOOLTIP": "\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0438 \u0447\u0438\u0441\u043b\u043e \u0447\u0451\u0442\u043d\u044b\u043c, \u043d\u0435\u0447\u0451\u0442\u043d\u044b\u043c, \u043f\u0440\u043e\u0441\u0442\u044b\u043c, \u0446\u0435\u043b\u044b\u043c, \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c, \u043e\u0442\u0440\u0438\u0446\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0438\u043b\u0438 \u043e\u043d\u043e \u043a\u0440\u0430\u0442\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u043c\u0443 \u0447\u0438\u0441\u043b\u0443. \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u0438\u043d\u0430 \u0438\u043b\u0438 \u043b\u043e\u0436\u044c.", + "MATH_CHANGE_TITLE_CHANGE": "\u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c", + "MATH_CHANGE_INPUT_BY": "\u043d\u0430", + "MATH_CHANGE_TOOLTIP": "\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0447\u0438\u0441\u043b\u043e \u043a \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 '%1'.", + "MATH_ROUND_HELPURL": "http://ru.wikipedia.org/wiki/\u041e\u043a\u0440\u0443\u0433\u043b\u0435\u043d\u0438\u0435", + "MATH_ROUND_TOOLTIP": "\u041e\u043a\u0440\u0443\u0433\u043b\u044f\u0435\u0442 \u0447\u0438\u0441\u043b\u043e \u0434\u043e \u0431\u043e\u043b\u044c\u0448\u0435\u0433\u043e \u0438\u043b\u0438 \u043c\u0435\u043d\u044c\u0448\u0435\u0433\u043e.", + "MATH_ROUND_OPERATOR_ROUND": "\u043e\u043a\u0440\u0443\u0433\u043b\u0438\u0442\u044c", + "MATH_ROUND_OPERATOR_ROUNDUP": "\u043e\u043a\u0440\u0443\u0433\u043b\u0438\u0442\u044c \u043a \u0431\u043e\u043b\u044c\u0448\u0435\u043c\u0443", + "MATH_ROUND_OPERATOR_ROUNDDOWN": "\u043e\u043a\u0440\u0443\u0433\u043b\u0438\u0442\u044c \u043a \u043c\u0435\u043d\u044c\u0448\u0435\u043c\u0443", + "MATH_ONLIST_OPERATOR_SUM": "\u0441\u0443\u043c\u043c\u0430 \u0441\u043f\u0438\u0441\u043a\u0430", + "MATH_ONLIST_TOOLTIP_SUM": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0443\u043c\u043c\u0443 \u0432\u0441\u0435\u0445 \u0447\u0438\u0441\u0435\u043b \u0432 \u0441\u043f\u0438\u0441\u043a\u0435.", + "MATH_ONLIST_OPERATOR_MIN": "\u043d\u0430\u0438\u043c\u0435\u043d\u044c\u0448\u0435\u0435 \u0432 \u0441\u043f\u0438\u0441\u043a\u0435", + "MATH_ONLIST_TOOLTIP_MIN": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u0430\u0438\u043c\u0435\u043d\u044c\u0448\u0435\u0435 \u0447\u0438\u0441\u043b\u043e \u0441\u043f\u0438\u0441\u043a\u0430.", + "MATH_ONLIST_OPERATOR_MAX": "\u043d\u0430\u0438\u0431\u043e\u043b\u044c\u0448\u0435\u0435 \u0432 \u0441\u043f\u0438\u0441\u043a\u0435", + "MATH_ONLIST_TOOLTIP_MAX": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u0430\u0438\u0431\u043e\u043b\u044c\u0448\u0435\u0435 \u0447\u0438\u0441\u043b\u043e \u0441\u043f\u0438\u0441\u043a\u0430.", + "MATH_ONLIST_OPERATOR_AVERAGE": "\u0441\u0440\u0435\u0434\u043d\u0435\u0435 \u0430\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0441\u043f\u0438\u0441\u043a\u0430", + "MATH_ONLIST_TOOLTIP_AVERAGE": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0440\u0435\u0434\u043d\u0435\u0435 \u0430\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0441\u043f\u0438\u0441\u043a\u0430.", + "MATH_ONLIST_OPERATOR_MEDIAN": "\u043c\u0435\u0434\u0438\u0430\u043d\u0430 \u0441\u043f\u0438\u0441\u043a\u0430", + "MATH_ONLIST_TOOLTIP_MEDIAN": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043c\u0435\u0434\u0438\u0430\u043d\u0443 \u0441\u043f\u0438\u0441\u043a\u0430.", + "MATH_ONLIST_OPERATOR_MODE": "\u043c\u043e\u0434\u044b \u0441\u043f\u0438\u0441\u043a\u0430", + "MATH_ONLIST_TOOLTIP_MODE": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0447\u0430\u0441\u0442\u043e \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0441\u043f\u0438\u0441\u043a\u0430.", + "MATH_ONLIST_OPERATOR_STD_DEV": "\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0435 \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u0430", + "MATH_ONLIST_TOOLTIP_STD_DEV": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0435 \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u0430.", + "MATH_ONLIST_OPERATOR_RANDOM": "\u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u043f\u0438\u0441\u043a\u0430", + "MATH_ONLIST_TOOLTIP_RANDOM": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u043f\u0438\u0441\u043a\u0430.", + "MATH_MODULO_HELPURL": "http://ru.wikipedia.org/wiki/\u0414\u0435\u043b\u0435\u043d\u0438\u0435_\u0441_\u043e\u0441\u0442\u0430\u0442\u043a\u043e\u043c", + "MATH_MODULO_TITLE": "\u043e\u0441\u0442\u0430\u0442\u043e\u043a \u043e\u0442 %1 : %2", + "MATH_MODULO_TOOLTIP": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0441\u0442\u0430\u0442\u043e\u043a \u043e\u0442 \u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0434\u0432\u0443\u0445 \u0447\u0438\u0441\u0435\u043b.", + "MATH_CONSTRAIN_TITLE": "\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c %1 \u0441\u043d\u0438\u0437\u0443 %2 \u0441\u0432\u0435\u0440\u0445\u0443 %3", + "MATH_CONSTRAIN_TOOLTIP": "\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0447\u0438\u0441\u043b\u043e \u043d\u0438\u0436\u043d\u0435\u0439 \u0438 \u0432\u0435\u0440\u0445\u043d\u0435\u0439 \u0433\u0440\u0430\u043d\u0438\u0446\u0430\u043c\u0438 (\u0432\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e).", + "MATH_RANDOM_INT_HELPURL": "http://ru.wikipedia.org/wiki/\u0413\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440_\u043f\u0441\u0435\u0432\u0434\u043e\u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0445_\u0447\u0438\u0441\u0435\u043b", + "MATH_RANDOM_INT_TITLE": "\u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0435 \u0446\u0435\u043b\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u043e\u0442 %1 \u0434\u043b\u044f %2", + "MATH_RANDOM_INT_TOOLTIP": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u043c\u0435\u0436\u0434\u0443 \u0434\u0432\u0443\u043c\u044f \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u043c\u0438 (\u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0438 \u0438\u0445).", + "MATH_RANDOM_FLOAT_HELPURL": "http://ru.wikipedia.org/wiki/\u0413\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440_\u043f\u0441\u0435\u0432\u0434\u043e\u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0445_\u0447\u0438\u0441\u0435\u043b", + "MATH_RANDOM_FLOAT_TITLE_RANDOM": "\u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u043e\u0442 0 (\u0432\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e) \u0434\u043e 1", + "MATH_RANDOM_FLOAT_TOOLTIP": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u043e\u0442 0.0 (\u0432\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e) \u0434\u043e 1.0.", + "TEXT_TEXT_HELPURL": "http://ru.wikipedia.org/wiki/\u0421\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0439_\u0442\u0438\u043f", + "TEXT_TEXT_TOOLTIP": "\u0411\u0443\u043a\u0432\u0430, \u0441\u043b\u043e\u0432\u043e \u0438\u043b\u0438 \u0441\u0442\u0440\u043e\u043a\u0430 \u0442\u0435\u043a\u0441\u0442\u0430.", + "TEXT_JOIN_TITLE_CREATEWITH": "\u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442 \u0438\u0437", + "TEXT_JOIN_TOOLTIP": "\u0421\u043e\u0437\u0434\u0430\u0451\u0442 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u0442\u0435\u043a\u0441\u0442\u0430, \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u044f \u043b\u044e\u0431\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432", + "TEXT_CREATE_JOIN_TITLE_JOIN": "\u0441\u043e\u0435\u0434\u0438\u043d\u0438\u0442\u044c", + "TEXT_CREATE_JOIN_TOOLTIP": "\u0414\u043e\u0431\u0430\u0432\u044c\u0442\u0435, \u0443\u0434\u0430\u043b\u0438\u0442\u0435, \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u043a\u0438 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u0431\u043b\u043e\u043a\u0430.", + "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043a \u0442\u0435\u043a\u0441\u0442\u0443.", + "TEXT_APPEND_TO": "\u043a", + "TEXT_APPEND_APPENDTEXT": "\u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u0435\u043a\u0441\u0442", + "TEXT_APPEND_TOOLTIP": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u0435\u043a\u0441\u0442 \u043a \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u00ab%1\u00bb.", + "TEXT_LENGTH_TITLE": "\u0434\u043b\u0438\u043d\u0430 %1", + "TEXT_LENGTH_TOOLTIP": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0447\u0438\u0441\u043b\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 (\u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043f\u0440\u043e\u0431\u0435\u043b\u044b) \u0432 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u043c \u0442\u0435\u043a\u0441\u0442\u0435.", + "TEXT_ISEMPTY_TITLE": "%1 \u043f\u0443\u0441\u0442", + "TEXT_ISEMPTY_TOOLTIP": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u0438\u043d\u0430, \u0435\u0441\u043b\u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u043f\u0443\u0441\u0442.", + "TEXT_INDEXOF_TOOLTIP": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u043e\u043c\u0435\u0440 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u043f\u0435\u0440\u0432\u043e\u0433\u043e/\u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430 \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u043c. \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 0, \u0435\u0441\u043b\u0438 \u0442\u0435\u043a\u0441\u0442 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d.", + "TEXT_INDEXOF_INPUT_INTEXT": "\u0432 \u0442\u0435\u043a\u0441\u0442\u0435", + "TEXT_INDEXOF_OPERATOR_FIRST": "\u043d\u0430\u0439\u0442\u0438 \u043f\u0435\u0440\u0432\u043e\u0435 \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0430", + "TEXT_INDEXOF_OPERATOR_LAST": "\u043d\u0430\u0439\u0442\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0430", + "TEXT_CHARAT_INPUT_INTEXT": "\u0432 \u0442\u0435\u043a\u0441\u0442\u0435", + "TEXT_CHARAT_FROM_START": "\u0432\u0437\u044f\u0442\u044c \u0431\u0443\u043a\u0432\u0443 \u2116", + "TEXT_CHARAT_FROM_END": "\u0432\u0437\u044f\u0442\u044c \u0431\u0443\u043a\u0432\u0443 \u2116 \u0441 \u043a\u043e\u043d\u0446\u0430", + "TEXT_CHARAT_FIRST": "\u0432\u0437\u044f\u0442\u044c \u043f\u0435\u0440\u0432\u0443\u044e \u0431\u0443\u043a\u0432\u0443", + "TEXT_CHARAT_LAST": "\u0432\u0437\u044f\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0431\u0443\u043a\u0432\u0443", + "TEXT_CHARAT_RANDOM": "\u0432\u0437\u044f\u0442\u044c \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u0443\u044e \u0431\u0443\u043a\u0432\u0443", + "TEXT_CHARAT_TOOLTIP": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0431\u0443\u043a\u0432\u0443 \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438.", + "TEXT_GET_SUBSTRING_TOOLTIP": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u0442\u0435\u043a\u0441\u0442\u0430.", + "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "\u0432 \u0442\u0435\u043a\u0441\u0442\u0435", + "TEXT_GET_SUBSTRING_START_FROM_START": "\u0432\u0437\u044f\u0442\u044c \u043f\u043e\u0434\u0441\u0442\u0440\u043e\u043a\u0443 \u0441 \u0431\u0443\u043a\u0432\u044b \u2116", + "TEXT_GET_SUBSTRING_START_FROM_END": "\u0432\u0437\u044f\u0442\u044c \u043f\u043e\u0434\u0441\u0442\u0440\u043e\u043a\u0443 \u0441 \u0431\u0443\u043a\u0432\u044b \u2116 \u0441 \u043a\u043e\u043d\u0446\u0430", + "TEXT_GET_SUBSTRING_START_FIRST": "\u0432\u0437\u044f\u0442\u044c \u043f\u043e\u0434\u0441\u0442\u0440\u043e\u043a\u0443 \u0441 \u043f\u0435\u0440\u0432\u043e\u0439 \u0431\u0443\u043a\u0432\u044b", + "TEXT_GET_SUBSTRING_END_FROM_START": "\u043f\u043e \u0431\u0443\u043a\u0432\u0443 \u2116", + "TEXT_GET_SUBSTRING_END_FROM_END": "\u043f\u043e \u0431\u0443\u043a\u0432\u0443 \u2116 \u0441 \u043a\u043e\u043d\u0446\u0430", + "TEXT_GET_SUBSTRING_END_LAST": "\u043f\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0431\u0443\u043a\u0432\u0443", + "TEXT_CHANGECASE_TOOLTIP": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043a\u043e\u043f\u0438\u044e \u0442\u0435\u043a\u0441\u0442\u0430 \u0441 \u0417\u0410\u0413\u041b\u0410\u0412\u041d\u042b\u041c\u0418 \u0438\u043b\u0438 \u0441\u0442\u0440\u043e\u0447\u043d\u044b\u043c\u0438 \u0431\u0443\u043a\u0432\u0430\u043c\u0438.", + "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "\u0432 \u0417\u0410\u0413\u041b\u0410\u0412\u041d\u042b\u0415 \u0411\u0423\u041a\u0412\u042b", + "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "\u0432 \u0441\u0442\u0440\u043e\u0447\u043d\u044b\u0435 \u0431\u0443\u043a\u0432\u044b", + "TEXT_CHANGECASE_OPERATOR_TITLECASE": "\u0432 \u0417\u0430\u0433\u043b\u0430\u0432\u043d\u044b\u0435 \u041d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0435 \u0411\u0443\u043a\u0432\u044b", + "TEXT_TRIM_TOOLTIP": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043a\u043e\u043f\u0438\u044e \u0442\u0435\u043a\u0441\u0442\u0430 \u0441 \u043f\u0440\u043e\u0431\u0435\u043b\u0430\u043c\u0438, \u0443\u0434\u0430\u043b\u0435\u043d\u044b\u043c\u0438 \u0441 \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u043b\u0438 \u043e\u0431\u043e\u0438\u0445 \u043a\u043e\u043d\u0446\u043e\u0432.", + "TEXT_TRIM_OPERATOR_BOTH": "\u043e\u0431\u0440\u0435\u0437\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u0435\u043b\u044b \u0441 \u0434\u0432\u0443\u0445 \u0441\u0442\u043e\u0440\u043e\u043d", + "TEXT_TRIM_OPERATOR_LEFT": "\u043e\u0431\u0440\u0435\u0437\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u0435\u043b\u044b \u0441\u043b\u0435\u0432\u0430", + "TEXT_TRIM_OPERATOR_RIGHT": "\u043e\u0431\u0440\u0435\u0437\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u0435\u043b\u044b \u0441\u043f\u0440\u0430\u0432\u0430", + "TEXT_PRINT_TITLE": "\u043d\u0430\u043f\u0435\u0447\u0430\u0442\u0430\u0442\u044c %1", + "TEXT_PRINT_TOOLTIP": "\u041f\u0435\u0447\u0430\u0442\u0430\u0435\u0442 \u0442\u0435\u043a\u0441\u0442, \u0447\u0438\u0441\u043b\u043e \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442.", + "TEXT_PROMPT_TYPE_TEXT": "\u0437\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0442\u0435\u043a\u0441\u0442 \u0441 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u043e\u0439", + "TEXT_PROMPT_TYPE_NUMBER": "\u0437\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0447\u0438\u0441\u043b\u043e \u0441 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u043e\u0439", + "TEXT_PROMPT_TOOLTIP_NUMBER": "\u0417\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0447\u0438\u0441\u043b\u043e.", + "TEXT_PROMPT_TOOLTIP_TEXT": "\u0417\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0442\u0435\u043a\u0441\u0442.", + "LISTS_CREATE_EMPTY_TITLE": "\u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0443\u0441\u0442\u043e\u0439 \u0441\u043f\u0438\u0441\u043e\u043a", + "LISTS_CREATE_EMPTY_TOOLTIP": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u043b\u0438\u043d\u044b 0, \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u0434\u0430\u043d\u043d\u044b\u0445", + "LISTS_CREATE_WITH_TOOLTIP": "\u0421\u043e\u0437\u0434\u0430\u0451\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u0441 \u043b\u044e\u0431\u044b\u043c \u0447\u0438\u0441\u043b\u043e\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432.", + "LISTS_CREATE_WITH_INPUT_WITH": "\u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0438\u0437", + "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "\u0441\u043f\u0438\u0441\u043e\u043a", + "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "\u0414\u043e\u0431\u0430\u0432\u044c\u0442\u0435, \u0443\u0434\u0430\u043b\u0438\u0442\u0435, \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u043a\u0438 \u0431\u043b\u043e\u043a\u0430 \u0441\u043f\u0438\u0441\u043a\u0430.", + "LISTS_CREATE_WITH_ITEM_TOOLTIP": "\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043a \u0441\u043f\u0438\u0441\u043a\u0443.", + "LISTS_REPEAT_TOOLTIP": "\u0421\u043e\u0437\u0434\u0430\u0451\u0442 \u0441\u043f\u0438\u0441\u043e\u043a, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u0438\u0437 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 \u043a\u043e\u043f\u0438\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430.", + "LISTS_REPEAT_TITLE": "\u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0438\u0437 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 %1, \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0435\u0433\u043e\u0441\u044f %2 \u0440\u0430\u0437", + "LISTS_LENGTH_TITLE": "\u0434\u043b\u0438\u043d\u0430 %1", + "LISTS_LENGTH_TOOLTIP": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0434\u043b\u0438\u043d\u0443 \u0441\u043f\u0438\u0441\u043a\u0430.", + "LISTS_IS_EMPTY_TITLE": "%1 \u043f\u0443\u0441\u0442", + "LISTS_TOOLTIP": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u0438\u043d\u0430, \u0435\u0441\u043b\u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u0443\u0441\u0442.", + "LISTS_INLIST": "\u0432 \u0441\u043f\u0438\u0441\u043a\u0435", + "LISTS_INDEX_OF_FIRST": "\u043d\u0430\u0439\u0442\u0438 \u043f\u0435\u0440\u0432\u043e\u0435 \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430", + "LISTS_INDEX_OF_LAST": "\u043d\u0430\u0439\u0442\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430", + "LISTS_INDEX_OF_TOOLTIP": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043d\u043e\u043c\u0435\u0440 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u043f\u0435\u0440\u0432\u043e\u0433\u043e/\u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0432 \u0441\u043f\u0438\u0441\u043a\u0435. \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 0, \u0435\u0441\u043b\u0438 \u0442\u0435\u043a\u0441\u0442 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d.", + "LISTS_GET_INDEX_GET": "\u0432\u0437\u044f\u0442\u044c", + "LISTS_GET_INDEX_GET_REMOVE": "\u0432\u0437\u044f\u0442\u044c \u0438 \u0443\u0434\u0430\u043b\u0438\u0442\u044c", + "LISTS_GET_INDEX_REMOVE": "\u0443\u0434\u0430\u043b\u0438\u0442\u044c", + "LISTS_GET_INDEX_FROM_END": "\u2116 \u0441 \u043a\u043e\u043d\u0446\u0430", + "LISTS_GET_INDEX_FIRST": "\u043f\u0435\u0440\u0432\u044b\u0439", + "LISTS_GET_INDEX_LAST": "\u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439", + "LISTS_GET_INDEX_RANDOM": "\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439", + "LISTS_GET_INDEX_TOOLTIP_GET_FROM_START": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0441\u043f\u0438\u0441\u043a\u0430 (\u21161 - \u043f\u0435\u0440\u0432\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442).", + "LISTS_GET_INDEX_TOOLTIP_GET_FROM_END": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0441\u043f\u0438\u0441\u043a\u0430 (\u21161 - \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442).", + "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u0435\u0440\u0432\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u043f\u0438\u0441\u043a\u0430.", + "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u043f\u0438\u0441\u043a\u0430.", + "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u043f\u0438\u0441\u043a\u0430.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START": "\u0423\u0434\u0430\u043b\u044f\u0435\u0442 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0441\u043f\u0438\u0441\u043a\u0430 (\u21161 - \u043f\u0435\u0440\u0432\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442).", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END": "\u0423\u0434\u0430\u043b\u044f\u0435\u0442 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0441\u043f\u0438\u0441\u043a\u0430 (\u21161 - \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442).", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "\u0423\u0434\u0430\u043b\u044f\u0435\u0442 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u0435\u0440\u0432\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u043f\u0438\u0441\u043a\u0430.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "\u0423\u0434\u0430\u043b\u044f\u0435\u0442 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u043f\u0438\u0441\u043a\u0430.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "\u0423\u0434\u0430\u043b\u044f\u0435\u0442 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u043f\u0438\u0441\u043a\u0430.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START": "\u0423\u0434\u0430\u043b\u044f\u0435\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0441\u043f\u0438\u0441\u043a\u0430 (\u21161 - \u043f\u0435\u0440\u0432\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442).", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END": "\u0423\u0434\u0430\u043b\u044f\u0435\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0441\u043f\u0438\u0441\u043a\u0430 (\u21161 - \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442).", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "\u0423\u0434\u0430\u043b\u044f\u0435\u0442 \u043f\u0435\u0440\u0432\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u043f\u0438\u0441\u043a\u0430.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "\u0423\u0434\u0430\u043b\u044f\u0435\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u043f\u0438\u0441\u043a\u0430.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "\u0423\u0434\u0430\u043b\u044f\u0435\u0442 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u043f\u0438\u0441\u043a\u0430.", + "LISTS_SET_INDEX_SET": "\u043f\u0440\u0438\u0441\u0432\u043e\u0438\u0442\u044c", + "LISTS_SET_INDEX_INSERT": "\u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432", + "LISTS_SET_INDEX_INPUT_TO": "=", + "LISTS_SET_INDEX_TOOLTIP_SET_FROM_START": "\u041f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0441\u043f\u0438\u0441\u043a\u0430 (\u21161 - \u043f\u0435\u0440\u0432\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442).", + "LISTS_SET_INDEX_TOOLTIP_SET_FROM_END": "\u041f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0441\u043f\u0438\u0441\u043a\u0430 (\u21161 - \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442).", + "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "\u041f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0432\u043e\u043c\u0443 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 \u0441\u043f\u0438\u0441\u043a\u0430.", + "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "\u041f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u043c\u0443 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 \u0441\u043f\u0438\u0441\u043a\u0430.", + "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "\u041f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u043c\u0443 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 \u0441\u043f\u0438\u0441\u043a\u0430.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START": "\u0412\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0441\u043f\u0438\u0441\u043a\u0430 (\u21161 - \u043f\u0435\u0440\u0432\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442).", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END": "\u0412\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0441\u043f\u0438\u0441\u043a\u0430 (\u21161 - \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442).", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "\u0412\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0432 \u043d\u0430\u0447\u0430\u043b\u043e \u0441\u043f\u0438\u0441\u043a\u0430.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0432 \u043a\u043e\u043d\u0435\u0446 \u0441\u043f\u0438\u0441\u043a\u0430.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "\u0412\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0432 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u0432 \u0441\u043f\u0438\u0441\u043a\u0435.", + "LISTS_GET_SUBLIST_START_FROM_START": "\u0432\u0437\u044f\u0442\u044c \u043f\u043e\u0434\u0441\u043f\u0438\u0441\u043e\u043a \u0441 \u2116", + "LISTS_GET_SUBLIST_START_FROM_END": "\u0432\u0437\u044f\u0442\u044c \u043f\u043e\u0434\u0441\u043f\u0438\u0441\u043e\u043a \u0441 \u2116 \u0441 \u043a\u043e\u043d\u0446\u0430", + "LISTS_GET_SUBLIST_START_FIRST": "\u0432\u0437\u044f\u0442\u044c \u043f\u043e\u0434\u0441\u043f\u0438\u0441\u043e\u043a \u0441 \u043f\u0435\u0440\u0432\u043e\u0433\u043e", + "LISTS_GET_SUBLIST_END_FROM_START": "\u043f\u043e \u2116", + "LISTS_GET_SUBLIST_END_FROM_END": "\u043f\u043e \u2116 \u0441 \u043a\u043e\u043d\u0446\u0430", + "LISTS_GET_SUBLIST_END_LAST": "\u043f\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439", + "LISTS_GET_SUBLIST_TOOLTIP": "\u0421\u043e\u0437\u0434\u0430\u0451\u0442 \u043a\u043e\u043f\u0438\u044e \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u043f\u0438\u0441\u043a\u0430.", + "VARIABLES_GET_TOOLTIP": "\u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u044d\u0442\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439.", + "VARIABLES_GET_CREATE_SET": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0431\u043b\u043e\u043a \"\u043f\u0440\u0438\u0441\u0432\u043e\u0438\u0442\u044c\" \u0434\u043b\u044f %1", + "VARIABLES_SET_TITLE": "\u043f\u0440\u0438\u0441\u0432\u043e\u0438\u0442\u044c", + "VARIABLES_SET_TAIL": "=", + "VARIABLES_SET_TOOLTIP": "\u041f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432\u0441\u0442\u0430\u0432\u043a\u0438.", + "VARIABLES_SET_CREATE_GET": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0432\u0441\u0442\u0430\u0432\u043a\u0443 %1", + "PROCEDURES_DEFNORETURN_TITLE": "\u0447\u0442\u043e\u0431\u044b", + "PROCEDURES_DEFNORETURN_PROCEDURE": "\u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0447\u0442\u043e-\u0442\u043e", + "PROCEDURES_BEFORE_PARAMS": "\u0441:", + "PROCEDURES_DEFNORETURN_TOOLTIP": "\u0421\u043e\u0437\u0434\u0430\u0451\u0442 \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0443, \u043d\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0443\u044e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435.", + "PROCEDURES_DEFRETURN_RETURN": "\u0432\u0435\u0440\u043d\u0443\u0442\u044c", + "PROCEDURES_DEFRETURN_TOOLTIP": "\u0421\u043e\u0437\u0434\u0430\u0451\u0442 \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0443, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0443\u044e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435.", + "PROCEDURES_DEF_DUPLICATE_WARNING": "\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435: \u044d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0438\u043c\u0435\u0435\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b.", + "PROCEDURES_CALLNORETURN_HELPURL": "http://ru.wikipedia.org/wiki/\u0424\u0443\u043d\u043a\u0446\u0438\u044f_%28\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435%29", + "PROCEDURES_CALLNORETURN_TOOLTIP": "\u0418\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u0443\u044e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0443 '%1'.", + "PROCEDURES_CALLRETURN_HELPURL": "http://ru.wikipedia.org/wiki/\u0424\u0443\u043d\u043a\u0446\u0438\u044f_%28\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435%29", + "PROCEDURES_CALLRETURN_TOOLTIP": "\u0418\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u0443\u044e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0443 '%1' \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435.", + "PROCEDURES_MUTATORCONTAINER_TITLE": "\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b", + "PROCEDURES_MUTATORARG_TITLE": "\u0438\u043c\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430:", + "PROCEDURES_HIGHLIGHT_DEF": "\u0412\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u044b", + "PROCEDURES_CREATE_DO": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0432\u044b\u0437\u043e\u0432 '%1'", + "PROCEDURES_IFRETURN_TOOLTIP": "\u0415\u0441\u043b\u0438 \u043f\u0435\u0440\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u0442\u0438\u043d\u043d\u043e, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0432\u0442\u043e\u0440\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435.", + "PROCEDURES_IFRETURN_WARNING": "\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435: \u042d\u0442\u043e\u0442 \u0431\u043b\u043e\u043a \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438." +} \ No newline at end of file diff --git a/msg/json/sv.json b/msg/json/sv.json new file mode 100644 index 000000000..bcc611d1c --- /dev/null +++ b/msg/json/sv.json @@ -0,0 +1,192 @@ +{ + "@metadata": { + "authors": [ + "Jopparn", + "WikiPhoenix" + ] + }, + "VARIABLES_DEFAULT_NAME": "f\u00f6rem\u00e5l", + "DUPLICATE_BLOCK": "Duplicera", + "ADD_COMMENT": "L\u00e4gg till kommentar", + "REMOVE_COMMENT": "Radera kommentar", + "EXTERNAL_INPUTS": "Externa inmatningar", + "DELETE_BLOCK": "Radera block", + "DELETE_X_BLOCKS": "Radera %1 block", + "COLLAPSE_BLOCK": "F\u00e4ll ihop block", + "COLLAPSE_ALL": "F\u00e4ll ihop block", + "EXPAND_BLOCK": "Expandera block", + "EXPAND_ALL": "Expandera block", + "DISABLE_BLOCK": "Inaktivera block", + "ENABLE_BLOCK": "Aktivera block", + "HELP": "Hj\u00e4lp", + "CHANGE_VALUE_TITLE": "\u00c4ndra v\u00e4rde:", + "NEW_VARIABLE": "Ny variabel...", + "NEW_VARIABLE_TITLE": "Nytt variabelnamn:", + "RENAME_VARIABLE": "Byt namn p\u00e5 variabel...", + "RENAME_VARIABLE_TITLE": "Byt namn p\u00e5 alla variablerna '%1' till:", + "COLOUR_PICKER_HELPURL": "http://sv.wikipedia.org/wiki/F\u00e4rg", + "COLOUR_PICKER_TOOLTIP": "V\u00e4lj en f\u00e4rg fr\u00e5n paletten.", + "COLOUR_RANDOM_TITLE": "slumpf\u00e4rg", + "COLOUR_RANDOM_TOOLTIP": "V\u00e4lj en slumpartad f\u00e4rg.", + "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", + "COLOUR_RGB_TITLE": "f\u00e4rg med", + "COLOUR_RGB_RED": "r\u00f6d", + "COLOUR_RGB_GREEN": "gr\u00f6n", + "COLOUR_RGB_BLUE": "bl\u00e5", + "COLOUR_RGB_TOOLTIP": "Skapa en f\u00e4rg med det angivna m\u00e4ngden r\u00f6d, gr\u00f6n och bl\u00e5. Alla v\u00e4rden m\u00e5ste vara mellan 0 och 100.", + "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", + "COLOUR_BLEND_TITLE": "blanda", + "COLOUR_BLEND_COLOUR1": "f\u00e4rg 1", + "COLOUR_BLEND_COLOUR2": "f\u00e4rg 2", + "COLOUR_BLEND_RATIO": "f\u00f6rh\u00e5llande", + "COLOUR_BLEND_TOOLTIP": "Blandar ihop tv\u00e5 f\u00e4rger med ett best\u00e4mt f\u00f6rh\u00e5llande (0.0 - 1.0).", + "CONTROLS_REPEAT_HELPURL": "http://en.wikipedia.org/wiki/For_loop", + "CONTROLS_REPEAT_TITLE": "upprepa %1 g\u00e5nger", + "CONTROLS_REPEAT_TITLE_REPEAT": "upprepa", + "CONTROLS_REPEAT_TITLE_TIMES": "g\u00e5nger", + "CONTROLS_REPEAT_INPUT_DO": "utf\u00f6r", + "CONTROLS_REPEAT_TOOLTIP": "Utf\u00f6r n\u00e5gra kommandon flera g\u00e5nger.", + "CONTROLS_WHILEUNTIL_HELPURL": "http://code.google.com/p/blockly/wiki/Repeat", + "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "upprepa medan", + "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "upprepa tills", + "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Medan ett v\u00e4rde \u00e4r sant, utf\u00f6r n\u00e5gra kommandon.", + "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Medan ett v\u00e4rde \u00e4r falskt, utf\u00f6r n\u00e5gra kommandon.", + "CONTROLS_FOR_HELPURL": "https://code.google.com/p/blockly/wiki/Loops#count_with", + "CONTROLS_FOR_INPUT_WITH": "r\u00e4kna med", + "CONTROLS_FOR_INPUT_FROM_TO_BY": "fr\u00e5n %1 till %2 med %3", + "CONTROLS_FOREACH_INPUT_ITEM": "f\u00f6r varje f\u00f6rem\u00e5l", + "CONTROLS_FOREACH_INPUT_INLIST": "i listan", + "CONTROLS_FOREACH_TOOLTIP": "F\u00f6r varje objekt i en lista, ange variabeln '%1' till objektet, och utf\u00f6r sedan n\u00e5gra kommandon.", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "bryt ut ur upprepning", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Bryta ut ur den inneh\u00e5llande upprepningen.", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Hoppa \u00f6ver resten av denna upprepning och forts\u00e4tt med n\u00e4sta upprepning.", + "CONTROLS_FLOW_STATEMENTS_WARNING": "Varning: Detta block kan endast anv\u00e4ndas i en upprepning.", + "CONTROLS_IF_TOOLTIP_1": "Om ett v\u00e4rde \u00e4r sant, utf\u00f6r n\u00e5gra kommandon.", + "CONTROLS_IF_TOOLTIP_2": "Om v\u00e4rdet \u00e4r sant, utf\u00f6r det f\u00f6rsta kommandoblocket. Annars utf\u00f6r det andra kommandoblocket.", + "CONTROLS_IF_TOOLTIP_3": "Om det f\u00f6rsta v\u00e4rdet \u00e4r sant, utf\u00f6r det f\u00f6rsta kommandoblocket. Annars, om det andra v\u00e4rdet \u00e4r sant, utf\u00f6r det andra kommandoblocket.", + "CONTROLS_IF_TOOLTIP_4": "Om det f\u00f6rsta v\u00e4rdet \u00e4r sant, utf\u00f6r det f\u00f6rsta kommandoblocket. Annars, om det andra v\u00e4rdet \u00e4r sant, utf\u00f6r det andra kommandoblocket. Om ingen av v\u00e4rdena \u00e4r sanna, utf\u00f6r det sista kommandoblocket.", + "CONTROLS_IF_MSG_IF": "om", + "CONTROLS_IF_MSG_ELSEIF": "annars om", + "CONTROLS_IF_MSG_ELSE": "annars", + "CONTROLS_IF_IF_TOOLTIP": "L\u00e4gg till, ta bort eller \u00e4ndra ordningen f\u00f6r sektioner f\u00f6r att omkonfigurera blocket \"om\".", + "CONTROLS_IF_ELSEIF_TOOLTIP": "L\u00e4gg till ett villkor blocket \"om\".", + "LOGIC_COMPARE_HELPURL": "http://sv.wikipedia.org/wiki/Olikhet", + "LOGIC_OPERATION_AND": "och", + "LOGIC_OPERATION_OR": "eller", + "LOGIC_NEGATE_TITLE": "inte %1", + "LOGIC_BOOLEAN_TRUE": "sant", + "LOGIC_BOOLEAN_FALSE": "falskt", + "LOGIC_TERNARY_CONDITION": "test", + "LOGIC_TERNARY_IF_TRUE": "om sant", + "LOGIC_TERNARY_IF_FALSE": "om falskt", + "MATH_NUMBER_HELPURL": "http://sv.wikipedia.org/wiki/Tal", + "MATH_NUMBER_TOOLTIP": "Ett tal.", + "MATH_ARITHMETIC_HELPURL": "http://sv.wikipedia.org/wiki/Aritmetik", + "MATH_SINGLE_HELPURL": "http://sv.wikipedia.org/wiki/Kvadratrot", + "MATH_SINGLE_OP_ROOT": "kvadratrot", + "MATH_TRIG_HELPURL": "http://sv.wikipedia.org/wiki/Trigonometrisk_funktion", + "MATH_CONSTANT_HELPURL": "http://sv.wikipedia.org/wiki/Matematisk_konstant", + "MATH_IS_EVEN": "\u00e4r j\u00e4mnt", + "MATH_IS_ODD": "\u00e4r udda", + "MATH_IS_PRIME": "\u00e4r ett primtal", + "MATH_IS_WHOLE": "\u00e4r helt", + "MATH_IS_POSITIVE": "\u00e4r positivt", + "MATH_IS_NEGATIVE": "\u00e4r negativt", + "MATH_IS_DIVISIBLE_BY": "\u00e4r delbart med", + "MATH_IS_TOOLTIP": "Kontrollera om ett tal \u00e4r j\u00e4mnt, udda, helt, positivt, negativt eller det \u00e4r delbart med ett best\u00e4mt tal. Returnerar med sant eller falskt.", + "MATH_CHANGE_TITLE_CHANGE": "\u00e4ndra", + "MATH_CHANGE_INPUT_BY": "till", + "MATH_CHANGE_TOOLTIP": "L\u00e4gg till ett tal till variabeln '%1'.", + "MATH_ROUND_HELPURL": "http://sv.wikipedia.org/wiki/Avrundning", + "MATH_ROUND_TOOLTIP": "Avrunda ett tal upp\u00e5t eller ned\u00e5t.", + "MATH_ROUND_OPERATOR_ROUND": "avrunda", + "MATH_ROUND_OPERATOR_ROUNDUP": "avrunda upp\u00e5t", + "MATH_ROUND_OPERATOR_ROUNDDOWN": "avrunda ned\u00e5t", + "MATH_ONLIST_OPERATOR_SUM": "summan av listan", + "MATH_RANDOM_INT_HELPURL": "http://sv.wikipedia.org/wiki/Slumptalsgenerator", + "MATH_RANDOM_INT_TITLE": "slumpartat heltal fr\u00e5n %1 till %2", + "MATH_RANDOM_FLOAT_HELPURL": "http://sv.wikipedia.org/wiki/Slumptalsgenerator", + "TEXT_TEXT_HELPURL": "http://sv.wikipedia.org/wiki/Str%C3%A4ng_%28data%29", + "TEXT_TEXT_TOOLTIP": "En bokstav, ord eller textrad.", + "TEXT_JOIN_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Text_creation", + "TEXT_JOIN_TITLE_CREATEWITH": "skapa text med", + "TEXT_JOIN_TOOLTIP": "Skapa en textbit genom att sammanfoga ett valfritt antal f\u00f6rem\u00e5l.", + "TEXT_CREATE_JOIN_TITLE_JOIN": "sammanfoga", + "TEXT_CREATE_JOIN_TOOLTIP": "L\u00e4gg till, ta bort eller \u00e4ndra ordningen f\u00f6r sektioner f\u00f6r att omkonfigurera detta textblocket.", + "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "L\u00e4gg till ett f\u00f6rem\u00e5l till texten.", + "TEXT_APPEND_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Text_modification", + "TEXT_APPEND_TO": "till", + "TEXT_APPEND_APPENDTEXT": "l\u00e4gg till text", + "TEXT_APPEND_TOOLTIP": "L\u00e4gg till lite text till variabeln '%1'.", + "TEXT_LENGTH_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Text_modification", + "TEXT_LENGTH_TITLE": "l\u00e4ngden p\u00e5 %1", + "TEXT_ISEMPTY_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text", + "TEXT_ISEMPTY_TITLE": "%1 \u00e4r tom", + "TEXT_INDEXOF_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Finding_text", + "TEXT_INDEXOF_INPUT_INTEXT": "i texten", + "TEXT_INDEXOF_OPERATOR_FIRST": "hitta f\u00f6rsta textf\u00f6rekomsten", + "TEXT_INDEXOF_OPERATOR_LAST": "hitta sista textf\u00f6rekomsten", + "TEXT_CHARAT_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Extracting_text", + "TEXT_CHARAT_INPUT_INTEXT": "i texten", + "TEXT_CHARAT_FROM_START": "h\u00e4mta bokstaven #", + "TEXT_CHARAT_FROM_END": "h\u00e4mta bokstaven # fr\u00e5n slutet", + "TEXT_CHARAT_FIRST": "h\u00e4mta f\u00f6rsta bokstaven", + "TEXT_CHARAT_LAST": "h\u00e4mta sista bokstaven", + "TEXT_CHARAT_RANDOM": "h\u00e4mta slumpad bokstav", + "TEXT_GET_SUBSTRING_HELPURL": "http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text", + "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "i texten", + "TEXT_GET_SUBSTRING_END_FROM_START": "till bokstav #", + "TEXT_GET_SUBSTRING_END_FROM_END": "till bokstav # fr\u00e5n slutet", + "TEXT_GET_SUBSTRING_END_LAST": "till sista bokstaven", + "TEXT_CHANGECASE_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case", + "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "till VERSALER", + "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "till gemener", + "TEXT_CHANGECASE_OPERATOR_TITLECASE": "till Versala Initialer", + "TEXT_TRIM_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces", + "TEXT_PRINT_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Printing_text", + "TEXT_PRINT_TITLE": "skriv %1", + "TEXT_PRINT_TOOLTIP": "Skriv angivna texten, talet eller annat v\u00e4rde.", + "TEXT_PROMPT_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user", + "LISTS_CREATE_EMPTY_TITLE": "skapa tom lista", + "LISTS_CREATE_WITH_TOOLTIP": "Skapa en lista med valfritt antal f\u00f6rem\u00e5l.", + "LISTS_CREATE_WITH_INPUT_WITH": "skapa lista med", + "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "lista", + "LISTS_CREATE_WITH_ITEM_TOOLTIP": "L\u00e4gg till ett f\u00f6rem\u00e5l till listan.", + "LISTS_REPEAT_HELPURL": "https://code.google.com/p/blockly/wiki/Lists#create_list_with", + "LISTS_REPEAT_TITLE": "skapa lista med f\u00f6rem\u00e5let %1 upprepat %2 g\u00e5nger", + "LISTS_LENGTH_HELPURL": "https://code.google.com/p/blockly/wiki/Lists#length_of", + "LISTS_LENGTH_TITLE": "l\u00e4ngden p\u00e5 %1", + "LISTS_IS_EMPTY_HELPURL": "https://code.google.com/p/blockly/wiki/Lists#is_empty", + "LISTS_IS_EMPTY_TITLE": "%1 \u00e4r tom", + "LISTS_INLIST": "i listan", + "LISTS_INDEX_OF_HELPURL": "https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List", + "LISTS_INDEX_OF_FIRST": "hitta f\u00f6rsta f\u00f6rekomsten av f\u00f6rem\u00e5let", + "LISTS_INDEX_OF_LAST": "hitta sista f\u00f6rekomsten av f\u00f6rem\u00e5let", + "LISTS_GET_INDEX_GET": "h\u00e4mta", + "LISTS_GET_INDEX_GET_REMOVE": "h\u00e4mta och ta bort", + "LISTS_GET_INDEX_REMOVE": "ta bort", + "LISTS_GET_INDEX_FROM_END": "# fr\u00e5n slut", + "LISTS_GET_INDEX_FIRST": "f\u00f6rsta", + "LISTS_GET_INDEX_LAST": "sista", + "LISTS_GET_INDEX_RANDOM": "slumpad", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Tar bort en slumpm\u00e4ssig post i en lista.", + "LISTS_SET_INDEX_HELPURL": "https://code.google.com/p/blockly/wiki/Lists#in_list_..._set", + "LISTS_SET_INDEX_SET": "ange", + "LISTS_SET_INDEX_INPUT_TO": "som", + "LISTS_GET_SUBLIST_HELPURL": "https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist", + "LISTS_GET_SUBLIST_END_FROM_START": "till #", + "LISTS_GET_SUBLIST_END_FROM_END": "till # fr\u00e5n slutet", + "LISTS_GET_SUBLIST_END_LAST": "till sista", + "VARIABLES_GET_HELPURL": "http://code.google.com/p/blockly/wiki/Variables#Get", + "VARIABLES_SET_HELPURL": "http://code.google.com/p/blockly/wiki/Variables#Set", + "VARIABLES_SET_TAIL": "till", + "VARIABLES_SET_CREATE_GET": "Skapa 'h\u00e4mta %1'", + "PROCEDURES_DEFNORETURN_HELPURL": "http://sv.wikipedia.org/wiki/Funktion_%28programmering%29", + "PROCEDURES_DEFNORETURN_TITLE": "till", + "PROCEDURES_DEFNORETURN_PROCEDURE": "utf\u00f6r n\u00e5gonting", + "PROCEDURES_BEFORE_PARAMS": "med:", + "PROCEDURES_DEFRETURN_HELPURL": "http://sv.wikipedia.org/wiki/Funktion_%28programmering%29", + "PROCEDURES_CALLNORETURN_HELPURL": "http://sv.wikipedia.org/wiki/Funktion_%28programmering%29", + "PROCEDURES_CALLRETURN_HELPURL": "http://sv.wikipedia.org/wiki/Funktion_%28programmering%29", + "PROCEDURES_CREATE_DO": "Skapa '%1'" +} \ No newline at end of file diff --git a/msg/json/synonyms.json b/msg/json/synonyms.json new file mode 100644 index 000000000..697aade72 --- /dev/null +++ b/msg/json/synonyms.json @@ -0,0 +1 @@ +{"PROCEDURES_DEFRETURN_TITLE": "PROCEDURES_DEFNORETURN_TITLE", "LISTS_GET_SUBLIST_INPUT_IN_LIST": "LISTS_INLIST", "LISTS_SET_INDEX_INPUT_IN_LIST": "LISTS_INLIST", "PROCEDURES_DEFRETURN_PROCEDURE": "PROCEDURES_DEFNORETURN_PROCEDURE", "VARIABLES_SET_ITEM": "VARIABLES_DEFAULT_NAME", "LISTS_CREATE_WITH_ITEM_TITLE": "VARIABLES_DEFAULT_NAME", "CONTROLS_IF_ELSE_TITLE_ELSE": "CONTROLS_IF_MSG_ELSE", "VARIABLES_GET_ITEM": "VARIABLES_DEFAULT_NAME", "PROCEDURES_DEFRETURN_DO": "PROCEDURES_DEFNORETURN_DO", "LISTS_GET_INDEX_HELPURL": "LISTS_INDEX_OF_HELPURL", "TEXT_CREATE_JOIN_ITEM_TITLE_ITEM": "VARIABLES_DEFAULT_NAME", "CONTROLS_IF_MSG_THEN": "CONTROLS_REPEAT_INPUT_DO", "LISTS_INDEX_OF_INPUT_IN_LIST": "LISTS_INLIST", "PROCEDURES_CALLRETURN_CALL": "PROCEDURES_CALLNORETURN_CALL", "LISTS_GET_INDEX_INPUT_IN_LIST": "LISTS_INLIST", "CONTROLS_IF_ELSEIF_TITLE_ELSEIF": "CONTROLS_IF_MSG_ELSEIF", "CONTROLS_FOREACH_INPUT_DO": "CONTROLS_REPEAT_INPUT_DO", "CONTROLS_IF_IF_TITLE_IF": "CONTROLS_IF_MSG_IF", "CONTROLS_WHILEUNTIL_INPUT_DO": "CONTROLS_REPEAT_INPUT_DO", "CONTROLS_FOR_INPUT_DO": "CONTROLS_REPEAT_INPUT_DO", "TEXT_APPEND_VARIABLE": "VARIABLES_DEFAULT_NAME", "MATH_CHANGE_TITLE_ITEM": "VARIABLES_DEFAULT_NAME"} \ No newline at end of file diff --git a/msg/json/uk.json b/msg/json/uk.json new file mode 100644 index 000000000..9bc6b8812 --- /dev/null +++ b/msg/json/uk.json @@ -0,0 +1,342 @@ +{ + "@metadata": { + "authors": [ + "Andriykopanytsia" + ] + }, + "VARIABLES_DEFAULT_NAME": "\u0435\u043b\u0435\u043c\u0435\u043d\u0442", + "DUPLICATE_BLOCK": "\u0414\u0443\u0431\u043b\u0456\u043a\u0430\u0442", + "ADD_COMMENT": "\u0414\u043e\u0434\u0430\u0442\u0438 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440", + "REMOVE_COMMENT": "\u0412\u0438\u0434\u0430\u043b\u0438\u0442\u0438 \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440", + "EXTERNAL_INPUTS": "\u0417\u043e\u0432\u043d\u0456\u0448\u043d\u0456 \u0432\u0445\u043e\u0434\u0438", + "INLINE_INPUTS": "\u0412\u0431\u0443\u0434\u043e\u0432\u0430\u043d\u0456 \u0432\u0445\u043e\u0434\u0438", + "DELETE_BLOCK": "\u0412\u0438\u0434\u0430\u043b\u0438\u0442\u0438 \u0431\u043b\u043e\u043a", + "DELETE_X_BLOCKS": "\u0412\u0438\u0434\u0430\u043b\u0438\u0442\u0438 %1 \u0431\u043b\u043e\u043a\u0456\u0432", + "COLLAPSE_BLOCK": "\u0417\u0433\u043e\u0440\u043d\u0443\u0442\u0438 \u0431\u043b\u043e\u043a", + "COLLAPSE_ALL": "\u0417\u0433\u043e\u0440\u043d\u0443\u0442\u0438 \u0431\u043b\u043e\u043a\u0438", + "EXPAND_BLOCK": "\u0420\u043e\u0437\u0433\u043e\u0440\u043d\u0443\u0442\u0438 \u0431\u043b\u043e\u043a", + "EXPAND_ALL": "\u0420\u043e\u0437\u0433\u043e\u0440\u043d\u0443\u0442\u0438 \u0431\u043b\u043e\u043a\u0438", + "DISABLE_BLOCK": "\u0412\u0438\u043c\u043a\u043d\u0443\u0442\u0438 \u0431\u043b\u043e\u043a", + "ENABLE_BLOCK": "\u0423\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u0431\u043b\u043e\u043a", + "HELP": "\u0414\u043e\u0432\u0456\u0434\u043a\u0430", + "CHANGE_VALUE_TITLE": "\u0417\u043c\u0456\u043d\u0438\u0442\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f:", + "NEW_VARIABLE": "\u041d\u043e\u0432\u0430 \u0437\u043c\u0456\u043d\u043d\u0430...", + "NEW_VARIABLE_TITLE": "\u041d\u043e\u0432\u0435 \u0456\u043c'\u044f \u0437\u043c\u0456\u043d\u043d\u043e\u0457:", + "RENAME_VARIABLE": "\u041f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0432\u0430\u0442\u0438 \u0437\u043c\u0456\u043d\u043d\u0443...", + "RENAME_VARIABLE_TITLE": "\u041f\u0435\u0440\u0435\u0439\u043c\u0435\u043d\u0443\u0432\u0430\u0442\u0438 \u0443\u0441\u0456 \u0437\u043c\u0456\u043d\u043d\u0456 \"%1\" \u0434\u043e:", + "COLOUR_PICKER_HELPURL": "http://uk.wikipedia.org/wiki/\u041a\u043e\u043b\u0456\u0440", + "COLOUR_PICKER_TOOLTIP": "\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u043a\u043e\u043b\u0456\u0440 \u0437 \u043f\u0430\u043b\u0456\u0442\u0440\u0438.", + "COLOUR_RANDOM_TITLE": "\u0432\u0438\u043f\u0430\u0434\u043a\u043e\u0432\u0438\u0439 \u043a\u043e\u043b\u0456\u0440", + "COLOUR_RANDOM_TOOLTIP": "\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u043a\u043e\u043b\u0456\u0440 \u043d\u0430\u0432\u043c\u0430\u043d\u043d\u044f.", + "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", + "COLOUR_RGB_TITLE": "\u043a\u043e\u043b\u0456\u0440 \u0437", + "COLOUR_RGB_RED": "\u0447\u0435\u0440\u0432\u043e\u043d\u0438\u0439", + "COLOUR_RGB_GREEN": "\u0437\u0435\u043b\u0435\u043d\u0438\u0439", + "COLOUR_RGB_BLUE": "\u0441\u0438\u043d\u0456\u0439", + "COLOUR_RGB_TOOLTIP": "\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u043a\u043e\u043b\u0456\u0440 \u0437 \u0443\u043a\u0430\u0437\u0430\u043d\u043e\u0433\u043e \u0447\u0435\u0440\u0432\u043e\u043d\u043e\u0433\u043e, \u0437\u0435\u043b\u0435\u043d\u043e\u0433\u043e \u0442\u0430 \u0441\u0438\u043d\u044c\u043e\u0433\u043e. \u0423\u0441\u0456 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043c\u0430\u044e\u0442\u044c \u0431\u0443\u0442\u0438 \u0432\u0456\u0434 0 \u0434\u043e 100.", + "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", + "COLOUR_BLEND_TITLE": "\u0441\u0443\u043c\u0456\u0448", + "COLOUR_BLEND_COLOUR1": "\u043a\u043e\u043b\u0456\u0440 1", + "COLOUR_BLEND_COLOUR2": "\u043a\u043e\u043b\u0456\u0440 2", + "COLOUR_BLEND_RATIO": "\u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f", + "COLOUR_BLEND_TOOLTIP": "\u0417\u043c\u0456\u0448\u0443\u0454 \u0434\u0432\u0456 \u0431\u0430\u0440\u0432\u0438 \u0440\u0430\u0437\u043e\u043c \u0437 \u0434\u0430\u043d\u0438\u043c \u0441\u043f\u0456\u0432\u0432\u0456\u0434\u043d\u043e\u0448\u0435\u043d\u043d\u044f\u043c (0.0 - 1.0).", + "CONTROLS_REPEAT_HELPURL": "http://en.Wikipedia.org/Wiki/For_loop", + "CONTROLS_REPEAT_TITLE": "\u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0438 %1 \u0440\u0430\u0437\u0456\u0432", + "CONTROLS_REPEAT_TITLE_REPEAT": "\u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0438", + "CONTROLS_REPEAT_TITLE_TIMES": "\u0440\u0430\u0437\u0456\u0432", + "CONTROLS_REPEAT_INPUT_DO": "\u0437\u0440\u043e\u0431\u0438\u0442\u0438", + "CONTROLS_REPEAT_TOOLTIP": "\u0417\u0440\u043e\u0431\u0438\u0442\u0438 \u0434\u0435\u044f\u043a\u0456 \u0437\u0430\u044f\u0432\u0438 \u043a\u0456\u043b\u044c\u043a\u0430 \u0440\u0430\u0437\u0456\u0432.", + "CONTROLS_WHILEUNTIL_HELPURL": "http://code.google.com/p/blockly/wiki/Repeat", + "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "\u043f\u043e\u0432\u0442\u043e\u0440\u044e\u0432\u0430\u0442\u0438 \u043f\u043e\u043a\u0438", + "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "\u043f\u043e\u0432\u0442\u043e\u0440\u044e\u0432\u0430\u0442\u0438 \u0434\u043e\u043a\u0438", + "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "\u041f\u043e\u043a\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f true, \u0437\u0440\u043e\u0431\u0438\u0442\u0438 \u0434\u0435\u044f\u043a\u0456 \u0437\u0430\u044f\u0432\u0438.", + "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "\u041f\u043e\u043a\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f false, \u0437\u0440\u043e\u0431\u0438\u0442\u0438 \u0434\u0435\u044f\u043a\u0456 \u0437\u0430\u044f\u0432\u0438.", + "CONTROLS_FOR_HELPURL": "https://code.google.com/p/blockly/wiki/Loops#count_with", + "CONTROLS_FOR_TOOLTIP": "\u041d\u0430\u044f\u0432\u043d\u0430 \u0437\u043c\u0456\u043d\u043d\u0430 %1 \u043f\u0440\u0438\u0439\u043c\u0430\u0454 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0432\u0456\u0434 \u043f\u043e\u0447\u0430\u0442\u043a\u043e\u0432\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0434\u043e \u043a\u0456\u043d\u0446\u0435\u0432\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f, \u0432\u0440\u0430\u0445\u043e\u0432\u0443\u044e\u0447\u0438 \u0437\u0430\u0434\u0430\u043d\u0438\u0439 \u0456\u043d\u0442\u0435\u0440\u0432\u0430\u043b, \u0456 \u0437\u0440\u043e\u0431\u0456\u0442\u044c \u0432\u043a\u0430\u0437\u0430\u043d\u0456 \u0431\u043b\u043e\u043a\u0438.", + "CONTROLS_FOR_INPUT_WITH": "\u0440\u0430\u0445\u0443\u0432\u0430\u0442\u0438 \u0437", + "CONTROLS_FOR_INPUT_FROM_TO_BY": "\u0432\u0456\u0434 %1 \u0434\u043e %2 \u0447\u0435\u0440\u0435\u0437 %3", + "CONTROLS_FOREACH_HELPURL": "https://code.google.com/p/blockly/wiki/Loops#for_each for each block", + "CONTROLS_FOREACH_INPUT_ITEM": "\u0434\u043b\u044f \u043a\u043e\u0436\u043d\u043e\u0433\u043e \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0430", + "CONTROLS_FOREACH_INPUT_INLIST": "\u0443 \u0441\u043f\u0438\u0441\u043a\u0443", + "CONTROLS_FOREACH_INPUT_INLIST_TAIL": "\u0431\u043b\u043e\u043a \u0442\u0435\u043a\u0441\u0442\u0443", + "CONTROLS_FOREACH_TOOLTIP": "\u0414\u043b\u044f \u043a\u043e\u0436\u043d\u043e\u0433\u043e \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0432 \u0441\u043f\u0438\u0441\u043a\u0443 \u0437\u0430\u0434\u0430\u0439\u0442\u0435 \u0437\u043c\u0456\u043d\u043d\u0443 '%1' \u0434\u043b\u044f \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0430, \u0430 \u043f\u043e\u0442\u0456\u043c \u0437\u0440\u043e\u0431\u0456\u0442\u044c \u0434\u0435\u044f\u043a\u0456 \u0437\u0430\u044f\u0432\u0438.", + "CONTROLS_FLOW_STATEMENTS_HELPURL": "https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "\u043f\u0435\u0440\u0435\u0440\u0432\u0430\u0442\u0438 \u0446\u0438\u043a\u043b", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "\u043f\u0440\u043e\u0434\u043e\u0432\u0436\u0438\u0442\u0438 \u0437 \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u043e\u0457 \u0456\u0442\u0435\u0440\u0430\u0446\u0456\u0457 \u0446\u0438\u043a\u043b\u0443", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "\u0412\u0438\u0440\u0432\u0430\u0442\u0438\u0441\u044f \u0437 \u0446\u0438\u043a\u043b\u0456\u0447\u043d\u0438\u0445 \u043e\u0442\u043e\u0447\u0435\u043d\u044c.", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "\u041f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u0437\u0430\u043b\u0438\u0448\u043e\u043a \u0446\u044c\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0443 \u0456 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0434\u043e \u0432\u0438\u043a\u043e\u043d\u0430\u043d\u043d\u044f \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u043e\u0457 \u0456\u0442\u0435\u0440\u0430\u0446\u0456\u0457.", + "CONTROLS_FLOW_STATEMENTS_WARNING": "\u041f\u043e\u043f\u0435\u0440\u0435\u0434\u0436\u0435\u043d\u043d\u044f: \u0446\u0435\u0439 \u0431\u043b\u043e\u043a \u043c\u043e\u0436\u0435 \u0431\u0443\u0442\u0438 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u0430\u043d\u0438\u0439 \u0442\u0456\u043b\u044c\u043a\u0438 \u0432 \u043c\u0435\u0436\u0430\u0445 \u0446\u0438\u043a\u043b\u0443.", + "CONTROLS_IF_HELPURL": "http://code.google.com/p/blockly/wiki/If_Then", + "CONTROLS_IF_TOOLTIP_1": "\u042f\u043a\u0449\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f true, \u0437\u0440\u043e\u0431\u0438\u0442\u0438 \u0434\u0435\u044f\u043a\u0456 \u0437\u0430\u044f\u0432\u0438.", + "CONTROLS_IF_TOOLTIP_2": "\u042f\u043a\u0449\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0456\u0441\u0442\u0438\u043d\u0430, \u0442\u043e \u0432\u0438\u043a\u043e\u043d\u0443\u0454\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0448\u0438\u0439 \u0431\u043b\u043e\u043a \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0456\u0432. \u0412 \u0456\u043d\u0448\u043e\u043c\u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443 \u0432\u0438\u043a\u043e\u043d\u0443\u0454\u0442\u044c\u0441\u044f \u0434\u0440\u0443\u0433\u0438\u0439 \u0431\u043b\u043e\u043a \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0456\u0432.", + "CONTROLS_IF_TOOLTIP_3": "\u042f\u043a\u0449\u043e \u043f\u0435\u0440\u0448\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0456\u0441\u0442\u0438\u043d\u0430, \u0442\u043e \u0432\u0438\u043a\u043e\u043d\u0443\u0454\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0448\u0438\u0439 \u0431\u043b\u043e\u043a \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0456\u0432. \u0412 \u0456\u043d\u0448\u043e\u043c\u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443, \u044f\u043a\u0449\u043e \u0434\u0440\u0443\u0433\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0456\u0441\u0442\u0438\u043d\u0430, \u0442\u043e \u0432\u0438\u043a\u043e\u043d\u0443\u0454\u0442\u044c\u0441\u044f \u0434\u0440\u0443\u0433\u0438\u0439 \u0431\u043b\u043e\u043a \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0456\u0432.", + "CONTROLS_IF_TOOLTIP_4": "\u042f\u043a\u0449\u043e \u043f\u0435\u0440\u0448\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0456\u0441\u0442\u0438\u043d\u0430, \u0442\u043e \u0432\u0438\u043a\u043e\u043d\u0443\u0454\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0448\u0438\u0439 \u0431\u043b\u043e\u043a \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0456\u0432. \u0412 \u0456\u043d\u0448\u043e\u043c\u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443, \u044f\u043a\u0449\u043e \u0434\u0440\u0443\u0433\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0456\u0441\u0442\u0438\u043d\u0430, \u0442\u043e \u0432\u0438\u043a\u043e\u043d\u0443\u0454\u0442\u044c\u0441\u044f \u0434\u0440\u0443\u0433\u0438\u0439 \u0431\u043b\u043e\u043a \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0456\u0432. \u042f\u043a\u0449\u043e \u0436\u043e\u0434\u043d\u0435 \u0456\u0437 \u0437\u043d\u0430\u0447\u0435\u043d\u044c \u043d\u0435 \u0454 \u0456\u0441\u0442\u0438\u043d\u043d\u0438\u043c, \u0442\u043e \u0432\u0438\u043a\u043e\u043d\u0443\u0454\u0442\u044c\u0441\u044f \u043e\u0441\u0442\u0430\u043d\u043d\u0456\u0439 \u0431\u043b\u043e\u043a \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0456\u0432.", + "CONTROLS_IF_MSG_IF": "\u044f\u043a\u0449\u043e", + "CONTROLS_IF_MSG_ELSEIF": "\u0406\u043d\u0430\u043a\u0448\u0435 \u044f\u043a\u0449\u043e", + "CONTROLS_IF_MSG_ELSE": "\u0456\u043d\u0430\u043a\u0448\u0435", + "CONTROLS_IF_IF_TOOLTIP": "\u0414\u043e\u0434\u0430\u0442\u0438, \u0432\u0438\u0434\u0430\u043b\u0438\u0442\u0438 \u0430\u0431\u043e \u0437\u043c\u0456\u043d\u0438\u0442\u0438 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0440\u043e\u0437\u0434\u0456\u043b\u0456\u0432 \u043f\u0435\u0440\u0435\u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u0442\u0438 \u0446\u0435, \u044f\u043a\u0449\u043e \u0431\u043b\u043e\u043a\u0443\u0454\u0442\u044c\u0441\u044f.", + "CONTROLS_IF_ELSEIF_TOOLTIP": "\u0414\u043e\u0434\u0430\u0442\u0438 \u0443\u043c\u043e\u0432\u0443 \u0434\u043e \u044f\u043a\u0449\u043e \u0431\u043b\u043e\u043a\u0443\u0432\u0430\u0442\u0438.", + "CONTROLS_IF_ELSE_TOOLTIP": "\u0414\u043e\u0434\u0430\u0442\u0438 \u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u0443, \u0432\u0441\u0435\u043e\u0441\u044f\u0436\u043d\u0443 \u0443\u043c\u043e\u0432\u0430 \u0434\u043e \u0431\u043b\u043e\u043a\u0443 \u044f\u043a\u0449\u043e.", + "LOGIC_COMPARE_HELPURL": "http://uk.wikipedia.org/wiki/\u041d\u0435\u0440\u0456\u0432\u043d\u0456\u0441\u0442\u044c", + "LOGIC_COMPARE_TOOLTIP_EQ": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 true, \u044f\u043a\u0449\u043e \u043e\u0431\u0438\u0434\u0432\u0430 \u0432\u0445\u043e\u0434\u0438 \u0440\u0456\u0432\u043d\u0456 \u043e\u0434\u0438\u043d \u043e\u0434\u043d\u043e\u043c\u0443.", + "LOGIC_COMPARE_TOOLTIP_NEQ": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 true, \u044f\u043a\u0449\u043e \u043e\u0431\u0438\u0434\u0432\u0430 \u0432\u0445\u043e\u0434\u0438 \u043d\u0435 \u0434\u043e\u0440\u0456\u0432\u043d\u044e\u044e\u0442\u044c \u043e\u0434\u0438\u043d \u043e\u0434\u043d\u043e\u043c\u0443.", + "LOGIC_COMPARE_TOOLTIP_LT": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 true, \u044f\u043a\u0449\u043e \u043f\u0435\u0440\u0448\u0435 \u0432\u0445\u0456\u0434\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043c\u0435\u043d\u0448\u0435, \u043d\u0456\u0436 \u0434\u0440\u0443\u0433\u0438\u0439 \u0432\u0445\u0456\u0434.", + "LOGIC_COMPARE_TOOLTIP_LTE": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 true, \u044f\u043a\u0449\u043e \u043f\u0435\u0440\u0448\u0435 \u0432\u0445\u0456\u0434\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043c\u0435\u043d\u0448\u0435 \u0430\u0431\u043e \u0434\u043e\u0440\u0456\u0432\u043d\u044e\u0454 \u0434\u0440\u0443\u0433\u043e\u043c\u0443 \u0432\u0445\u043e\u0434\u0443.", + "LOGIC_COMPARE_TOOLTIP_GT": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 true, \u044f\u043a\u0449\u043e \u043f\u0435\u0440\u0448\u0435 \u0432\u0445\u0456\u0434\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0431\u0456\u043b\u044c\u0448\u0435, \u043d\u0456\u0436 \u0434\u0440\u0443\u0433\u0438\u0439 \u0432\u0445\u0456\u0434.", + "LOGIC_COMPARE_TOOLTIP_GTE": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 true, \u044f\u043a\u0449\u043e \u043f\u0435\u0440\u0448\u0435 \u0432\u0445\u0456\u0434\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0431\u0456\u043b\u044c\u0448\u0435 \u0430\u0431\u043e \u0434\u043e\u0440\u0456\u0432\u043d\u044e\u0454 \u0434\u0440\u0443\u0433\u043e\u043c\u0443 \u0432\u0445\u043e\u0434\u0443.", + "LOGIC_OPERATION_HELPURL": "http://code.google.com/p/blockly/wiki/And_Or", + "LOGIC_OPERATION_TOOLTIP_AND": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 true, \u044f\u043a\u0449\u043e \u043e\u0431\u0438\u0434\u0432\u0430 \u0432\u0445\u043e\u0434\u0438 \u0456\u0441\u0442\u0438\u043d\u043d\u0456.", + "LOGIC_OPERATION_AND": "\u0442\u0430", + "LOGIC_OPERATION_TOOLTIP_OR": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 true, \u044f\u043a\u0449\u043e \u043f\u0440\u0438\u043d\u0430\u0439\u043c\u043d\u0456 \u043e\u0434\u0438\u043d \u0437 \u0432\u0445\u043e\u0434\u0456\u0432 true.", + "LOGIC_OPERATION_OR": "\u0430\u0431\u043e", + "LOGIC_NEGATE_HELPURL": "http://code.google.com/p/blockly/wiki/Not", + "LOGIC_NEGATE_TITLE": "\u043d\u0435 %1", + "LOGIC_NEGATE_TOOLTIP": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0456\u0441\u0442\u0438\u043d\u0430, \u044f\u043a\u0449\u043e \u0432\u0445\u0456\u0434\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0445\u0438\u0431\u043d\u0456\u0441\u0442\u044c. \u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0445\u0438\u0431\u043d\u0456\u0441\u0442\u044c, \u044f\u043a\u0449\u043e \u0432\u0445\u0456\u0434\u043d\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0456\u0441\u0442\u0438\u043d\u0430.", + "LOGIC_BOOLEAN_HELPURL": "http://code.google.com/p/blockly/wiki/True_False", + "LOGIC_BOOLEAN_TRUE": "\u0456\u0441\u0442\u0438\u043d\u0430", + "LOGIC_BOOLEAN_FALSE": "\u0445\u0438\u0431\u043d\u0456\u0441\u0442\u044c", + "LOGIC_BOOLEAN_TOOLTIP": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0406\u0421\u0422\u0418\u041d\u0410 \u0430\u0431\u043e \u0425\u0418\u0411\u041d\u0406\u0421\u0422\u042c.", + "LOGIC_NULL_HELPURL": "http://en.wikipedia.org/wiki/Nullable_type", + "LOGIC_NULL": "\u043d\u0456\u0447\u043e\u0433\u043e", + "LOGIC_NULL_TOOLTIP": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 null.", + "LOGIC_TERNARY_HELPURL": "http://en.wikipedia.org/wiki/%3F:", + "LOGIC_TERNARY_CONDITION": "\u0442\u0435\u0441\u0442", + "LOGIC_TERNARY_IF_TRUE": "\u044f\u043a\u0449\u043e \u0456\u0441\u0442\u0438\u043d\u0430", + "LOGIC_TERNARY_IF_FALSE": "\u042f\u043a\u0449\u043e \u0445\u0438\u0431\u043d\u0456\u0441\u0442\u044c", + "LOGIC_TERNARY_TOOLTIP": "\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u0443\u043c\u043e\u0432\u0443 \u0432 'test'. \u042f\u043a\u0449\u043e \u0443\u043c\u043e\u0432\u0430 \u0456\u0441\u0442\u0438\u043d\u043d\u0430, \u0442\u043e \u043f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0442\u0438\u043f\u0443 '\u044f\u043a\u0449\u043e \u0456\u0441\u0442\u0438\u043d\u0430'; \u0432 \u0456\u043d\u0448\u043e\u043c\u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443 \u043f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f '\u044f\u043a\u0449\u043e \u0445\u0438\u0431\u043d\u0456\u0441\u0442\u044c'.", + "MATH_NUMBER_HELPURL": "http://uk.wikipedia.org/wiki/\u0427\u0438\u0441\u043b\u043e", + "MATH_NUMBER_TOOLTIP": "\u0427\u0438\u0441\u043b\u043e.", + "MATH_ARITHMETIC_HELPURL": "http://uk.wikipedia.org/wiki/\u0410\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u043a\u0430", + "MATH_ARITHMETIC_TOOLTIP_ADD": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0441\u0443\u043c\u0443 \u0434\u0432\u043e\u0445 \u0447\u0438\u0441\u0435\u043b.", + "MATH_ARITHMETIC_TOOLTIP_MINUS": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0440\u0456\u0437\u043d\u0438\u0446\u044e \u0434\u0432\u043e\u0445 \u0447\u0438\u0441\u0435\u043b.", + "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0434\u043e\u0431\u0443\u0442\u043e\u043a \u0434\u0432\u043e\u0445 \u0447\u0438\u0441\u0435\u043b.", + "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0447\u0430\u0441\u0442\u043a\u0443 \u0434\u0432\u043e\u0445 \u0447\u0438\u0441\u0435\u043b.", + "MATH_ARITHMETIC_TOOLTIP_POWER": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u043f\u0435\u0440\u0448\u0435 \u0447\u0438\u0441\u043b\u043e, \u043f\u0456\u0434\u043d\u0435\u0441\u0435\u043d\u0435 \u0434\u043e \u0441\u0442\u0435\u043f\u0435\u043d\u044f \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430.", + "MATH_SINGLE_HELPURL": "http://uk.wikipedia.org/wiki/\u041a\u0432\u0430\u0434\u0440\u0430\u0442\u043d\u0438\u0439_\u043a\u043e\u0440\u0456\u043d\u044c", + "MATH_SINGLE_OP_ROOT": "\u043a\u0432\u0430\u0434\u0440\u0430\u0442\u043d\u0438\u0439 \u043a\u043e\u0440\u0456\u043d\u044c", + "MATH_SINGLE_TOOLTIP_ROOT": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u043d\u0438\u0439 \u043a\u043e\u0440\u0456\u043d\u044c \u0447\u0438\u0441\u043b\u0430.", + "MATH_SINGLE_OP_ABSOLUTE": "\u043c\u043e\u0434\u0443\u043b\u044c", + "MATH_SINGLE_TOOLTIP_ABS": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u043c\u043e\u0434\u0443\u043b\u044c \u0447\u0438\u0441\u043b\u0430.", + "MATH_SINGLE_TOOLTIP_NEG": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u043f\u0440\u043e\u0442\u0438\u043b\u0435\u0436\u043d\u0435 \u0447\u0438\u0441\u043b\u043e.", + "MATH_SINGLE_TOOLTIP_LN": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u043d\u0430\u0442\u0443\u0440\u0430\u043b\u044c\u043d\u0438\u0439 \u043b\u043e\u0433\u0430\u0440\u0438\u0444\u043c \u0447\u0438\u0441\u043b\u0430.", + "MATH_SINGLE_TOOLTIP_LOG10": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0434\u0435\u0441\u044f\u0442\u043a\u043e\u0432\u0438\u0439 \u043b\u043e\u0433\u0430\u0440\u0438\u0444\u043c \u0447\u0438\u0441\u043b\u0430.", + "MATH_SINGLE_TOOLTIP_EXP": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 e \u0443 \u0441\u0442\u0435\u043f\u0435\u043d\u0456.", + "MATH_SINGLE_TOOLTIP_POW10": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 10 \u0443 \u0441\u0442\u0435\u043f\u0435\u043d\u0456.", + "MATH_TRIG_HELPURL": "http://uk.wikipedia.org/wiki/\u0422\u0440\u0438\u0433\u043e\u043d\u043e\u043c\u0435\u0442\u0440\u0438\u0447\u043d\u0456_\u0444\u0443\u043d\u043a\u0446\u0456\u0457", + "MATH_TRIG_TOOLTIP_SIN": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0441\u0438\u043d\u0443\u0441 \u043a\u0443\u0442\u0430 \u0443 \u0433\u0440\u0430\u0434\u0443\u0441\u0430\u0445 (\u043d\u0435 \u0443 \u0440\u0430\u0434\u0456\u0430\u043d\u0430\u0445).", + "MATH_TRIG_TOOLTIP_COS": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u043a\u043e\u0441\u0438\u043d\u0443\u0441 \u043a\u0443\u0442\u0430 \u0443 \u0433\u0440\u0430\u0434\u0443\u0441\u0430\u0445 (\u043d\u0435 \u0443 \u0440\u0430\u0434\u0456\u0430\u043d\u0430\u0445).", + "MATH_TRIG_TOOLTIP_TAN": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0442\u0430\u043d\u0433\u0435\u043d\u0441 \u043a\u0443\u0442\u0430 \u0443 \u0433\u0440\u0430\u0434\u0443\u0441\u0430\u0445 (\u043d\u0435 \u0443 \u0440\u0430\u0434\u0456\u0430\u043d\u0430\u0445).", + "MATH_TRIG_TOOLTIP_ASIN": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0430\u0440\u043a\u0441\u0438\u043d\u0443\u0441 \u0447\u0438\u0441\u043b\u0430.", + "MATH_TRIG_TOOLTIP_ACOS": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0430\u0440\u043a\u043a\u043e\u0441\u0438\u043d\u0443\u0441 \u0447\u0438\u0441\u043b\u0430.", + "MATH_TRIG_TOOLTIP_ATAN": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0430\u0440\u043a\u0442\u0430\u043d\u0433\u0435\u043d\u0441 \u0447\u0438\u0441\u043b\u0430.", + "MATH_CONSTANT_HELPURL": "http://uk.wikipedia.org/wiki/\u041c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u043d\u0430_\u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430", + "MATH_CONSTANT_TOOLTIP": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u043e\u0434\u043d\u0443 \u0437 \u043f\u043e\u0448\u0438\u0440\u0435\u043d\u0438\u0445 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442: \u03c0 (3.141...), e (2.718...), \u03c6 (1,618...), sqrt(2) (1.414...), sqrt(\u00bd) (0.707...) \u0430\u0431\u043e \u221e (\u0431\u0435\u0437\u043c\u0435\u0436\u043d\u0456\u0441\u0442\u044c).", + "MATH_IS_EVEN": "\u043f\u0430\u0440\u043d\u0435", + "MATH_IS_ODD": "\u043d\u0435\u043f\u0430\u0440\u043d\u0435", + "MATH_IS_PRIME": "\u043f\u0440\u043e\u0441\u0442\u0435", + "MATH_IS_WHOLE": "\u0446\u0456\u043b\u0435", + "MATH_IS_POSITIVE": "\u0434\u043e\u0434\u0430\u0442\u043d\u0435", + "MATH_IS_NEGATIVE": "\u0432\u0456\u0434'\u0454\u043c\u043d\u0435", + "MATH_IS_DIVISIBLE_BY": "\u0434\u0456\u043b\u0438\u0442\u044c\u0441\u044f \u043d\u0430", + "MATH_IS_TOOLTIP": "\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u044f\u0454, \u0447\u0438 \u0447\u0438\u0441\u043b\u043e \u043f\u0430\u0440\u043d\u0435, \u043d\u0435\u043f\u0430\u0440\u043d\u0435, \u043f\u0440\u043e\u0441\u0442\u0435, \u0446\u0456\u043b\u0435, \u0434\u043e\u0434\u0430\u0442\u043d\u0435, \u0432\u0456\u0434'\u0454\u043c\u043d\u0435 \u0430\u0431\u043e \u0447\u0438 \u0432\u043e\u043d\u043e \u0434\u0456\u043b\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u043f\u0435\u0432\u043d\u0435 \u0447\u0438\u0441\u043b\u043e \u0431\u0435\u0437 \u043e\u0441\u0442\u0430\u0447\u0456. \u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0456\u0441\u0442\u0438\u043d\u0430 \u0430\u0431\u043e \u0445\u0438\u0431\u043d\u0456\u0441\u0442\u044c.", + "MATH_CHANGE_HELPURL": "http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", + "MATH_CHANGE_TITLE_CHANGE": "\u0437\u043c\u0456\u043d\u0438\u0442\u0438", + "MATH_CHANGE_INPUT_BY": "\u0432\u0456\u0434", + "MATH_CHANGE_TOOLTIP": "\u0414\u043e\u0434\u0430\u0442\u0438 \u0447\u0438\u0441\u043b\u043e \u0437\u043c\u0456\u043d\u043d\u0456\u0439 '%1'.", + "MATH_ROUND_HELPURL": "http://en.wikipedia.org/wiki/Rounding", + "MATH_ROUND_TOOLTIP": "\u041e\u043a\u0440\u0443\u0433\u043b\u0435\u043d\u043d\u044f \u0447\u0438\u0441\u043b\u0430 \u0443 \u0431\u0456\u043b\u044c\u0448\u0443 \u0430\u0431\u043e \u043c\u0435\u043d\u0448\u0443 \u0441\u0442\u043e\u0440\u043e\u043d\u0443.", + "MATH_ROUND_OPERATOR_ROUND": "\u043e\u043a\u0440\u0443\u0433\u043b\u0438\u0442\u0438", + "MATH_ROUND_OPERATOR_ROUNDUP": "\u043e\u043a\u0440\u0443\u0433\u043b\u0438\u0442\u0438 \u0443 \u0431\u0456\u043b\u044c\u0448\u0443 \u0441\u0442\u043e\u0440\u043e\u043d\u0443", + "MATH_ROUND_OPERATOR_ROUNDDOWN": "\u043e\u043a\u0440\u0443\u0433\u043b\u0438\u0442\u0438 \u0443 \u043c\u0435\u043d\u0448\u0443 \u0441\u0442\u043e\u0440\u043e\u043d\u0443", + "MATH_ONLIST_HELPURL": "http://www.mapleprimes.com/questions/100441-Applying-Function-To-List-Of-Numbers", + "MATH_ONLIST_OPERATOR_SUM": "\u0441\u0443\u043c\u0430 \u0441\u043f\u0438\u0441\u043a\u0443", + "MATH_ONLIST_TOOLTIP_SUM": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0441\u0443\u043c\u0443 \u0432\u0441\u0456\u0445 \u0447\u0438\u0441\u0435\u043b \u0443 \u0441\u043f\u0438\u0441\u043a\u0443.", + "MATH_ONLIST_OPERATOR_MIN": "\u043c\u0456\u043d\u0456\u043c\u0443\u043c \u0441\u043f\u0438\u0441\u043a\u0443", + "MATH_ONLIST_TOOLTIP_MIN": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u043d\u0430\u0439\u043c\u0435\u043d\u0448\u0435 \u0447\u0438\u0441\u043b\u043e \u0443 \u0441\u043f\u0438\u0441\u043a\u0443.", + "MATH_ONLIST_OPERATOR_MAX": "\u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u0441\u043f\u0438\u0441\u043a\u0443", + "MATH_ONLIST_TOOLTIP_MAX": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u043d\u0430\u0439\u0431\u0456\u043b\u044c\u0448\u0435 \u0447\u0438\u0441\u043b\u043e \u0443 \u0441\u043f\u0438\u0441\u043a\u0443.", + "MATH_ONLIST_OPERATOR_AVERAGE": "\u0441\u0435\u0440\u0435\u0434\u043d\u0454 \u0441\u043f\u0438\u0441\u043a\u0443", + "MATH_ONLIST_TOOLTIP_AVERAGE": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0441\u0435\u0440\u0435\u0434\u043d\u0454 (\u0430\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u0447\u043d\u0435) \u0447\u0438\u0441\u043b\u043e\u0432\u0438\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u044c \u0443 \u0441\u043f\u0438\u0441\u043a\u0443.", + "MATH_ONLIST_OPERATOR_MEDIAN": "\u043c\u0435\u0434\u0456\u0430\u043d\u0430 \u0441\u043f\u0438\u0441\u043a\u0443", + "MATH_ONLIST_TOOLTIP_MEDIAN": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u043c\u0435\u0434\u0456\u0430\u043d\u0443 \u0441\u043f\u0438\u0441\u043a\u0443.", + "MATH_ONLIST_OPERATOR_MODE": "\u043c\u043e\u0434\u0438 \u0441\u043f\u0438\u0441\u043a\u0443", + "MATH_ONLIST_TOOLTIP_MODE": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u043f\u0435\u0440\u0435\u043b\u0456\u043a \u043d\u0430\u0439\u043f\u043e\u0448\u0438\u0440\u0435\u043d\u0456\u0448\u0438\u0445 \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0456\u0432 \u0443 \u0441\u043f\u0438\u0441\u043a\u0443.", + "MATH_ONLIST_OPERATOR_STD_DEV": "\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0435 \u0432\u0456\u0434\u0445\u0438\u043b\u0435\u043d\u043d\u044f \u0441\u043f\u0438\u0441\u043a\u0443", + "MATH_ONLIST_TOOLTIP_STD_DEV": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0435 \u0432\u0456\u0434\u0445\u0438\u043b\u0435\u043d\u043d\u044f \u0441\u043f\u0438\u0441\u043a\u0443.", + "MATH_ONLIST_OPERATOR_RANDOM": "\u0432\u0438\u043f\u0430\u0434\u043a\u043e\u0432\u0438\u0439 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u043f\u0438\u0441\u043a\u0443", + "MATH_ONLIST_TOOLTIP_RANDOM": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0432\u0438\u043f\u0430\u0434\u043a\u043e\u0432\u0438\u0439 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0437\u0456 \u0441\u043f\u0438\u0441\u043a\u0443.", + "MATH_MODULO_HELPURL": "http://uk.wikipedia.org/wiki/\u0414\u0456\u043b\u0435\u043d\u043d\u044f_\u0437_\u043e\u0441\u0442\u0430\u0447\u0435\u044e", + "MATH_MODULO_TITLE": "\u043e\u0441\u0442\u0430\u0447\u0430 \u0432\u0456\u0434 %1 \u00f7 %2", + "MATH_MODULO_TOOLTIP": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u043e\u0441\u0442\u0430\u0447\u0443 \u0432\u0456\u0434 \u0434\u0456\u043b\u0435\u043d\u043d\u044f \u0434\u0432\u043e\u0445 \u0447\u0438\u0441\u0435\u043b.", + "MATH_CONSTRAIN_HELPURL": "http://en.wikipedia.org/wiki/Clamping_%28graphics%29", + "MATH_CONSTRAIN_TITLE": "\u043e\u0431\u043c\u0435\u0436\u0438\u0442\u0438 %1 \u0432\u0456\u0434 %2 \u0434\u043e %3", + "MATH_CONSTRAIN_TOOLTIP": "\u041e\u0431\u043c\u0435\u0436\u0443\u0454 \u0447\u0438\u0441\u043b\u043e \u0432\u043a\u0430\u0437\u0430\u043d\u0438\u043c\u0438 \u043c\u0435\u0436\u0430\u043c\u0438 (\u0432\u043a\u043b\u044e\u0447\u043d\u043e).", + "MATH_RANDOM_INT_HELPURL": "http://uk.wikipedia.org/wiki/\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0456\u044f_\u0432\u0438\u043f\u0430\u0434\u043a\u043e\u0432\u0438\u0445_\u0447\u0438\u0441\u0435\u043b", + "MATH_RANDOM_INT_TITLE": "\u0432\u0438\u043f\u0430\u0434\u043a\u043e\u0432\u0435 \u0446\u0456\u043b\u0435 \u0447\u0438\u0441\u043b\u043e \u0432\u0456\u0434 %1 \u0434\u043e %2", + "MATH_RANDOM_INT_TOOLTIP": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0432\u0438\u043f\u0430\u0434\u043a\u043e\u0432\u0435 \u0446\u0456\u043b\u0435 \u0447\u0438\u0441\u043b\u043e \u043c\u0456\u0436 \u0434\u0432\u043e\u043c\u0430 \u0437\u0430\u0434\u0430\u043d\u0438\u043c\u0438 \u043c\u0435\u0436\u0430\u043c\u0438 \u0432\u043a\u043b\u044e\u0447\u043d\u043e.", + "MATH_RANDOM_FLOAT_HELPURL": "http://uk.wikipedia.org/wiki/\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0456\u044f_\u0432\u0438\u043f\u0430\u0434\u043a\u043e\u0432\u0438\u0445_\u0447\u0438\u0441\u0435\u043b", + "MATH_RANDOM_FLOAT_TITLE_RANDOM": "\u0432\u0438\u043f\u0430\u0434\u043a\u043e\u0432\u0438\u0439 \u0434\u0440\u0456\u0431", + "MATH_RANDOM_FLOAT_TOOLTIP": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0432\u0438\u043f\u0430\u0434\u043a\u043e\u0432\u0438\u0439 \u0434\u0440\u0456\u0431 \u0432\u0456\u0434 0,0 (\u0432\u043a\u043b\u044e\u0447\u043d\u043e) \u0442\u0430 1.0 (\u043d\u0435 \u0432\u043a\u043b\u044e\u0447\u043d\u043e).", + "TEXT_TEXT_HELPURL": "http://uk.wikipedia.org/wiki/\u0420\u044f\u0434\u043e\u043a_(\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0443\u0432\u0430\u043d\u043d\u044f)", + "TEXT_TEXT_TOOLTIP": "\u0421\u0438\u043c\u0432\u043e\u043b, \u0441\u043b\u043e\u0432\u043e \u0430\u0431\u043e \u0440\u044f\u0434\u043e\u043a \u0442\u0435\u043a\u0441\u0442\u0443.", + "TEXT_JOIN_HELPURL": "http://www.chemie.fu-berlin.de/chemnet/use/info/make/make_8.html", + "TEXT_JOIN_TITLE_CREATEWITH": "\u0441\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0442\u0435\u043a\u0441\u0442 \u0437", + "TEXT_JOIN_TOOLTIP": "\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u0442\u0435\u043a\u0441\u0442\u0443 \u0448\u043b\u044f\u0445\u043e\u043c \u043f\u0440\u0438\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u0431\u0443\u0434\u044c-\u044f\u043a\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0456\u0432.", + "TEXT_CREATE_JOIN_TITLE_JOIN": "\u043f\u0440\u0438\u0454\u0434\u043d\u0430\u0442\u0438", + "TEXT_CREATE_JOIN_TOOLTIP": "\u0414\u043e\u0434\u0430\u0442\u0438, \u0432\u0438\u0434\u0430\u043b\u0438\u0442\u0438 \u0430\u0431\u043e \u0437\u043c\u0456\u043d\u0438\u0442\u0438 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0440\u043e\u0437\u0434\u0456\u043b\u0456\u0432 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0431\u043b\u043e\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u0442\u0435\u043a\u0441\u0442\u0443.", + "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "\u0414\u043e\u0434\u0430\u0442\u0438 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0434\u043e \u0442\u0435\u043a\u0441\u0442\u0443.", + "TEXT_APPEND_HELPURL": "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html", + "TEXT_APPEND_TO": "\u0434\u043e", + "TEXT_APPEND_APPENDTEXT": "\u0434\u043e\u0434\u0430\u0442\u0438 \u0442\u0435\u043a\u0441\u0442", + "TEXT_APPEND_TOOLTIP": "\u0414\u043e\u0434\u0430\u0442\u0438 \u044f\u043a\u0438\u0439-\u043d\u0435\u0431\u0443\u0434\u044c \u0442\u0435\u043a\u0441\u0442 \u0437\u043c\u0456\u043d\u043d\u0456\u0439 '%1'.", + "TEXT_LENGTH_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Text_modification", + "TEXT_LENGTH_TITLE": "\u0434\u043e\u0432\u0436\u0438\u043d\u0430 %1", + "TEXT_LENGTH_TOOLTIP": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0447\u0438\u0441\u043b\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u0456\u0432 (\u0432\u043a\u043b\u044e\u0447\u0430\u044e\u0447\u0438 \u043f\u0440\u043e\u0431\u0456\u043b\u0438) \u0443 \u0434\u0430\u043d\u043e\u043c\u0443 \u0442\u0435\u043a\u0441\u0442\u0456.", + "TEXT_ISEMPTY_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text", + "TEXT_ISEMPTY_TITLE": "%1 \u0454 \u043f\u043e\u0440\u043e\u0436\u043d\u0456\u043c", + "TEXT_ISEMPTY_TOOLTIP": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 true, \u044f\u043a\u0449\u043e \u0432\u043a\u0430\u0437\u0430\u043d\u0438\u0439 \u0442\u0435\u043a\u0441\u0442 \u043f\u043e\u0440\u043e\u0436\u043d\u0456\u0439.", + "TEXT_INDEXOF_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Finding_text", + "TEXT_INDEXOF_TOOLTIP": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0456\u043d\u0434\u0435\u043a\u0441 \u043f\u0435\u0440\u0448\u043e\u0433\u043e/\u043e\u0441\u0442\u0430\u043d\u043d\u044c\u043e\u0433\u043e \u0432\u0445\u043e\u0434\u0436\u0435\u043d\u043d\u044f \u043f\u0435\u0440\u0448\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0443 \u0443 \u0434\u0440\u0443\u0433\u043e\u043c\u0443. \u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 0, \u044f\u043a\u0449\u043e \u0442\u0435\u043a\u0441\u0442 \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u0438\u0439.", + "TEXT_INDEXOF_INPUT_INTEXT": "\u0443 \u0442\u0435\u043a\u0441\u0442\u0456", + "TEXT_INDEXOF_OPERATOR_FIRST": "\u0437\u043d\u0430\u0439\u0442\u0438 \u043f\u0435\u0440\u0448\u0435 \u0432\u0445\u043e\u0434\u0436\u0435\u043d\u043d\u044f \u0442\u0435\u043a\u0441\u0442\u0443", + "TEXT_INDEXOF_OPERATOR_LAST": "\u0437\u043d\u0430\u0439\u0442\u0438 \u043e\u0441\u0442\u0430\u043d\u043d\u0454 \u0432\u0445\u043e\u0434\u0436\u0435\u043d\u043d\u044f \u0442\u0435\u043a\u0441\u0442\u0443", + "TEXT_INDEXOF_TAIL": ".", + "TEXT_CHARAT_HELPURL": "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm", + "TEXT_CHARAT_INPUT_INTEXT": "\u0443 \u0442\u0435\u043a\u0441\u0442\u0456", + "TEXT_CHARAT_FROM_START": "\u043e\u0442\u0440\u0438\u043c\u0430\u0442\u0438 \u0441\u0438\u043c\u0432\u043e\u043b", + "TEXT_CHARAT_FROM_END": "\u043e\u0442\u0440\u0438\u043c\u0430\u0442\u0438 \u0441\u0438\u043c\u0432\u043e\u043b # \u0437 \u043a\u0456\u043d\u0446\u044f", + "TEXT_CHARAT_FIRST": "\u043e\u0442\u0440\u0438\u043c\u0430\u0442\u0438 \u043f\u0435\u0440\u0448\u0438\u0439 \u0441\u0438\u043c\u0432\u043e\u043b", + "TEXT_CHARAT_LAST": "\u043e\u0442\u0440\u0438\u043c\u0430\u0442\u0438 \u043e\u0441\u0442\u0430\u043d\u043d\u0456\u0439 \u0441\u0438\u043c\u0432\u043e\u043b", + "TEXT_CHARAT_RANDOM": "\u043e\u0442\u0440\u0438\u043c\u0430\u0442\u0438 \u0432\u0438\u043f\u0430\u0434\u043a\u043e\u0432\u0438\u0439 \u0441\u0438\u043c\u0432\u043e\u043b", + "TEXT_CHARAT_TAIL": "-\u0438\u0439.", + "TEXT_CHARAT_TOOLTIP": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0441\u0438\u043c\u0432\u043e\u043b \u0443 \u0437\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0456\u0439 \u043f\u043e\u0437\u0438\u0446\u0456\u0457.", + "TEXT_GET_SUBSTRING_TOOLTIP": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0437\u0430\u0434\u0430\u043d\u0438\u0439 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u0442\u0435\u043a\u0441\u0442\u0443.", + "TEXT_GET_SUBSTRING_HELPURL": "http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text", + "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "\u0443 \u0442\u0435\u043a\u0441\u0442\u0456", + "TEXT_GET_SUBSTRING_START_FROM_START": "\u043e\u0442\u0440\u0438\u043c\u0430\u0442\u0438 \u043f\u0456\u0434\u0440\u044f\u0434\u043e\u043a \u0432\u0456\u0434 \u0441\u0438\u043c\u0432\u043e\u043b\u0443", + "TEXT_GET_SUBSTRING_START_FROM_END": "\u043e\u0442\u0440\u0438\u043c\u0430\u0442\u0438 \u043f\u0456\u0434\u0440\u044f\u0434\u043e\u043a \u0432\u0456\u0434 \u0441\u0438\u043c\u0432\u043e\u043b\u0443 # \u0437 \u043a\u0456\u043d\u0446\u044f", + "TEXT_GET_SUBSTRING_START_FIRST": "\u043e\u0442\u0440\u0438\u043c\u0430\u0442\u0438 \u043f\u0456\u0434\u0440\u044f\u0434\u043e\u043a \u0432\u0456\u0434 \u043f\u0435\u0440\u0448\u043e\u0433\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u0443", + "TEXT_GET_SUBSTRING_END_FROM_START": "\u0434\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u0443 #", + "TEXT_GET_SUBSTRING_END_FROM_END": "\u0434\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u0443 \u0437 \u043a\u0456\u043d\u0446\u044f", + "TEXT_GET_SUBSTRING_END_LAST": "\u0434\u043e \u043e\u0441\u0442\u0430\u043d\u043d\u044c\u043e\u0433\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u0443", + "TEXT_GET_SUBSTRING_TAIL": "-\u043e\u0433\u043e.", + "TEXT_CHANGECASE_HELPURL": "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html", + "TEXT_CHANGECASE_TOOLTIP": "\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438 \u043a\u043e\u043f\u0456\u044e \u0442\u0435\u043a\u0441\u0442\u0443 \u0432 \u0456\u043d\u0448\u043e\u043c\u0443 \u0432\u0438\u043f\u0430\u0434\u043a\u0443.", + "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "\u0434\u043e \u0412\u0415\u0420\u0425\u041d\u042c\u041e\u0413\u041e \u0440\u0435\u0433\u0456\u0441\u0442\u0440\u0443", + "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "\u0434\u043e \u043d\u0438\u0436\u043d\u044c\u043e\u0433\u043e \u0440\u0435\u0433\u0456\u0441\u0442\u0440\u0443", + "TEXT_CHANGECASE_OPERATOR_TITLECASE": "\u0412\u0435\u043b\u0438\u043a\u0456 \u041f\u0435\u0440\u0448\u0456 \u0411\u0443\u043a\u0432\u0438", + "TEXT_TRIM_HELPURL": "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html", + "TEXT_TRIM_TOOLTIP": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u043a\u043e\u043f\u0456\u044e \u0442\u0435\u043a\u0441\u0442\u0443 \u0437 \u043f\u0440\u043e\u0431\u0456\u043b\u0430\u043c\u0438 \u0432\u0438\u043b\u0443\u0447\u0435\u043d\u0438\u043c\u0438 \u0432\u0456\u0434 \u043e\u0434\u043d\u043e\u0433\u043e \u0430\u0431\u043e \u043e\u0431\u043e\u0445 \u043a\u0456\u043d\u0446\u0456\u0432.", + "TEXT_TRIM_OPERATOR_BOTH": "\u0432\u0438\u043a\u0438\u0434\u0430\u0442\u0438 \u043a\u0440\u0430\u0439\u043d\u0456 \u043f\u0440\u043e\u0431\u0456\u043b\u0438 \u0437 \u043e\u0431\u043e\u0445 \u0441\u0442\u043e\u0440\u0456\u043d", + "TEXT_TRIM_OPERATOR_LEFT": "\u0432\u0438\u043b\u0443\u0447\u0430\u0442\u0438 \u043f\u0440\u043e\u0431\u0456\u043b\u0438 \u0437 \u043b\u0456\u0432\u043e\u0433\u043e \u0431\u043e\u043a\u0443", + "TEXT_TRIM_OPERATOR_RIGHT": "\u0432\u0438\u043b\u0443\u0447\u0430\u0442\u0438 \u043f\u0440\u043e\u0431\u0456\u043b\u0438 \u0437 \u043f\u0440\u0430\u0432\u043e\u0433\u043e \u0431\u043e\u043a\u0443", + "TEXT_PRINT_HELPURL": "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html", + "TEXT_PRINT_TITLE": "\u0434\u0440\u0443\u043a %1", + "TEXT_PRINT_TOOLTIP": "\u041d\u0430\u0434\u0440\u0443\u043a\u0443\u0432\u0430\u0442\u0438 \u0437\u0430\u0434\u0430\u043d\u0438\u0439 \u0442\u0435\u043a\u0441\u0442, \u0447\u0438\u0441\u043b\u0430 \u0430\u0431\u043e \u0456\u043d\u0448\u0456 \u0441\u0438\u043c\u0432\u043e\u043b\u0438.", + "TEXT_PROMPT_HELPURL": "http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode92.html", + "TEXT_PROMPT_TYPE_TEXT": "\u0437\u0430\u043f\u0438\u0442 \u043d\u0430 \u0442\u0435\u043a\u0441\u0442 \u0437 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f", + "TEXT_PROMPT_TYPE_NUMBER": "\u0437\u0430\u043f\u0438\u0442 \u043d\u0430 \u0447\u0438\u0441\u043b\u043e \u0437 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f", + "TEXT_PROMPT_TOOLTIP_NUMBER": "\u0417\u0430\u043f\u0438\u0442\u0443\u0432\u0430\u0442\u0438 \u0443 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0447\u0438\u0441\u043b\u043e.", + "TEXT_PROMPT_TOOLTIP_TEXT": "\u0417\u0430\u043f\u0438\u0442\u0443\u0432\u0430\u0442\u0438 \u0443 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430 \u0434\u0435\u044f\u043a\u0438\u0439 \u0442\u0435\u043a\u0441\u0442.", + "LISTS_CREATE_EMPTY_HELPURL": "http://uk.wikipedia.org/wiki/\u0417\u0432%27\u044f\u0437\u0430\u043d\u0438\u0439_\u0441\u043f\u0438\u0441\u043e\u043a", + "LISTS_CREATE_EMPTY_TITLE": "\u0441\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u043f\u043e\u0440\u043e\u0436\u043d\u0456\u0439 \u0441\u043f\u0438\u0441\u043e\u043a", + "LISTS_CREATE_EMPTY_TOOLTIP": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0441\u043f\u0438\u0441\u043e\u043a, \u0434\u043e\u0432\u0436\u0438\u043d\u043e\u044e 0, \u0449\u043e \u043d\u0435 \u043c\u0456\u0441\u0442\u0438\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u0456\u0432 \u0434\u0430\u043d\u0438\u0445", + "LISTS_CREATE_WITH_TOOLTIP": "\u0421\u0442\u0432\u043e\u0440\u044e\u0454 \u0441\u043f\u0438\u0441\u043e\u043a \u0437 \u0431\u0443\u0434\u044c-\u044f\u043a\u043e\u044e \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044e \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0456\u0432.", + "LISTS_CREATE_WITH_INPUT_WITH": "\u0441\u0442\u0432\u043e\u0440\u044e\u0454 \u0441\u043f\u0438\u0441\u043e\u043a \u0437", + "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "\u0441\u043f\u0438\u0441\u043e\u043a", + "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "\u0414\u043e\u0434\u0430\u0442\u0438, \u0432\u0438\u0434\u0430\u043b\u0438\u0442\u0438 \u0430\u0431\u043e \u0437\u043c\u0456\u043d\u0438\u0442\u0438 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0440\u043e\u0437\u0434\u0456\u043b\u0456\u0432 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0431\u043b\u043e\u043a\u0443\u0432\u0430\u043d\u043d\u044f \u0441\u043f\u0438\u0441\u043a\u0443.", + "LISTS_CREATE_WITH_ITEM_TOOLTIP": "\u0414\u043e\u0434\u0430\u0442\u0438 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0434\u043e \u0441\u043f\u0438\u0441\u043a\u0443.", + "LISTS_REPEAT_HELPURL": "https://code.google.com/p/blockly/wiki/Lists#create_list_with", + "LISTS_REPEAT_TOOLTIP": "\u0421\u0442\u0432\u043e\u0440\u044e\u0454 \u0441\u043f\u0438\u0441\u043e\u043a, \u0449\u043e \u0441\u043a\u043b\u0430\u0434\u0430\u0454\u0442\u044c\u0441\u044f \u0437 \u0437\u0430\u0434\u0430\u043d\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u0435\u043d\u043e\u0433\u043e \u043f\u0435\u0432\u043d\u0443 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u0440\u0430\u0437\u0456\u0432.", + "LISTS_REPEAT_TITLE": "\u0441\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u0437 \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0430 %1 \u043f\u043e\u0432\u0442\u043e\u0440\u0435\u043d\u043e\u0433\u043e %2 \u0440\u0430\u0437\u0456\u0432", + "LISTS_LENGTH_HELPURL": "https://code.google.com/p/blockly/wiki/Lists#length_of", + "LISTS_LENGTH_TITLE": "\u0434\u043e\u0432\u0436\u0438\u043d\u0430 %1", + "LISTS_LENGTH_TOOLTIP": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0434\u043e\u0432\u0436\u0438\u043d\u0443 \u0441\u043f\u0438\u0441\u043a\u0443.", + "LISTS_IS_EMPTY_HELPURL": "https://code.google.com/p/blockly/wiki/Lists#is_empty", + "LISTS_IS_EMPTY_TITLE": "%1 \u0454 \u043f\u043e\u0440\u043e\u0436\u043d\u0456\u043c", + "LISTS_TOOLTIP": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0456\u0441\u0442\u0438\u043d\u0430, \u044f\u043a\u0449\u043e \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u0440\u043e\u0436\u043d\u0456\u0439.", + "LISTS_INLIST": "\u0443 \u0441\u043f\u0438\u0441\u043a\u0443", + "LISTS_INDEX_OF_HELPURL": "https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List", + "LISTS_INDEX_OF_FIRST": "\u0437\u043d\u0430\u0439\u0442\u0438 \u043f\u0435\u0440\u0448\u0435 \u0432\u0445\u043e\u0434\u0436\u0435\u043d\u043d\u044f \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0430", + "LISTS_INDEX_OF_LAST": "\u0437\u043d\u0430\u0439\u0442\u0438 \u043e\u0441\u0442\u0430\u043d\u043d\u0454 \u0432\u0445\u043e\u0434\u0436\u0435\u043d\u043d\u044f \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0430", + "LISTS_INDEX_OF_TOOLTIP": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0456\u043d\u0434\u0435\u043a\u0441 \u043f\u0435\u0440\u0448\u043e\u0433\u043e/\u043e\u0441\u0442\u0430\u043d\u043d\u044c\u043e\u0433\u043e \u0432\u0445\u043e\u0434\u0436\u0435\u043d\u043d\u044f \u043f\u0435\u0440\u0448\u043e\u0433\u043e \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0443 \u0443 \u0441\u043f\u0438\u0441\u043a\u0443. \u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 0, \u044f\u043a\u0449\u043e \u0442\u0435\u043a\u0441\u0442 \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u0438\u0439.", + "LISTS_GET_INDEX_GET": "\u043e\u0442\u0440\u0438\u043c\u0430\u0442\u0438", + "LISTS_GET_INDEX_GET_REMOVE": "\u043e\u0442\u0440\u0438\u043c\u0430\u0442\u0438 \u0456 \u0432\u0438\u0434\u0430\u043b\u0438\u0442\u0438", + "LISTS_GET_INDEX_REMOVE": "\u0432\u0438\u043b\u0443\u0447\u0438\u0442\u0438", + "LISTS_GET_INDEX_FROM_START": "#", + "LISTS_GET_INDEX_FROM_END": "# \u0437 \u043a\u0456\u043d\u0446\u044f", + "LISTS_GET_INDEX_FIRST": "\u043f\u0435\u0440\u0448\u0438\u0439", + "LISTS_GET_INDEX_LAST": "\u043e\u0441\u0442\u0430\u043d\u043d\u0456\u0439", + "LISTS_GET_INDEX_RANDOM": "\u0432\u0438\u043f\u0430\u0434\u043a\u043e\u0432\u0438\u0439", + "LISTS_GET_INDEX_TAIL": "-\u0438\u0439.", + "LISTS_GET_INDEX_TOOLTIP_GET_FROM_START": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0443 \u0437\u0430\u0434\u0430\u043d\u0456\u0439 \u043f\u043e\u0437\u0438\u0446\u0456\u044e \u0443 \u0441\u043f\u0438\u0441\u043a\u0443. #1 - \u0446\u0435 \u043f\u0435\u0440\u0448\u0438\u0439 \u043f\u0443\u043d\u043a\u0442.", + "LISTS_GET_INDEX_TOOLTIP_GET_FROM_END": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0443 \u0437\u0430\u0434\u0430\u043d\u0456\u0439 \u043f\u043e\u0437\u0438\u0446\u0456\u0457 \u0443 \u0441\u043f\u0438\u0441\u043a\u0443. #1 - \u0446\u0435 \u043e\u0441\u0442\u0430\u043d\u043d\u0456\u0439 \u043f\u0443\u043d\u043a\u0442.", + "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u043f\u0435\u0440\u0448\u0438\u0439 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0443 \u0441\u043f\u0438\u0441\u043a\u0443.", + "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u043e\u0441\u0442\u0430\u043d\u043d\u0456\u0439 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u043f\u0438\u0441\u043a\u0443.", + "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0432\u0438\u043f\u0430\u0434\u043a\u043e\u0432\u0438\u0439 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0443 \u0441\u043f\u0438\u0441\u043a\u0443.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START": "\u0412\u0438\u0434\u0430\u043b\u044f\u0454 \u0456 \u043f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0443 \u0437\u0430\u0434\u0430\u043d\u0456\u0439 \u043f\u043e\u0437\u0438\u0446\u0456\u0457 \u0443 \u0441\u043f\u0438\u0441\u043a\u0443. #1 - \u0446\u0435 \u043f\u0435\u0440\u0448\u0438\u0439 \u043f\u0443\u043d\u043a\u0442.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END": "\u0412\u0438\u0434\u0430\u043b\u044f\u0454 \u0456 \u043f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0443 \u0437\u0430\u0434\u0430\u043d\u0456\u0439 \u043f\u043e\u0437\u0438\u0446\u0456\u0457 \u0443 \u0441\u043f\u0438\u0441\u043a\u0443. #1 - \u0446\u0435 \u043e\u0441\u0442\u0430\u043d\u043d\u0456\u0439 \u043f\u0443\u043d\u043a\u0442.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "\u0412\u0438\u0434\u0430\u043b\u044f\u0454 \u0456 \u043f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u043f\u0435\u0440\u0448\u0438\u0439 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0443 \u0441\u043f\u0438\u0441\u043a\u0443.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "\u0412\u0438\u0434\u0430\u043b\u044f\u0454 \u0456 \u043f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u043e\u0441\u0442\u0430\u043d\u043d\u0456\u0439 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u043f\u0438\u0441\u043a\u0443.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "\u0412\u0438\u0434\u0430\u043b\u044f\u0454 \u0456 \u043f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0432\u0438\u043f\u0430\u0434\u043a\u043e\u0432\u0438\u0439 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0443 \u0441\u043f\u0438\u0441\u043e\u043a.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START": "\u0412\u0438\u043b\u0443\u0447\u0430\u0454 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0443 \u0432\u043a\u0430\u0437\u0430\u043d\u0456\u0439 \u043f\u043e\u0437\u0438\u0446\u0456\u0457 \u0441\u043f\u0438\u0441\u043a\u0443. #1 - \u0446\u0435 \u043f\u0435\u0440\u0448\u0438\u0439 \u043f\u0443\u043d\u043a\u0442.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END": "\u0412\u0438\u043b\u0443\u0447\u0430\u0454 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0443 \u0432\u043a\u0430\u0437\u0430\u043d\u0456\u0439 \u043f\u043e\u0437\u0438\u0446\u0456\u0457 \u0441\u043f\u0438\u0441\u043a\u0443. #1 - \u0446\u0435 \u043e\u0441\u0442\u0430\u043d\u043d\u0456\u0439 \u043f\u0443\u043d\u043a\u0442.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "\u0412\u0438\u0434\u0430\u043b\u044f\u0454 \u043f\u0435\u0440\u0448\u0438\u0439 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0443 \u0441\u043f\u0438\u0441\u043a\u0443.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "\u0412\u0438\u0434\u0430\u043b\u044f\u0454 \u043e\u0441\u0442\u0430\u043d\u043d\u0456\u0439 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u043f\u0438\u0441\u043a\u0443.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "\u0412\u0438\u0434\u0430\u043b\u044f\u0454 \u0432\u0438\u043f\u0430\u0434\u043a\u043e\u0432\u0438\u0439 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0443 \u0441\u043f\u0438\u0441\u043a\u0443.", + "LISTS_SET_INDEX_HELPURL": "https://code.google.com/p/blockly/wiki/Lists#in_list_..._set", + "LISTS_SET_INDEX_SET": "\u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438", + "LISTS_SET_INDEX_INSERT": "\u0432\u0441\u0442\u0430\u0432\u0438\u0442\u0438 \u0432", + "LISTS_SET_INDEX_INPUT_TO": "\u044f\u043a", + "LISTS_SET_INDEX_TOOLTIP_SET_FROM_START": "\u0417\u0430\u0434\u0430\u0454 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0443 \u0432\u043a\u0430\u0437\u0430\u043d\u0456\u0439 \u043f\u043e\u0437\u0438\u0446\u0456\u0457 \u0441\u043f\u0438\u0441\u043a\u0443. #1 - \u0446\u0435 \u043f\u0435\u0440\u0448\u0438\u0439 \u043f\u0443\u043d\u043a\u0442.", + "LISTS_SET_INDEX_TOOLTIP_SET_FROM_END": "\u0417\u0430\u0434\u0430\u0454 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0443 \u0432\u043a\u0430\u0437\u0430\u043d\u0456\u0439 \u043f\u043e\u0437\u0438\u0446\u0456\u0457 \u0441\u043f\u0438\u0441\u043a\u0443. #1 - \u0446\u0435 \u043e\u0441\u0442\u0430\u043d\u043d\u0456\u0439 \u043f\u0443\u043d\u043a\u0442.", + "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "\u0417\u0430\u0434\u0430\u0454 \u043f\u0435\u0440\u0448\u0438\u0439 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0443 \u0441\u043f\u0438\u0441\u043a\u0443.", + "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "\u0417\u0430\u0434\u0430\u0454 \u043e\u0441\u0442\u0430\u043d\u043d\u0456\u0439 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u043f\u0438\u0441\u043a\u0443.", + "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "\u0417\u0430\u0434\u0430\u0454 \u0432\u0438\u043f\u0430\u0434\u043a\u043e\u0432\u0438\u0439 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0443 \u0441\u043f\u0438\u0441\u043a\u0443.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START": "\u0412\u0441\u0442\u0430\u0432\u043a\u0430 \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0443 \u0432\u043a\u0430\u0437\u0430\u043d\u0443 \u043f\u043e\u0437\u0438\u0446\u0456\u044e \u0441\u043f\u0438\u0441\u043a\u0443. #1 \u0454 \u043f\u0435\u0440\u0448\u0438\u043c \u043f\u0443\u043d\u043a\u0442\u043e\u043c.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END": "\u0412\u0441\u0442\u0430\u0432\u043b\u044f\u0454 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0443 \u0432\u043a\u0430\u0437\u0430\u043d\u0443 \u043f\u043e\u0437\u0438\u0446\u0456\u044e \u0441\u043f\u0438\u0441\u043a\u0443. #1 - \u0446\u0435 \u043e\u0441\u0442\u0430\u043d\u043d\u0456\u0439 \u043f\u0443\u043d\u043a\u0442.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "\u0412\u0441\u0442\u0430\u0432\u043b\u044f\u0454 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u043d\u0430 \u043f\u043e\u0447\u0430\u0442\u043e\u043a \u0441\u043f\u0438\u0441\u043a\u0443.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "\u0414\u043e\u0434\u0430\u0454 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0434\u043e \u043a\u0456\u043d\u0446\u044f \u0441\u043f\u0438\u0441\u043a\u0443.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "\u0412\u0438\u043f\u0430\u0434\u043a\u043e\u0432\u0438\u043c \u0447\u0438\u043d\u043e\u043c \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0454 \u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0443 \u0441\u043f\u0438\u0441\u043a\u0443.", + "LISTS_GET_SUBLIST_HELPURL": "https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist", + "LISTS_GET_SUBLIST_START_FROM_START": "\u043e\u0442\u0440\u0438\u043c\u0430\u0442\u0438 \u0432\u043a\u043b\u0430\u0434\u0435\u043d\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0437 #", + "LISTS_GET_SUBLIST_START_FROM_END": "\u043e\u0442\u0440\u0438\u043c\u0430\u0442\u0438 \u0432\u043a\u043b\u0430\u0434\u0435\u043d\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0456\u0434 # \u0437 \u043a\u0456\u043d\u0446\u044f", + "LISTS_GET_SUBLIST_START_FIRST": "\u043e\u0442\u0440\u0438\u043c\u0430\u0442\u0438 \u0432\u043a\u043b\u0430\u0434\u0435\u043d\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0437 \u043f\u0435\u0440\u0448\u043e\u0433\u043e", + "LISTS_GET_SUBLIST_END_FROM_START": "\u0434\u043e #", + "LISTS_GET_SUBLIST_END_FROM_END": "\u0434\u043e # \u0437 \u043a\u0456\u043d\u0446\u044f", + "LISTS_GET_SUBLIST_END_LAST": "\u0434\u043e \u043e\u0441\u0442\u0430\u043d\u043d\u044c\u043e\u0433\u043e", + "LISTS_GET_SUBLIST_TAIL": "\u0441\u0438\u043c\u0432\u043e\u043b\u0443.", + "LISTS_GET_SUBLIST_TOOLTIP": "\u0421\u0442\u0432\u043e\u0440\u044e\u0454 \u043a\u043e\u043f\u0456\u044e \u0432\u043a\u0430\u0437\u0430\u043d\u043e\u0457 \u0447\u0430\u0441\u0442\u0438\u043d\u0438 \u0441\u043f\u0438\u0441\u043a\u0443.", + "ORDINAL_NUMBER_SUFFIX": "-\u0438\u0439.", + "VARIABLES_GET_HELPURL": "http://code.google.com/p/blockly/wiki/Variables#Get", + "VARIABLES_GET_TITLE": "\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f", + "VARIABLES_GET_TAIL": "\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f", + "VARIABLES_GET_TOOLTIP": "\u041f\u043e\u0432\u0435\u0440\u0442\u0430\u0454 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0446\u0456\u0454\u0457 \u0437\u043c\u0456\u043d\u043d\u043e\u0457.", + "VARIABLES_GET_CREATE_SET": "\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 'set %1'", + "VARIABLES_SET_HELPURL": "http://code.google.com/p/blockly/wiki/Variables#Set", + "VARIABLES_SET_TITLE": "\u0432\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438", + "VARIABLES_SET_TAIL": "\u0434\u043e", + "VARIABLES_SET_TOOLTIP": "\u0417\u0430\u0434\u0430\u0454 \u0446\u044e \u0437\u043c\u0456\u043d\u043d\u0443 \u0440\u0456\u0432\u043d\u043e\u044e \u0432\u0432\u043e\u0434\u0443.", + "VARIABLES_SET_CREATE_GET": "\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 'get %1'", + "PROCEDURES_DEFNORETURN_HELPURL": "http://uk.wikipedia.org/wiki/\u041f\u0456\u0434\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430", + "PROCEDURES_DEFNORETURN_TITLE": "\u0434\u043e", + "PROCEDURES_DEFNORETURN_PROCEDURE": "\u0449\u043e\u0441\u044c \u0437\u0440\u043e\u0431\u0438\u0442\u0438", + "PROCEDURES_BEFORE_PARAMS": "\u0437:", + "PROCEDURES_DEFNORETURN_DO": "\u0431\u043b\u043e\u043a \u0442\u0435\u043a\u0441\u0442\u0443", + "PROCEDURES_DEFNORETURN_TOOLTIP": "\u0421\u0442\u0432\u043e\u0440\u044e\u0454 \u0444\u0443\u043d\u043a\u0446\u0456\u044e \u0431\u0435\u0437 \u0432\u0438\u0432\u043e\u0434\u0443.", + "PROCEDURES_DEFRETURN_HELPURL": "http://uk.wikipedia.org/wiki/\u041f\u0456\u0434\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430", + "PROCEDURES_DEFRETURN_RETURN": "\u043f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438", + "PROCEDURES_DEFRETURN_TOOLTIP": "\u0421\u0442\u0432\u043e\u0440\u044e\u0454 \u0444\u0443\u043d\u043a\u0446\u0456\u044e \u0437 \u0432\u0438\u0432\u043e\u0434\u0443.", + "PROCEDURES_DEF_DUPLICATE_WARNING": "\u0423\u0432\u0430\u0433\u0430: \u0446\u044f \u0444\u0443\u043d\u043a\u0446\u0456\u044f \u043c\u0430\u0454 \u0434\u0443\u0431\u043b\u044c\u043e\u0432\u0430\u043d\u0456 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438.", + "PROCEDURES_CALLNORETURN_HELPURL": "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29", + "PROCEDURES_CALLNORETURN_CALL": "\u0431\u043b\u043e\u043a \u0442\u0435\u043a\u0441\u0442\u0443", + "PROCEDURES_CALLNORETURN_TOOLTIP": "\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0446\u044c\u043a\u0443 \u0444\u0443\u043d\u043a\u0446\u0456\u044e \"%1\".", + "PROCEDURES_CALLRETURN_HELPURL": "http://uk.wikipedia.org/wiki/\u041f\u0456\u0434\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430", + "PROCEDURES_CALLRETURN_TOOLTIP": "\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0438 \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0446\u044c\u043a\u0443 \u0444\u0443\u043d\u043a\u0446\u0456\u044e \"%1\" \u0456 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438 \u0457\u0457 \u0432\u0438\u0432\u0456\u0434.", + "PROCEDURES_MUTATORCONTAINER_TITLE": "\u0432\u0445\u0456\u0434", + "PROCEDURES_MUTATORARG_TITLE": "\u0456\u043c'\u044f \u0432\u0445\u043e\u0434\u0443:", + "PROCEDURES_HIGHLIGHT_DEF": "\u0412\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0444\u0443\u043d\u043a\u0446\u0456\u0457 \u043f\u0456\u0434\u0441\u0432\u0456\u0442\u043a\u0438", + "PROCEDURES_CREATE_DO": "\u0421\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \"%1\"", + "PROCEDURES_IFRETURN_TOOLTIP": "\u042f\u043a\u0449\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f true, \u0442\u043e \u043f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u0438 \u0434\u0440\u0443\u0433\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f.", + "PROCEDURES_IFRETURN_WARNING": "\u041f\u043e\u043f\u0435\u0440\u0435\u0434\u0436\u0435\u043d\u043d\u044f: \u0426\u0435\u0439 \u0431\u043b\u043e\u043a \u043c\u043e\u0436\u0435 \u0432\u0438\u043a\u043e\u0440\u0438\u0441\u0442\u043e\u0432\u0443\u0432\u0430\u0442\u0438\u0441\u044f \u043b\u0438\u0448\u0435 \u0432 \u043c\u0435\u0436\u0430\u0445 \u0432\u0438\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044f \u0444\u0443\u043d\u043a\u0446\u0456\u0457." +} \ No newline at end of file diff --git a/msg/json/vi.json b/msg/json/vi.json new file mode 100644 index 000000000..7732eedb5 --- /dev/null +++ b/msg/json/vi.json @@ -0,0 +1,305 @@ +{ + "@metadata": { + "authors": [ + "Baonguyen21022003", + "Espertus", + "Qneutron" + ] + }, + "VARIABLES_DEFAULT_NAME": "v\u1eadt", + "DUPLICATE_BLOCK": "T\u1ea1o B\u1ea3n Sao", + "ADD_COMMENT": "Th\u00eam Ch\u00fa Gi\u1ea3i", + "REMOVE_COMMENT": "X\u00f3a Ch\u00fa Gi\u1ea3i", + "EXTERNAL_INPUTS": "Ch\u1ed7 G\u1eafn B\u00ean Ngo\u00e0i", + "INLINE_INPUTS": "Ch\u1ed7 G\u1eafn C\u00f9ng D\u00f2ng", + "DELETE_BLOCK": "X\u00f3a M\u1ea3nh N\u00e0y", + "DELETE_X_BLOCKS": "X\u00f3a %1 M\u1ea3nh", + "COLLAPSE_BLOCK": "Thu Nh\u1ecf M\u1ea3nh", + "COLLAPSE_ALL": "Thu Nh\u1ecf M\u1ecdi M\u1ea3nh", + "EXPAND_BLOCK": "M\u1edf L\u1edbn M\u1ea3nh", + "EXPAND_ALL": "M\u1edf L\u1edbn M\u1ecdi M\u1ea3nh", + "DISABLE_BLOCK": "Ng\u01b0ng T\u00e1c D\u1ee5ng", + "ENABLE_BLOCK": "Ph\u1ee5c H\u1ed3i T\u00e1c D\u1ee5ng", + "HELP": "Tr\u1ee3 Gi\u00fap", + "CHANGE_VALUE_TITLE": "Thay gi\u00e1 tr\u1ecb th\u00e0nh:", + "NEW_VARIABLE": "Bi\u1ebfn m\u1edbi...", + "NEW_VARIABLE_TITLE": "T\u00ean c\u1ee7a bi\u1ebfn m\u1edbi:", + "RENAME_VARIABLE": "Thay t\u00ean bi\u1ebfn...", + "RENAME_VARIABLE_TITLE": "Thay t\u00ean t\u1ea5t c\u1ea3 \"%1\" bi\u1ebfn n\u00e0y th\u00e0nh:", + "COLOUR_PICKER_HELPURL": "http://vi.wikipedia.org/wiki/M%C3%A0u_s%E1%BA%AFc", + "COLOUR_PICKER_TOOLTIP": "Ch\u1ecdn m\u1ed9t m\u00e0u t\u1eeb b\u1ea3ng m\u00e0u.", + "COLOUR_RANDOM_TITLE": "m\u00e0u b\u1ea5t k\u1ef3", + "COLOUR_RANDOM_TOOLTIP": "ch\u1ecdn m\u1ed9t m\u00e0u b\u1ea5t k\u1ef3.", + "COLOUR_RGB_TITLE": "T\u1ea1o m\u00e0u t\u1eeb", + "COLOUR_RGB_RED": "m\u00e0u \u0111\u1ecf", + "COLOUR_RGB_GREEN": "m\u00e0u xanh l\u00e1 c\u00e2y", + "COLOUR_RGB_BLUE": "m\u00e0u xanh d\u01b0\u01a1ng", + "COLOUR_RGB_TOOLTIP": "T\u1ea1o m\u00e0u t\u1eeb ba m\u00e0u: \u0111\u1ecf, xanh l\u00e1 c\u00e2y, xanh d\u01b0\u01a1ng v\u1edbi s\u1ed1 l\u01b0\u1ee3ng c\u1ee5 th\u1ec3. M\u1ed7i s\u1ed1 ph\u1ea3i c\u00f3 gi\u00e1 tr\u1ecb t\u1eeb 0 \u0111\u1ebfn 100.", + "COLOUR_BLEND_TITLE": "pha", + "COLOUR_BLEND_COLOUR1": "m\u00e0u 1", + "COLOUR_BLEND_COLOUR2": "m\u00e0u 2", + "COLOUR_BLEND_RATIO": "t\u1ec9 l\u1ec7", + "COLOUR_BLEND_TOOLTIP": "Pha hai m\u00e0u v\u1edbi nhau theo t\u1ec9 l\u1ec7 (0 - 100).", + "CONTROLS_REPEAT_HELPURL": "http://en.wikipedia.org/wiki/For_loop", + "CONTROLS_REPEAT_TITLE": "l\u1eb7p l\u1ea1i %1 l\u1ea7n", + "CONTROLS_REPEAT_TITLE_REPEAT": "l\u1eb7p l\u1ea1i", + "CONTROLS_REPEAT_TITLE_TIMES": "l\u1ea7n", + "CONTROLS_REPEAT_INPUT_DO": "th\u1ef1c hi\u1ec7n", + "CONTROLS_REPEAT_TOOLTIP": "Th\u1ef1c hi\u1ec7n c\u00e1c l\u1ec7nh v\u00e0i l\u1ea7n.", + "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "l\u1eb7p l\u1ea1i trong\u00a0khi", + "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "l\u1eb7p l\u1ea1i cho \u0111\u1ebfn\u00a0khi", + "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Mi\u1ec5n l\u00e0 \u0111i\u1ec1u ki\u1ec7n c\u00f2n \u0111\u00fang, th\u00ec th\u1ef1c hi\u1ec7n c\u00e1c l\u1ec7nh.", + "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Mi\u1ec5n l\u00e0 \u0111i\u1ec1u ki\u1ec7n c\u00f2n sai, th\u00ec th\u1ef1c hi\u1ec7n c\u00e1c l\u1ec7nh. Khi \u0111i\u1ec1u ki\u1ec7n \u0111\u00fang th\u00ec ng\u01b0ng.", + "CONTROLS_FOR_TOOLTIP": "\u0110\u1ebfm t\u1eeb s\u1ed1 \u0111\u1ea7u \u0111\u1ebfn s\u1ed1 cu\u1ed1i. Khi \u0111\u1ebfn m\u1ed7i s\u1ed1, g\u00e1n s\u1ed1 v\u00e0o bi\u1ebfn \"%1\" r\u1ed3i th\u1ef1c hi\u1ec7n c\u00e1c l\u1ec7nh.", + "CONTROLS_FOR_INPUT_WITH": "\u0111\u1ebfm theo", + "CONTROLS_FOR_INPUT_FROM_TO_BY": "t\u1eeb %1 \u0111\u1ebfn %2 m\u1ed7i l\u1ea7n th\u00eam %3", + "CONTROLS_FOREACH_INPUT_ITEM": "v\u1edbi m\u1ed7i th\u00e0nh ph\u1ea7n", + "CONTROLS_FOREACH_INPUT_INLIST": "trong danh s\u00e1ch", + "CONTROLS_FOREACH_INPUT_INLIST_TAIL": "", + "CONTROLS_FOREACH_TOOLTIP": "Trong m\u1ed9t danh s\u00e1ch, l\u1ea5y t\u1eebng th\u00e0nh ph\u1ea7n, g\u00e1n v\u00e0o bi\u1ebfn \"%1\", r\u1ed3i th\u1ef1c hi\u1ec7n m\u1ed9t s\u1ed1 l\u1ec7nh.", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "tho\u00e1t", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "sang l\u1ea7n l\u1eb7p ti\u1ebfp theo", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Tho\u00e1t kh\u1ecfi v\u00f2ng l\u1eb7p hi\u1ec7n t\u1ea1i.", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "B\u1ecf qua ph\u1ea7n c\u00f2n l\u1ea1i trong v\u00f2ng l\u1eb7p n\u00e0y, v\u00e0 sang l\u1ea7n l\u1eb7p ti\u1ebfp theo.", + "CONTROLS_FLOW_STATEMENTS_WARNING": "Ch\u00fa \u00fd: M\u1ea3nh n\u00e0y ch\u1ec9 c\u00f3 th\u1ebf d\u00f9ng trong c\u00e1c v\u00f2ng l\u1eb7p.", + "CONTROLS_IF_TOOLTIP_1": "N\u1ebfu \u0111i\u1ec1u ki\u1ec7n \u0111\u00fang, th\u1ef1c hi\u1ec7n c\u00e1c l\u1ec7nh.", + "CONTROLS_IF_TOOLTIP_2": "N\u1ebfu \u0111i\u1ec1u ki\u1ec7n \u0111\u00fang, th\u1ef1c hi\u1ec7n c\u00e1c l\u1ec7nh \u0111\u1ea7u. N\u1ebfu sai, th\u1ef1c hi\u1ec7n c\u00e1c l\u1ec7nh sau.", + "CONTROLS_IF_TOOLTIP_3": "N\u1ebfu \u0111i\u1ec1u ki\u1ec7n \u0111\u00fang, th\u1ef1c hi\u1ec7n c\u00e1c l\u1ec7nh \u0111\u1ea7u. N\u1ebfu kh\u00f4ng, n\u1ebfu \u0111i\u1ec1u ki\u1ec7n th\u1ee9 hai \u0111\u00fang, th\u1ef1c hi\u1ec7n c\u00e1c l\u1ec7nh th\u1ee9 hai.", + "CONTROLS_IF_TOOLTIP_4": "N\u1ebfu \u0111i\u1ec1u ki\u1ec7n \u0111\u00fang, th\u1ef1c hi\u1ec7n c\u00e1c l\u1ec7nh \u0111\u1ea7u. N\u1ebfu kh\u00f4ng, n\u1ebfu \u0111i\u1ec1u ki\u1ec7n th\u1ee9 hai \u0111\u00fang, th\u1ef1c hi\u1ec7n c\u00e1c l\u1ec7nh th\u1ee9 hai. N\u1ebfu kh\u00f4ng \u0111i\u1ec1u ki\u1ec7n n\u00e0o \u0111\u00fang, th\u1ef1c hi\u1ec7n c\u00e1c l\u1ec7nh cu\u1ed1i c\u00f9ng.", + "CONTROLS_IF_MSG_IF": "n\u1ebfu", + "CONTROLS_IF_MSG_ELSEIF": "n\u1ebfu kh\u00f4ng n\u1ebfu", + "CONTROLS_IF_MSG_ELSE": "n\u1ebfu kh\u00f4ng", + "CONTROLS_IF_IF_TOOLTIP": "Th\u00eam, b\u1ecf, ho\u1eb7c \u0111\u1ed5i th\u1ee9 t\u1ef1 c\u00e1c m\u1ea3nh con \u0111\u1ec3 t\u1ea1o c\u1ea5u tr\u00fac m\u1edbi cho m\u1ea3nh n\u1ebfu.", + "CONTROLS_IF_ELSEIF_TOOLTIP": "Th\u00eam m\u1ed9t \u0111i\u1ec1u ki\u1ec7n v\u00e0o m\u1ea3nh n\u1ebfu.", + "CONTROLS_IF_ELSE_TOOLTIP": "Cu\u1ed1i c\u00f9ng, khi kh\u00f4ng \u0111i\u1ec1u ki\u1ec7n n\u00e0o \u0111\u00fang.", + "LOGIC_COMPARE_HELPURL": "http://vi.wikipedia.org/wiki/B%E1%BA%A5t_%C4%91%E1%BA%B3ng_th%E1%BB%A9c", + "LOGIC_COMPARE_TOOLTIP_EQ": "Ho\u00e0n tr\u1ea3 gi\u00e1 tr\u1ecb \"\u0111\u00fang\" (true) n\u1ebfu gi\u00e1 tr\u1ecb hai \u0111\u1ea7u v\u00e0o b\u1eb1ng nhau.", + "LOGIC_COMPARE_TOOLTIP_NEQ": "Ho\u00e0n tr\u1ea3 gi\u00e1 tr\u1ecb \"\u0111\u00fang\" (true) n\u1ebfu gi\u00e1 tr\u1ecb hai \u0111\u1ea7u v\u00e0o kh\u00f4ng b\u1eb1ng nhau.", + "LOGIC_COMPARE_TOOLTIP_LT": "Ho\u00e0n tr\u1ea3 gi\u00e1 tr\u1ecb \"\u0111\u00fang\" (true) n\u1ebfu \u0111\u1ea7u v\u00e0o th\u1ee9 nh\u1ea5t nh\u1ecf h\u01a1n \u0111\u1ea7u v\u00e0o th\u1ee9 hai.", + "LOGIC_COMPARE_TOOLTIP_LTE": "Ho\u00e0n tr\u1ea3 gi\u00e1 tr\u1ecb \"\u0111\u00fang\" (true) n\u1ebfu \u0111\u1ea7u v\u00e0o th\u1ee9 nh\u1ea5t nh\u1ecf h\u01a1n ho\u1eb7c b\u1eb1ng \u0111\u1ea7u v\u00e0o th\u1ee9 hai.", + "LOGIC_COMPARE_TOOLTIP_GT": "Ho\u00e0n tr\u1ea3 gi\u00e1 tr\u1ecb \"\u0111\u00fang\" (true) n\u1ebfu \u0111\u1ea7u v\u00e0o th\u1ee9 nh\u1ea5t l\u1edbn h\u01a1n \u0111\u1ea7u v\u00e0o th\u1ee9 hai.", + "LOGIC_COMPARE_TOOLTIP_GTE": "Ho\u00e0n tr\u1ea3 gi\u00e1 tr\u1ecb \"\u0111\u00fang\" (true) n\u1ebfu \u0111\u1ea7u v\u00e0o th\u1ee9 nh\u1ea5t l\u1edbn h\u01a1n ho\u1eb7c b\u1eb1ng \u0111\u1ea7u v\u00e0o th\u1ee9 hai.", + "LOGIC_OPERATION_TOOLTIP_AND": "Ho\u00e0n tr\u1ea3 \"\u0111\u00fang\" (true) n\u1ebfu c\u1ea3 hai \u0111\u1ea7u v\u00e0o \u0111\u1ec1u \u0111\u00fang.", + "LOGIC_OPERATION_AND": "v\u00e0", + "LOGIC_OPERATION_TOOLTIP_OR": "Ho\u00e0n tr\u1ea3 \"\u0111\u00fang\" (true) n\u1ebfu \u00edt nh\u1ea5t m\u1ed9t trong hai \u0111\u1ea7u v\u00e0o \u0111\u00fang.", + "LOGIC_OPERATION_OR": "ho\u1eb7c", + "LOGIC_NEGATE_TITLE": "kh\u00f4ng %1", + "LOGIC_NEGATE_TOOLTIP": "Ho\u00e0n tr\u1ea3 \"\u0111\u00fang\" (true) n\u1ebfu \u0111\u1ea7u v\u00e0o sai. Ho\u00e0n tr\u1ea3 \"sai\" (false) n\u1ebfu \u0111\u1ea7u v\u00e0o \u0111\u00fang.", + "LOGIC_BOOLEAN_TRUE": "\u0111\u00fang", + "LOGIC_BOOLEAN_FALSE": "sai", + "LOGIC_BOOLEAN_TOOLTIP": "Ho\u00e0n tr\u1ea3 \"\u0111\u00fang\" ho\u1eb7c \"sai\".", + "LOGIC_NULL": "tr\u1ed1ng kh\u00f4ng", + "LOGIC_NULL_TOOLTIP": "Ho\u00e0n tr\u1ea3 tr\u1ed1ng kh\u00f4ng.", + "LOGIC_TERNARY_CONDITION": "ki\u1ec3m tra", + "LOGIC_TERNARY_IF_TRUE": "n\u1ebfu \u0111\u00fang", + "LOGIC_TERNARY_IF_FALSE": "n\u1ebfu sai", + "LOGIC_TERNARY_TOOLTIP": "Ki\u1ec3m tra \u0111i\u1ec1u ki\u1ec7n. N\u1ebfu \u0111i\u1ec1u ki\u1ec7n \u0111\u00fang, ho\u00e0n tr\u1ea3 gi\u00e1 tr\u1ecb t\u1eeb m\u1ec7nh \u0111\u1ec1 \"n\u1ebfu \u0111\u00fang\" n\u1ebfu kh\u00f4ng \u0111\u00fang, ho\u00e0n tr\u1ea3 gi\u00e1 tr\u1ecb t\u1eeb m\u1ec7nh \u0111\u1ec1 \"n\u1ebfu sai\".", + "MATH_NUMBER_HELPURL": "http://vi.wikipedia.org/wiki/S%E1%BB%91", + "MATH_NUMBER_TOOLTIP": "M\u1ed9t con s\u1ed1.", + "MATH_ARITHMETIC_HELPURL": "http://vi.wikipedia.org/wiki/S%E1%BB%91_h%E1%BB%8Dc", + "MATH_ARITHMETIC_TOOLTIP_ADD": "Ho\u00e0n tr\u1ea3 t\u1ed5ng c\u1ee7a hai con s\u1ed1.", + "MATH_ARITHMETIC_TOOLTIP_MINUS": "Ho\u00e0n tr\u1ea3 hi\u1ec7u c\u1ee7a hai con s\u1ed1.", + "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Ho\u00e0n tr\u1ea3 t\u00edch c\u1ee7a hai con s\u1ed1.", + "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Ho\u00e0n tr\u1ea3 th\u01b0\u01a1ng c\u1ee7a hai con s\u1ed1.", + "MATH_ARITHMETIC_TOOLTIP_POWER": "Ho\u00e0n tr\u1ea3 s\u1ed1 l\u0169y th\u1eeba v\u1edbi s\u1ed1 th\u1ee9 nh\u1ea5t l\u00e0 c\u01a1 s\u1ed1 v\u00e0 s\u1ed1 th\u1ee9 hai l\u00e0 s\u1ed1 m\u0169.", + "MATH_SINGLE_HELPURL": "http://vi.wikipedia.org/wiki/C%C4%83n_b%E1%BA%ADc_hai", + "MATH_SINGLE_OP_ROOT": "c\u0103n b\u1eadt hai", + "MATH_SINGLE_TOOLTIP_ROOT": "Ho\u00e0n tr\u1ea3 c\u0103n b\u1eadt hai c\u1ee7a s\u1ed1 \u0111\u1ea7u v\u00e0o.", + "MATH_SINGLE_OP_ABSOLUTE": "gi\u00e1 tr\u1ecb tuy\u1ec7t \u0111\u1ed1i", + "MATH_SINGLE_TOOLTIP_ABS": "Ho\u00e0n tr\u1ea3 gi\u00e1 tr\u1ecb tuy\u1ec7t \u0111\u1ed1i c\u1ee7a s\u1ed1 \u0111\u1ea7u v\u00e0o.", + "MATH_SINGLE_TOOLTIP_NEG": "\u0110\u1ed5i d\u1ea5u c\u1ee7a s\u1ed1 \u0111\u1ea7u v\u00e0o: \u00e2m th\u00e0nh d\u01b0\u01a1ng v\u00e0 d\u01b0\u01a1ng th\u00e0nh \u00e2m, v\u00e0 ho\u00e0n tr\u1ea3 s\u1ed1 m\u1edbi.", + "MATH_SINGLE_TOOLTIP_LN": "Ho\u00e0n tr\u1ea3 l\u00f4garit t\u1ef1 nhi\u00ean c\u1ee7a s\u1ed1 \u0111\u1ea7u v\u00e0o.", + "MATH_SINGLE_TOOLTIP_LOG10": "Ho\u00e0n tr\u1ea3 l\u00f4garit c\u01a1 s\u1ed1 10 c\u1ee7a s\u1ed1 \u0111\u1ea7u v\u00e0o.", + "MATH_SINGLE_TOOLTIP_EXP": "Ho\u00e0n tr\u1ea3 l\u0169y th\u1eeba c\u1ee7a s\u1ed1 e v\u1edbi s\u1ed1 m\u0169 \u0111\u1ea7u v\u00e0o.", + "MATH_SINGLE_TOOLTIP_POW10": "Ho\u00e0n tr\u1ea3 l\u0169y th\u1eeba c\u1ee7a s\u1ed1 10 v\u1edbi s\u1ed1 m\u0169 \u0111\u1ea7u v\u00e0o.", + "MATH_TRIG_HELPURL": "http://vi.wikipedia.org/wiki/H%C3%A0m_l%C6%B0%E1%BB%A3ng_gi%C3%A1c", + "MATH_TRIG_TOOLTIP_SIN": "Ho\u00e0n tr\u1ea3 Sin c\u1ee7a m\u1ed9t g\u00f3c (theo \u0111\u1ed9).", + "MATH_TRIG_TOOLTIP_COS": "Ho\u00e0n tr\u1ea3 Cos c\u1ee7a m\u1ed9t g\u00f3c (theo \u0111\u1ed9).", + "MATH_TRIG_TOOLTIP_TAN": "Ho\u00e0n tr\u1ea3 Tang c\u1ee7a m\u1ed9t g\u00f3c (theo \u0111\u1ed9).", + "MATH_TRIG_TOOLTIP_ASIN": "Ho\u00e0n tr\u1ea3 Arcsin c\u1ee7a m\u1ed9t g\u00f3c (theo \u0111\u1ed9).", + "MATH_TRIG_TOOLTIP_ACOS": "Ho\u00e0n tr\u1ea3 Arccos c\u1ee7a m\u1ed9t g\u00f3c (theo \u0111\u1ed9).", + "MATH_TRIG_TOOLTIP_ATAN": "Ho\u00e0n tr\u1ea3 Arctang c\u1ee7a m\u1ed9t g\u00f3c (theo \u0111\u1ed9).", + "MATH_CONSTANT_HELPURL": "http://en.wikipedia.org/wiki/Mathematical_constant", + "MATH_CONSTANT_TOOLTIP": "Ho\u00e0n tr\u1ea3 c\u00e1c \u0111\u1eb3ng s\u1ed1 th\u01b0\u1eddng g\u1eb7p: \u03c0 (3.141\u2026), e (2.718\u2026), \u03c6 (1.618\u2026), sqrt(2) (1.414\u2026), sqrt(\u00bd) (0.707\u2026), or \u221e (v\u00f4 c\u1ef1c).", + "MATH_IS_EVEN": "ch\u1eb5n", + "MATH_IS_ODD": "l\u1ebb", + "MATH_IS_PRIME": "l\u00e0 s\u1ed1 nguy\u00ean t\u1ed1", + "MATH_IS_WHOLE": "l\u00e0 s\u1ed1 nguy\u00ean", + "MATH_IS_POSITIVE": "l\u00e0 s\u1ed1 d\u01b0\u01a1ng", + "MATH_IS_NEGATIVE": "l\u00e0 s\u1ed1 \u00e2m", + "MATH_IS_DIVISIBLE_BY": "chia h\u1ebft cho", + "MATH_IS_TOOLTIP": "Ki\u1ec3m tra con s\u1ed1 xem n\u00f3 c\u00f3 ph\u1ea3i l\u00e0 s\u1ed1 ch\u1eb5n, l\u1ebb, nguy\u00ean t\u1ed1, nguy\u00ean, d\u01b0\u01a1ng, \u00e2m, hay xem n\u00f3 c\u00f3 chia h\u1ebft cho s\u1ed1 \u0111\u1ea7u v\u00e0o hay kh\u00f4ng. Ho\u00e0n tr\u1ea3 \u0111\u00fang hay sai.", + "MATH_CHANGE_TITLE_CHANGE": "c\u1ed9ng v\u00e0o", + "MATH_CHANGE_INPUT_BY": "gi\u00e1 tr\u1ecb", + "MATH_CHANGE_TOOLTIP": "C\u1ed9ng s\u1ed1 \u0111\u1ea7u v\u00e0o v\u00e0o bi\u1ebfn \"%1\".", + "MATH_ROUND_HELPURL": "http://en.wikipedia.org/wiki/Rounding", + "MATH_ROUND_TOOLTIP": "L\u00e0m tr\u00f2n l\u00ean ho\u1eb7c tr\u00f2n xu\u1ed1ng s\u1ed1 \u0111\u1ea7u v\u00e0o.", + "MATH_ROUND_OPERATOR_ROUND": "l\u00e0m tr\u00f2n", + "MATH_ROUND_OPERATOR_ROUNDUP": "l\u00e0m tr\u00f2n l\u00ean", + "MATH_ROUND_OPERATOR_ROUNDDOWN": "l\u00e0m tr\u00f2n xu\u1ed1ng", + "MATH_ONLIST_HELPURL": "", + "MATH_ONLIST_OPERATOR_SUM": "t\u1ed5ng c\u1ee7a m\u1ed9t danh s\u00e1ch", + "MATH_ONLIST_TOOLTIP_SUM": "Ho\u00e0n tr\u1ea3 t\u1ed5ng s\u1ed1 c\u1ee7a t\u1ea5t c\u1ea3 c\u00e1c s\u1ed1 trong danh s\u00e1ch.", + "MATH_ONLIST_OPERATOR_MIN": "s\u1ed1 nh\u1ecf nh\u1ea5t c\u1ee7a m\u1ed9t danh s\u00e1ch", + "MATH_ONLIST_TOOLTIP_MIN": "Ho\u00e0n tr\u1ea3 s\u1ed1 nh\u1ecf nh\u1ea5t trong t\u1ea5t c\u1ea3 c\u00e1c s\u1ed1 trong danh s\u00e1ch.", + "MATH_ONLIST_OPERATOR_MAX": "s\u1ed1 l\u1edbn nh\u00e2t c\u1ee7a m\u1ed9t danh s\u00e1ch", + "MATH_ONLIST_TOOLTIP_MAX": "Ho\u00e0n tr\u1ea3 s\u1ed1 l\u1edbn nh\u1ea5t trong t\u1ea5t c\u1ea3 c\u00e1c s\u1ed1 trong danh s\u00e1ch.", + "MATH_ONLIST_OPERATOR_AVERAGE": "gi\u00e1 tr\u1ecb trung b\u00ecnh c\u1ee7a m\u1ed9t danh s\u00e1ch", + "MATH_ONLIST_TOOLTIP_AVERAGE": "Ho\u00e0n tr\u1ea3 gi\u00e1 tr\u1ecb trung b\u00ecnh t\u1eeb c\u1ee7a danh s\u00e1ch s\u1ed1.", + "MATH_ONLIST_OPERATOR_MEDIAN": "s\u1ed1 trung v\u1ecb c\u1ee7a m\u1ed9t danh s\u00e1ch", + "MATH_ONLIST_TOOLTIP_MEDIAN": "Ho\u00e0n tr\u1ea3 s\u1ed1 trung v\u1ecb c\u1ee7a danh s\u00e1ch s\u1ed1.", + "MATH_ONLIST_OPERATOR_MODE": "c\u00e1c mode c\u1ee7a m\u1ed9t danh s\u00e1ch", + "MATH_ONLIST_TOOLTIP_MODE": "Ho\u00e0n tr\u1ea3 c\u00e1c s\u1ed1 c\u00f3 m\u1eb7t nhi\u1ec1u nh\u1ea5t trong danh s\u00e1ch.", + "MATH_ONLIST_OPERATOR_STD_DEV": "\u0111\u1ed9 l\u1ec7ch chu\u1ea9n c\u1ee7a m\u1ed9t danh s\u00e1ch", + "MATH_ONLIST_TOOLTIP_STD_DEV": "Ho\u00e0n tr\u1ea3 \u0111\u1ed9 l\u1ec7ch chu\u1ea9n c\u1ee7a danh s\u00e1ch s\u1ed1.", + "MATH_ONLIST_OPERATOR_RANDOM": "m\u1ed9t s\u1ed1 b\u1ea5t k\u1ef3 c\u1ee7a m\u1ed9t danh s\u00e1ch", + "MATH_ONLIST_TOOLTIP_RANDOM": "Ho\u00e0n tr\u1ea3 m\u1ed9t s\u1ed1 b\u1ea5t k\u1ef3 t\u1eeb c\u00e1c s\u1ed1 trong danh s\u00e1ch.", + "MATH_MODULO_HELPURL": "http://en.wikipedia.org/wiki/Modulo_operation", + "MATH_MODULO_TITLE": "s\u1ed1 d\u01b0 c\u1ee7a %1 \u00f7 %2", + "MATH_MODULO_TOOLTIP": "Chia s\u1ed1 th\u1ee9 nh\u1ea5t cho s\u1ed1 th\u1ee9 hai r\u1ed3i ho\u00e0n tr\u1ea3 s\u1ed1 d\u01b0 t\u1eeb.", + "MATH_CONSTRAIN_TITLE": "gi\u1edbi h\u1ea1n %1 kh\u00f4ng d\u01b0\u1edbi %2 kh\u00f4ng h\u01a1n %3", + "MATH_CONSTRAIN_TOOLTIP": "Gi\u1edbi h\u1ea1n s\u1ed1 \u0111\u1ea7u v\u00e0o \u0111\u1ec3 kh\u00f4ng d\u01b0\u1edbi s\u1ed1 th\u1ee9 nh\u1ea5t v\u00e0 kh\u00f4ng h\u01a1n s\u1ed1 th\u1ee9 hai.", + "MATH_RANDOM_INT_HELPURL": "http://en.wikipedia.org/wiki/Random_number_generation", + "MATH_RANDOM_INT_TITLE": "M\u1ed9t s\u1ed1 nguy\u00ean b\u1ea5t k\u1ef3 t\u1eeb %1 \u0111\u1ebfn %2", + "MATH_RANDOM_INT_TOOLTIP": "Ho\u00e0n tr\u1ea3 m\u1ed9t s\u1ed1 nguy\u00ean b\u1ea5t k\u1ef3 l\u1edbn h\u01a1n ho\u1eb7c b\u1eb1ng s\u1ed1 \u0111\u1ea7u v\u00e0 nh\u1ecf h\u01a1n ho\u1eb7c b\u1eb1ng s\u1ed1 sau.", + "MATH_RANDOM_FLOAT_HELPURL": "http://en.wikipedia.org/wiki/Random_number_generation", + "MATH_RANDOM_FLOAT_TITLE_RANDOM": "ph\u00e2n s\u1ed1 b\u1ea5t k\u1ef3", + "MATH_RANDOM_FLOAT_TOOLTIP": "Ho\u00e0n tr\u1ea3 m\u1ed9t ph\u00e2n s\u1ed1 b\u1ea5t k\u1ef3 kh\u00f4ng nh\u1ecf h\u01a1n 0.0 v\u00e0 kh\u00f4ng l\u1edbn h\u01a1n 1.0.", + "TEXT_TEXT_HELPURL": "http://en.wikipedia.org/wiki/string _(computer_science)", + "TEXT_TEXT_TOOLTIP": "M\u1ed9t k\u00fd t\u1ef1, m\u1ed9t t\u1eeb, hay m\u1ed9t d\u00f2ng.", + "TEXT_JOIN_HELPURL": "", + "TEXT_JOIN_TITLE_CREATEWITH": "t\u1ea1o v\u0103n b\u1ea3n t\u1eeb", + "TEXT_JOIN_TOOLTIP": "T\u1ea1o m\u1ed9t v\u0103n b\u1ea3n t\u1eeb c\u00e1c th\u00e0nh ph\u1ea7n.", + "TEXT_CREATE_JOIN_TITLE_JOIN": "k\u1ebft n\u1ed1i", + "TEXT_CREATE_JOIN_TOOLTIP": "Th\u00eam, b\u1ecf, ho\u1eb7c s\u1eafp x\u1ebfp l\u1ea1i c\u00e1c th\u00e0nh ph\u1ea7n \u0111\u1ec3 t\u1ea1o d\u1ef1ng m\u1ea3nh v\u0103n b\u1ea3n n\u00e0y.", + "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "th\u00eam v\u1eadt m\u1edbi v\u00e0o v\u0103n b\u1ea3n.", + "TEXT_APPEND_TO": "\u1edf cu\u1ed1i", + "TEXT_APPEND_APPENDTEXT": "th\u00eam v\u0103n b\u1ea3n", + "TEXT_APPEND_TOOLTIP": "Th\u00eam m\u1ed9t m\u1ea3ng v\u0103n b\u1ea3n v\u00e0o bi\u1ebfn \"%1\".", + "TEXT_LENGTH_TITLE": "\u0111\u1ed9 d\u00e0i c\u1ee7a %1", + "TEXT_LENGTH_TOOLTIP": "Ho\u00e0n tr\u1ea3 s\u1ed1 l\u01b0\u1ee3ng k\u00fd t\u1ef1 (k\u1ec3 c\u1ea3 kho\u1ea3ng tr\u1eafng) trong v\u0103n b\u1ea3n \u0111\u1ea7u v\u00e0o.", + "TEXT_ISEMPTY_TITLE": "%1 tr\u1ed1ng kh\u00f4ng", + "TEXT_ISEMPTY_TOOLTIP": "Ho\u00e0n tr\u1ea3 \u201c\u0111\u00fang n\u1ebfu v\u0103n b\u1ea3n kh\u00f4ng c\u00f3 k\u00fd t\u1ef1 n\u00e0o.", + "TEXT_INDEXOF_TOOLTIP": "Ho\u00e0n tr\u1ea3 v\u1ecb tr\u00ed xu\u1ea5t hi\u1ec7n \u0111\u1ea7u/cu\u1ed1i c\u1ee7a v\u0103n b\u1ea3n th\u1ee9 nh\u1ea5t trong v\u0103n b\u1ea3n th\u1ee9 hai. N\u1ebfu kh\u00f4ng t\u00ecm th\u1ea5y th\u00ec ho\u00e0n tr\u1ea3 s\u1ed1 0.", + "TEXT_INDEXOF_INPUT_INTEXT": "trong v\u0103n b\u1ea3n", + "TEXT_INDEXOF_OPERATOR_FIRST": "t\u00ecm s\u1ef1 c\u00f3 m\u1eb7t \u0111\u1ea7u ti\u00ean c\u1ee7a", + "TEXT_INDEXOF_OPERATOR_LAST": "t\u00ecm s\u1ef1 c\u00f3 m\u1eb7t cu\u1ed1i c\u00f9ng c\u1ee7a", + "TEXT_CHARAT_INPUT_INTEXT": "trong v\u0103n b\u1ea3n", + "TEXT_CHARAT_FROM_START": "l\u1ea5y k\u00fd t\u1ef1 th\u1ee9", + "TEXT_CHARAT_FROM_END": "l\u1ea5y t\u1eeb ph\u00eda cu\u1ed1i, k\u00fd t\u1ef1 th\u1ee9", + "TEXT_CHARAT_FIRST": "l\u1ea5y k\u00fd t\u1ef1 \u0111\u1ea7u ti\u00ean", + "TEXT_CHARAT_LAST": "l\u1ea5y k\u00fd t\u1ef1 cu\u1ed1i c\u00f9ng", + "TEXT_CHARAT_RANDOM": "l\u1ea5y k\u00fd t\u1ef1 b\u1ea5t k\u1ef3", + "TEXT_CHARAT_TAIL": "", + "TEXT_CHARAT_TOOLTIP": "Ho\u00e0n tr\u1ea3 k\u00fd t\u1ef1 \u1edf v\u1ecb tr\u00ed \u0111\u1eb7t ra.", + "TEXT_GET_SUBSTRING_TOOLTIP": "Ho\u00e0n tr\u1ea3 m\u1ed9t m\u1ea3ng k\u00fd t\u1ef1 \u1ea5n \u0111\u1ecbnh t\u1eeb trong v\u0103n b\u1ea3n.", + "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "trong v\u0103n b\u1ea3n", + "TEXT_GET_SUBSTRING_START_FROM_START": "l\u1ea5y t\u1eeb k\u00fd t\u1ef1 th\u1ee9", + "TEXT_GET_SUBSTRING_START_FROM_END": "l\u1ea5y t\u1eeb ph\u00eda cu\u1ed1i, k\u00fd t\u1ef1 th\u1ee9", + "TEXT_GET_SUBSTRING_START_FIRST": "l\u1ea5y t\u1eeb k\u00fd t\u1ef1 \u0111\u1ea7u ti\u00ean", + "TEXT_GET_SUBSTRING_END_FROM_START": "\u0111\u1ebfn k\u00fd t\u1ef1 th\u1ee9", + "TEXT_GET_SUBSTRING_END_FROM_END": "\u0111\u1ebfn t\u1eeb ph\u00eda cu\u1ed1i, k\u00fd t\u1ef1 th\u1ee9", + "TEXT_GET_SUBSTRING_END_LAST": "\u0111\u1ebfn k\u00fd t\u1ef1 cu\u1ed1i c\u00f9ng", + "TEXT_GET_SUBSTRING_TAIL": "", + "TEXT_CHANGECASE_TOOLTIP": "Ho\u00e0n tr\u1ea3 v\u0103n b\u1ea3n sau khi chuy\u1ec3n \u0111\u1ed5i ch\u1eef in hoa hay th\u01b0\u1eddng.", + "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "th\u00e0nh CH\u1eee IN HOA", + "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "th\u00e0nh ch\u1eef th\u01b0\u1eddng", + "TEXT_CHANGECASE_OPERATOR_TITLECASE": "th\u00e0nh Ch\u1eef In \u0110\u1ea7u M\u1ed7i T\u1eeb", + "TEXT_TRIM_TOOLTIP": "Ho\u00e0n tr\u1ea3 b\u1ea3n sao c\u1ee7a v\u0103n b\u1ea3n sau khi x\u00f3a kho\u1ea3ng tr\u1eafng t\u1eeb m\u1ed9t ho\u1eb7c hai b\u00ean.", + "TEXT_TRIM_OPERATOR_BOTH": "x\u00f3a kho\u1ea3ng tr\u1eafng t\u1eeb b\u00ean tr\u00e1i v\u00e0 ph\u1ea3i", + "TEXT_TRIM_OPERATOR_LEFT": "x\u00f3a kho\u1ea3ng tr\u1eafng t\u1eeb b\u00ean tr\u00e1i", + "TEXT_TRIM_OPERATOR_RIGHT": "x\u00f3a kho\u1ea3ng tr\u1eafng t\u1eeb b\u00ean ph\u1ea3i", + "TEXT_PRINT_TITLE": "in l\u00ean m\u00e0ng h\u00ecnh %1", + "TEXT_PRINT_TOOLTIP": "In ra m\u00e0ng h\u00ecnh m\u1ed9t v\u0103n b\u1ea3n, con s\u1ed1, hay m\u1ed9t gi\u00e1 tr\u1ecb \u0111\u1ea7u v\u00e0o kh\u00e1c.", + "TEXT_PROMPT_TYPE_TEXT": "Xin ng\u01b0\u1eddi d\u00f9ng nh\u1eadp v\u00e0o v\u0103n b\u1ea3n v\u1edbi d\u00f2ng h\u01b0\u1edbng d\u1eabn", + "TEXT_PROMPT_TYPE_NUMBER": "Xin ng\u01b0\u1eddi d\u00f9ng nh\u1eadp v\u00e0o con s\u1ed1 v\u1edbi d\u00f2ng h\u01b0\u1edbng d\u1eabn", + "TEXT_PROMPT_TOOLTIP_NUMBER": "Xin ng\u01b0\u1eddi d\u00f9ng nh\u1eadp v\u00e0o m\u1ed9t con s\u1ed1.", + "TEXT_PROMPT_TOOLTIP_TEXT": "Xin ng\u01b0\u1eddi d\u00f9ng nh\u1eadp v\u00e0o m\u1ed9t v\u0103n b\u1ea3n.", + "LISTS_CREATE_EMPTY_TITLE": "t\u1ea1o danh s\u00e1ch tr\u1ed1ng", + "LISTS_CREATE_EMPTY_TOOLTIP": "Ho\u00e0n tr\u1ea3 m\u1ed9t danh s\u00e1ch, v\u1edbi \u0111\u1ed9 d\u00e0i 0, kh\u00f4ng c\u00f3 th\u00e0nh t\u1ed1 n\u00e0o c\u1ea3", + "LISTS_CREATE_WITH_TOOLTIP": "T\u1ea1o m\u1ed9t danh s\u00e1ch bao g\u1ed3m nhi\u1ec1u v\u1eadts, v\u1edbi m\u1ed9t s\u1ed1 l\u01b0\u1ee3ng b\u1ea5t k\u1ef3.", + "LISTS_CREATE_WITH_INPUT_WITH": "t\u1ea1o danh s\u00e1ch g\u1ed3m", + "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "danh s\u00e1ch", + "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Th\u00eam, b\u1ecf, ho\u1eb7c s\u1eafp x\u1ebfp l\u1ea1i c\u00e1c th\u00e0nh ph\u1ea7n \u0111\u1ec3 t\u1ea1o d\u1ef1ng m\u1ea3nh danh s\u00e1ch n\u00e0y.", + "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Th\u00eam v\u1eadt v\u00e0o danh s\u00e1ch.", + "LISTS_REPEAT_TOOLTIP": "T\u1ea1o danh s\u00e1ch g\u1ed3m m\u1ed9t s\u1ed1 l\u01b0\u1ee3ng v\u1eadt nh\u1ea5t \u0111\u1ecbnh v\u1edbi m\u1ed7i v\u1eadt \u0111\u1ec1u gi\u1ed1ng nhau.", + "LISTS_REPEAT_TITLE": "t\u1ea1o danh s\u00e1ch g\u1ed3m m\u1ed9t v\u1eadt %1 l\u1eb7p l\u1ea1i %2 l\u1ea7n", + "LISTS_LENGTH_TITLE": "\u0111\u1ed9 d\u00e0i c\u1ee7a %1", + "LISTS_LENGTH_TOOLTIP": "Ho\u00e0n tr\u1ea3 \u0111\u1ed9 d\u00e0i c\u1ee7a m\u1ed9t danh s\u00e1ch.", + "LISTS_IS_EMPTY_TITLE": "%1 tr\u1ed1ng r\u1ed7ng", + "LISTS_TOOLTIP": "Ho\u00e0n tr\u1ea3 \u201c\u0111\u00fang\" n\u1ebfu danh s\u00e1ch kh\u00f4ng c\u00f3 th\u00e0nh t\u1eed n\u00e0o.", + "LISTS_INLIST": "trong d\u00e1nh s\u00e1ch", + "LISTS_INDEX_OF_FIRST": "t\u00ecm s\u1ef1 c\u00f3 m\u1eb7t \u0111\u1ea7u ti\u00ean c\u1ee7a v\u1eadt", + "LISTS_INDEX_OF_LAST": "t\u00ecm s\u1ef1 c\u00f3 m\u1eb7t cu\u1ed1i c\u00f9ng c\u1ee7a v\u1eadt", + "LISTS_INDEX_OF_TOOLTIP": "Ho\u00e0n tr\u1ea3 v\u1ecb tr\u00ed xu\u1ea5t hi\u1ec7n \u0111\u1ea7u/cu\u1ed1i c\u1ee7a v\u1eadt trong danh s\u00e1ch. N\u1ebfu kh\u00f4ng t\u00ecm th\u1ea5y th\u00ec ho\u00e0n tr\u1ea3 s\u1ed1 0.", + "LISTS_GET_INDEX_GET": "l\u1ea5y th\u00e0nh t\u1ed1", + "LISTS_GET_INDEX_GET_REMOVE": "l\u1ea5y v\u00e0 x\u00f3a th\u00e0nh t\u1ed1", + "LISTS_GET_INDEX_REMOVE": "x\u00f3a th\u00e0nh t\u1ed1", + "LISTS_GET_INDEX_FROM_START": "th\u1ee9", + "LISTS_GET_INDEX_FROM_END": "(\u0111\u1ebfm t\u1eeb cu\u1ed1i) th\u1ee9", + "LISTS_GET_INDEX_FIRST": "\u0111\u1ea7u ti\u00ean", + "LISTS_GET_INDEX_LAST": "cu\u1ed1i c\u00f9ng", + "LISTS_GET_INDEX_RANDOM": "b\u1ea5t k\u1ef3", + "LISTS_GET_INDEX_TOOLTIP_GET_FROM_START": "Ho\u00e0n tr\u1ea3 th\u00e0nh t\u1ed1 trong danh s\u00e1ch \u1edf v\u1ecb tr\u00ed \u1ea5n \u0111\u1ecbnh. S\u1ed1 1 l\u00e0 th\u00e0nh t\u1ed1 \u0111\u1ea7u ti\u00ean.", + "LISTS_GET_INDEX_TOOLTIP_GET_FROM_END": "Ho\u00e0n tr\u1ea3 th\u00e0nh t\u1ed1 trong danh s\u00e1ch \u1edf v\u1ecb tr\u00ed \u1ea5n \u0111\u1ecbnh. S\u1ed1 1 l\u00e0 th\u00e0nh t\u1ed1 cu\u1ed1i c\u00f9ng.", + "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Ho\u00e0n tr\u1ea3 th\u00e0nh t\u1ed1 \u0111\u1ea7u ti\u00ean trong danh s\u00e1ch.", + "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Ho\u00e0n tr\u1ea3 th\u00e0nh t\u1ed1 cu\u1ed1i c\u00f9ng trong danh s\u00e1ch.", + "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Ho\u00e0n tr\u1ea3 m\u1ed9t th\u00e0nh t\u1ed1 b\u1ea5t k\u1ef3 trong danh s\u00e1ch.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START": "Ho\u00e0n tr\u1ea3 v\u00e0 x\u00f3a th\u00e0nh t\u1ed1 trong danh s\u00e1ch \u1edf v\u1ecb tr\u00ed \u1ea5n \u0111\u1ecbnh. S\u1ed1 1 l\u00e0 th\u00e0nh t\u1ed1 \u0111\u1ea7u ti\u00ean.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END": "Ho\u00e0n tr\u1ea3 v\u00e0 x\u00f3a th\u00e0nh t\u1ed1 trong danh s\u00e1ch \u1edf v\u1ecb tr\u00ed \u1ea5n \u0111\u1ecbnh. S\u1ed1 1 l\u00e0 th\u00e0nh t\u1ed1 cu\u1ed1i c\u00f9ng.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Ho\u00e0n tr\u1ea3 v\u00e0 x\u00f3a th\u00e0nh t\u1ed1 \u0111\u1ea7u ti\u00ean trong danh s\u00e1ch.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Ho\u00e0n tr\u1ea3 v\u00e0 x\u00f3a th\u00e0nh t\u1ed1 cu\u1ed1i c\u00f9ng trong danh s\u00e1ch.", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Ho\u00e0n tr\u1ea3 v\u00e0 x\u00f3a m\u1ed9tth\u00e0nh t\u1ed1 b\u1ea5t k\u1ef3 trong danh s\u00e1ch.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START": "X\u00f3a th\u00e0nh t\u1ed1 trong danh s\u00e1ch \u1edf v\u1ecb tr\u00ed \u1ea5n \u0111\u1ecbnh. S\u1ed1 1 l\u00e0 th\u00e0nh t\u1ed1 \u0111\u1ea7u ti\u00ean.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END": "X\u00f3a th\u00e0nh t\u1ed1 trong danh s\u00e1ch \u1edf v\u1ecb tr\u00ed \u1ea5n \u0111\u1ecbnh. S\u1ed1 1 l\u00e0 th\u00e0nh t\u1ed1 cu\u1ed1i c\u00f9ng.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "X\u00f3a th\u00e0nh t\u1ed1 \u0111\u1ea7u ti\u00ean trong danh s\u00e1ch.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "X\u00f3a th\u00e0nh t\u1ed1 cu\u1ed1i c\u00f9ng trong danh s\u00e1ch.", + "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "X\u00f3a th\u00e0nh t\u1ed1 b\u1ea5t k\u1ef3 trong danh s\u00e1ch.", + "LISTS_SET_INDEX_SET": "\u0111\u1eb7t th\u00e0nh t\u1ed1", + "LISTS_SET_INDEX_INSERT": "g\u1eafn ch\u00e8n v\u00e0o v\u1ecb tr\u00ed", + "LISTS_SET_INDEX_INPUT_TO": "gi\u00e1 tr\u1ecb", + "LISTS_SET_INDEX_TOOLTIP_SET_FROM_START": "\u0110\u1eb7t gi\u00e1 tr\u1ecb c\u1ee7a th\u00e0nh t\u1ed1 \u1edf v\u1ecb tr\u00ed \u1ea5n \u0111\u1ecbnh trong m\u1ed9t danh s\u00e1ch. #1 l\u00e0 th\u00e0nh t\u1ed1 \u0111\u1ea7u ti\u00ean.", + "LISTS_SET_INDEX_TOOLTIP_SET_FROM_END": "\u0110\u1eb7t gi\u00e1 tr\u1ecb c\u1ee7a th\u00e0nh t\u1ed1 trong m\u1ed9t danh s\u00e1ch \u1edf v\u1ecb tr\u00ed \u1ea5n \u0111\u1ecbnh t\u1eeb ph\u00eda cu\u1ed1i. #1 l\u00e0 th\u00e0nh t\u1ed1 cu\u1ed1i c\u00f9ng.", + "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "\u0110\u1eb7t gi\u00e1 tr\u1ecb c\u1ee7a th\u00e0nh t\u1ed1 \u0111\u1ea7u ti\u00ean trong danh s\u00e1ch.", + "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "\u0110\u1eb7t gi\u00e1 tr\u1ecb c\u1ee7a th\u00e0nh t\u1ed1 cu\u1ed1i c\u00f9ng trong danh s\u00e1ch.", + "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "\u0110\u1eb7t gi\u00e1 tr\u1ecb c\u1ee7a th\u00e0nh t\u1ed1 ng\u1eabu nhi\u00ean trong danh s\u00e1ch.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START": "G\u1eafn ch\u00e8n v\u1eadt v\u00e0o danh s\u00e1ch theo v\u1ecb tr\u00ed \u1ea5n \u0111\u1ecbnh. #1 l\u00e0 th\u00e0nh t\u1ed1 \u0111\u1ea7u ti\u00ean.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END": "G\u1eafn ch\u00e8n v\u1eadt v\u00e0o danh s\u00e1ch theo v\u1ecb tr\u00ed \u1ea5n \u0111\u1ecbnh t\u1eeb ph\u00eda cu\u1ed1i. #1 l\u00e0 th\u00e0nh t\u1ed1 cu\u1ed1i c\u00f9ng.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "G\u1eafn ch\u00e8n v\u1eadt v\u00e0o \u0111\u1ea7u danh s\u00e1ch.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "G\u1eafn th\u00eam v\u1eadt v\u00e0o cu\u1ed1i danh s\u00e1ch.", + "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "G\u1eafn ch\u00e8n v\u1eadt v\u00e0o danh s\u00e1ch \u1edf v\u1ecb tr\u00ed ng\u1eabu nhi\u00ean.", + "LISTS_GET_SUBLIST_START_FROM_START": "l\u1ea5y m\u1ed9t danh s\u00e1ch con t\u1eeb th\u1ee9", + "LISTS_GET_SUBLIST_START_FROM_END": "l\u1ea5y m\u1ed9t danh s\u00e1ch con t\u1eeb (\u0111\u1ebfm t\u1eeb cu\u1ed1i) th\u1ee9", + "LISTS_GET_SUBLIST_START_FIRST": "l\u1ea5y m\u1ed9t danh s\u00e1ch con t\u1eeb \u0111\u1ea7u ti\u00ean", + "LISTS_GET_SUBLIST_END_FROM_START": "\u0111\u1ebfn th\u1ee9", + "LISTS_GET_SUBLIST_END_FROM_END": "\u0111\u1ebfn (\u0111\u1ebfm t\u1eeb cu\u1ed1i) th\u1ee9", + "LISTS_GET_SUBLIST_END_LAST": "\u0111\u1ebfn cu\u1ed1i c\u00f9ng", + "LISTS_GET_SUBLIST_TOOLTIP": "L\u1ea5y m\u1ed9t m\u1ea3ng c\u1ee7a danh s\u00e1ch n\u00e0y \u0111\u1ec3 t\u1ea1o danh s\u00e1ch con.", + "VARIABLES_GET_TITLE": "", + "VARIABLES_GET_TAIL": "", + "VARIABLES_GET_TOOLTIP": "Ho\u00e0n tr\u1ea3 gi\u00e1 tr\u1ecb c\u1ee7a.", + "VARIABLES_GET_CREATE_SET": "T\u1ea1o m\u1ea3nh \"\u0111\u1eb7t v\u00e0o %1\"", + "VARIABLES_SET_TITLE": "cho", + "VARIABLES_SET_TAIL": "b\u1eb1ng", + "VARIABLES_SET_TOOLTIP": "\u0110\u1eb7t gi\u00e1 tr\u1ecb c\u1ee7a bi\u1ebfn n\u00e0y th\u00e0nh...", + "VARIABLES_SET_CREATE_GET": "T\u1ea1o m\u1ea3nh \"l\u1ea5y %1\"", + "PROCEDURES_DEFNORETURN_TITLE": "", + "PROCEDURES_DEFNORETURN_PROCEDURE": "th\u1ee7 t\u1ee5c", + "PROCEDURES_BEFORE_PARAMS": "v\u1edbi:", + "PROCEDURES_DEFNORETURN_DO": "", + "PROCEDURES_DEFNORETURN_TOOLTIP": "M\u1ed9t th\u1ee7 t\u1ee5c kh\u00f4ng c\u00f3 gi\u00e1 tr\u1ecb ho\u00e0n tr\u1ea3.", + "PROCEDURES_DEFRETURN_RETURN": "ho\u00e0n tr\u1ea3", + "PROCEDURES_DEFRETURN_TOOLTIP": "M\u1ed9t th\u1ee7 t\u1ee5c c\u00f3 gi\u00e1 tr\u1ecb ho\u00e0n tr\u1ea3.", + "PROCEDURES_DEF_DUPLICATE_WARNING": "Ch\u00fa \u00fd: Th\u1ee7 t\u1ee5c n\u00e0y c\u00f3 l\u1eb7p l\u1ea1i t\u00ean c\u00e1c tham s\u1ed1.", + "PROCEDURES_CALLNORETURN_HELPURL": "http://en.wikipedia.org/wiki/procedure _ %28computer_science% 29", + "PROCEDURES_CALLNORETURN_CALL": "th\u1ef1c hi\u1ec7n", + "PROCEDURES_CALLNORETURN_TOOLTIP": "Ch\u1ea1y m\u1ed9t th\u1ee7 t\u1ee5c kh\u00f4ng c\u00f3 gi\u00e1 tr\u1ecb ho\u00e0n tr\u1ea3.", + "PROCEDURES_CALLRETURN_HELPURL": "http://en.wikipedia.org/wiki/procedure _ %28computer_science% 29", + "PROCEDURES_CALLRETURN_TOOLTIP": "Ch\u1ea1y m\u1ed9t th\u1ee7 t\u1ee5c c\u00f3 gi\u00e1 tr\u1ecb ho\u00e0n tr\u1ea3.", + "PROCEDURES_MUTATORCONTAINER_TITLE": "c\u00e1c tham s\u1ed1", + "PROCEDURES_MUTATORARG_TITLE": "bi\u1ebfn:", + "PROCEDURES_HIGHLIGHT_DEF": "L\u00e0m n\u1ed5i b\u1eadt th\u1ee7 t\u1ee5c", + "PROCEDURES_CREATE_DO": "T\u1ea1o m\u1ea3nh \"th\u1ef1c hi\u1ec7n %1\"", + "PROCEDURES_IFRETURN_TOOLTIP": "Khi \u0111i\u1ec1u ki\u1ec7n \u0111\u00fang th\u00ec ho\u00e0n tr\u1ea3 m\u1ed9t gi\u00e1 tr\u1ecb.", + "PROCEDURES_IFRETURN_WARNING": "Ch\u00fa \u00fd: M\u1ea3nh n\u00e0y ch\u1ec9 c\u00f3 th\u1ec3 d\u00f9ng trong m\u1ed9t th\u1ee7 t\u1ee5c." +} \ No newline at end of file diff --git a/msg/json/zh-hans.json b/msg/json/zh-hans.json new file mode 100644 index 000000000..7a2c9abf8 --- /dev/null +++ b/msg/json/zh-hans.json @@ -0,0 +1,193 @@ +{ + "@metadata": { + "authors": [ + "Liuxinyu970226", + "Qiyue2001" + ] + }, + "VARIABLES_DEFAULT_NAME": "\u9879", + "DUPLICATE_BLOCK": "\u590d\u5236", + "ADD_COMMENT": "\u6dfb\u52a0\u6ce8\u91ca", + "REMOVE_COMMENT": "\u5220\u9664\u6ce8\u91ca", + "EXTERNAL_INPUTS": "\u5916\u90e8\u8f93\u5165", + "DELETE_BLOCK": "\u5220\u9664\u5757", + "DELETE_X_BLOCKS": "\u5220\u9664 %1 \u5757", + "COLLAPSE_BLOCK": "\u6298\u53e0\u5757", + "COLLAPSE_ALL": "\u6298\u53e0\u5757", + "EXPAND_BLOCK": "\u5c55\u5f00\u5757", + "EXPAND_ALL": "\u5c55\u5f00\u5757", + "DISABLE_BLOCK": "\u7981\u7528\u5757", + "ENABLE_BLOCK": "\u542f\u7528\u5757", + "HELP": "\u5e2e\u52a9", + "CHANGE_VALUE_TITLE": "\u66f4\u6539\u503c\uff1a", + "NEW_VARIABLE": "\u65b0\u53d8\u91cf...", + "NEW_VARIABLE_TITLE": "\u65b0\u53d8\u91cf\u7684\u540d\u79f0\uff1a", + "RENAME_VARIABLE": "\u91cd\u547d\u540d\u53d8\u91cf...", + "COLOUR_PICKER_HELPURL": "http://zh.wikipedia.org/wiki/\u989c\u8272", + "COLOUR_PICKER_TOOLTIP": "\u4ece\u8c03\u8272\u677f\u4e2d\u9009\u62e9\u4e00\u79cd\u989c\u8272\u3002", + "COLOUR_RANDOM_TITLE": "\u968f\u673a\u989c\u8272", + "COLOUR_RANDOM_TOOLTIP": "\u968f\u673a\u9009\u62e9\u4e00\u79cd\u989c\u8272\u3002", + "COLOUR_RGB_TITLE": "\u989c\u8272\u5e26", + "COLOUR_RGB_RED": "\u7ea2\u8272", + "COLOUR_RGB_GREEN": "\u7eff\u8272", + "COLOUR_RGB_BLUE": "\u84dd\u8272", + "COLOUR_BLEND_TITLE": "\u6df7\u5408", + "COLOUR_BLEND_COLOUR1": "\u989c\u82721", + "COLOUR_BLEND_COLOUR2": "\u989c\u82722", + "COLOUR_BLEND_RATIO": "\u6bd4\u7387", + "CONTROLS_REPEAT_HELPURL": "http://zh.wikipedia.org/wiki/For\u56de\u5708", + "CONTROLS_REPEAT_TITLE": "\u91cd\u590d %1 \u6b21", + "CONTROLS_REPEAT_TITLE_REPEAT": "\u91cd\u590d", + "CONTROLS_REPEAT_TITLE_TIMES": "\u65f6\u95f4", + "CONTROLS_REPEAT_INPUT_DO": "\u505a", + "CONTROLS_REPEAT_TOOLTIP": "\u591a\u6b21\u6267\u884c\u4e00\u4e9b\u8bed\u53e5\u3002", + "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "\u91cd\u590d\u76f4\u5230", + "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "\u53ea\u8981\u503c\u4e3a\u771f\uff0c\u6267\u884c\u4e00\u4e9b\u8bed\u53e5\u3002", + "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "\u53ea\u8981\u503c\u4e3a\u5047\uff0c\u6267\u884c\u4e00\u4e9b\u8bed\u53e5\u3002", + "CONTROLS_FOR_INPUT_FROM_TO_BY": "\u7531%3\u4ece%1\u81f3%2", + "CONTROLS_FOREACH_INPUT_ITEM": "\u4e3a\u6bcf\u4e2a\u9879\u76ee", + "CONTROLS_FOREACH_INPUT_INLIST": "\u5728\u5217\u8868\u4e2d", + "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "\u4e2d\u65ad\u5faa\u73af", + "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "\u4e2d\u65ad\u5305\u542b\u5b83\u7684\u5faa\u73af\u3002", + "CONTROLS_IF_MSG_IF": "\u5982\u679c", + "CONTROLS_IF_MSG_ELSEIF": "\u6216\u8005\u5982\u679c", + "CONTROLS_IF_MSG_ELSE": "\u4e5f", + "LOGIC_COMPARE_HELPURL": "http://zh.wikipedia.org/wiki/\u4e0d\u7b49", + "LOGIC_OPERATION_AND": "\u548c", + "LOGIC_OPERATION_OR": "\u6216", + "LOGIC_NEGATE_TITLE": "\u5e76\u975e%1", + "LOGIC_BOOLEAN_TRUE": "\u6b63", + "LOGIC_BOOLEAN_FALSE": "\u9519", + "LOGIC_NULL": "\u6ee1", + "LOGIC_NULL_TOOLTIP": "\u8fd4\u56de\u7a7a\u503c\u3002", + "LOGIC_TERNARY_HELPURL": "http://zh.wikipedia.org/wiki/\u6761\u4ef6\u8fd0\u7b97\u7b26", + "LOGIC_TERNARY_CONDITION": "\u6d4b\u8bd5", + "LOGIC_TERNARY_IF_TRUE": "\u5982\u679c\u6b63\u786e", + "LOGIC_TERNARY_IF_FALSE": "\u5982\u679c\u65e0\u6548", + "MATH_NUMBER_HELPURL": "http://zh.wikipedia.org/wiki/\u6570\u5b57", + "MATH_NUMBER_TOOLTIP": "\u4e00\u4e2a\u6570\u5b57\u3002", + "MATH_ARITHMETIC_HELPURL": "http://zh.wikipedia.org/wiki/\u7b97\u672f", + "MATH_SINGLE_HELPURL": "http://zh.wikipedia.org/wiki/\u5e73\u65b9\u6839", + "MATH_SINGLE_OP_ROOT": "\u5e73\u65b9\u6839", + "MATH_SINGLE_OP_ABSOLUTE": "\u7edd\u5bf9", + "MATH_SINGLE_TOOLTIP_ABS": "\u8fd4\u56de\u4e00\u4e2a\u6570\u7684\u7edd\u5bf9\u503c\u3002", + "MATH_SINGLE_TOOLTIP_POW10": "\u8fd4\u56de\u6570\u5b57\u768410\u6b21\u5e42\u3002", + "MATH_TRIG_HELPURL": "http://zh.wikipedia.org/wiki/\u4e09\u89d2\u51fd\u6570", + "MATH_CONSTANT_HELPURL": "http://zh.wikipedia.org/wiki/\u6570\u5b66\u5e38\u6570", + "MATH_IS_EVEN": "\u4e43\u81f3\u4e8e", + "MATH_IS_ODD": "\u662f\u5947\u7279\u7684", + "MATH_IS_PRIME": "\u662f\u603b\u7406", + "MATH_IS_WHOLE": "\u4e3a\u6574\u6570", + "MATH_IS_NEGATIVE": "\u4e3a\u8d1f", + "MATH_CHANGE_TITLE_CHANGE": "\u66f4\u6539", + "MATH_CHANGE_INPUT_BY": "\u7531", + "MATH_ROUND_HELPURL": "http://zh.wikipedia.org/wiki/\u56db\u820d\u4e94\u5165", + "MATH_ROUND_OPERATOR_ROUND": "\u5411\u4e0b\u820d\u5165", + "MATH_ROUND_OPERATOR_ROUNDUP": "\u5411\u4e0a\u820d\u5165", + "MATH_ROUND_OPERATOR_ROUNDDOWN": "\u5411\u4e0b\u820d\u5165", + "MATH_ONLIST_OPERATOR_SUM": "\u5217\u8868\u4e2d\u7684\u6570\u7684\u603b\u548c", + "MATH_ONLIST_TOOLTIP_SUM": "\u8fd4\u56de\u5217\u8868\u4e2d\u7684\u6240\u6709\u6570\u5b57\u7684\u548c\u3002", + "MATH_ONLIST_OPERATOR_MIN": "\u5217\u8868\u6700\u5c0f\u503c", + "MATH_ONLIST_TOOLTIP_MIN": "\u8fd4\u56de\u5217\u8868\u4e2d\u6700\u5c0f\u6570\u3002", + "MATH_ONLIST_OPERATOR_MAX": "\u5217\u8868\u6700\u5927\u503c", + "MATH_ONLIST_TOOLTIP_MAX": "\u8fd4\u56de\u5217\u8868\u4e2d\u6700\u5927\u6570\u3002", + "MATH_ONLIST_OPERATOR_AVERAGE": "\u5217\u8868\u4e2d\u7684\u5e73\u5747\u6570", + "MATH_ONLIST_OPERATOR_MEDIAN": "\u5217\u8868\u4e2d\u4f4d\u6570", + "MATH_ONLIST_OPERATOR_MODE": "\u5217\u8868\u6a21\u5f0f", + "MATH_ONLIST_TOOLTIP_STD_DEV": "\u8fd4\u56de\u5217\u8868\u7684\u6807\u51c6\u504f\u5dee\u3002", + "MATH_ONLIST_OPERATOR_RANDOM": "\u5217\u8868\u7684\u968f\u673a\u9879", + "MATH_ONLIST_TOOLTIP_RANDOM": "\u4ece\u5217\u8868\u4e2d\u8fd4\u56de\u4e00\u4e2a\u968f\u673a\u7684\u5143\u7d20\u3002", + "MATH_CONSTRAIN_HELPURL": "http://en.wikipedia.org/wiki/Clamping_%28graphics%29", + "MATH_RANDOM_INT_HELPURL": "http://zh.wikipedia.org/wiki/\u968f\u673a\u6570\u53d1\u751f\u5668", + "MATH_RANDOM_FLOAT_TITLE_RANDOM": "\u968f\u673a\u5206\u6570", + "TEXT_TEXT_HELPURL": "http://zh.wikipedia.org/wiki/\u5b57\u7b26\u4e32", + "TEXT_JOIN_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Text_creation", + "TEXT_CREATE_JOIN_TITLE_JOIN": "\u52a0\u5165", + "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "\u5728\u6587\u672c\u4e2d\u52a0\u5165\u9879\u3002", + "TEXT_APPEND_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Text_modification", + "TEXT_APPEND_TO": "\u81f3", + "TEXT_APPEND_APPENDTEXT": "\u8ffd\u52a0\u6587\u672c", + "TEXT_APPEND_TOOLTIP": "\u5c06\u4e00\u4e9b\u6587\u672c\u8ffd\u52a0\u5230\u53d8\u91cf\u201c%1\u201d\u3002", + "TEXT_LENGTH_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Text_modification", + "TEXT_LENGTH_TITLE": "%1\u7684\u957f\u5ea6", + "TEXT_ISEMPTY_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text", + "TEXT_ISEMPTY_TITLE": "%1\u662f\u7a7a\u7684", + "TEXT_ISEMPTY_TOOLTIP": "\u5982\u679c\u63d0\u4f9b\u7684\u6587\u672c\u4e3a\u7a7a\uff0c\u5219\u8fd4\u56de\u771f\u3002", + "TEXT_INDEXOF_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Finding_text", + "TEXT_INDEXOF_INPUT_INTEXT": "\u4e8e\u6587\u672c\u4e2d", + "TEXT_INDEXOF_TAIL": "\u7a7a\u767d", + "TEXT_CHARAT_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Extracting_text", + "TEXT_CHARAT_INPUT_INTEXT": "\u4e8e\u6587\u672c\u4e2d", + "TEXT_CHARAT_FROM_START": "\u83b7\u5f97\u4fe1\u4ef6#", + "TEXT_CHARAT_FIRST": "\u83b7\u5f97\u7b2c\u4e00\u4e2a\u4fe1\u4ef6", + "TEXT_CHARAT_LAST": "\u83b7\u5f97\u6700\u540e\u4fe1\u4ef6", + "TEXT_CHARAT_RANDOM": "\u83b7\u53d6\u968f\u673a\u7684\u5b57\u6bcd", + "TEXT_CHARAT_TAIL": "\u7a7a\u767d", + "TEXT_GET_SUBSTRING_HELPURL": "http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text", + "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "\u4e8e\u6587\u672c\u4e2d", + "TEXT_GET_SUBSTRING_END_FROM_START": "\u5230\u5b57\u7b26#", + "TEXT_GET_SUBSTRING_END_FROM_END": "\u4ece\u6700\u540e\u81f3\u4fe1\u4ef6#", + "TEXT_GET_SUBSTRING_END_LAST": "\u81f3\u6700\u540e\u4fe1\u4ef6", + "TEXT_GET_SUBSTRING_TAIL": "\u7a7a\u767d", + "TEXT_CHANGECASE_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case", + "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "\u4e3a\u5927\u5199", + "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "\u4e3a\u5c0f\u5199", + "TEXT_CHANGECASE_OPERATOR_TITLECASE": "\u4e3a\u9996\u5b57\u6bcd\u5927\u5199", + "TEXT_TRIM_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces", + "TEXT_PRINT_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Printing_text", + "TEXT_PRINT_TITLE": "\u6253\u5370%1", + "TEXT_PROMPT_HELPURL": "https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user", + "LISTS_CREATE_EMPTY_HELPURL": "http://en.wikipedia.org/wiki/Linked_list#Empty_lists", + "LISTS_CREATE_EMPTY_TITLE": "\u521b\u5efa\u7a7a\u7684\u5217\u8868", + "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "\u5217\u8868", + "LISTS_REPEAT_HELPURL": "https://code.google.com/p/blockly/wiki/Lists#create_list_with", + "LISTS_LENGTH_HELPURL": "https://code.google.com/p/blockly/wiki/Lists#length_of", + "LISTS_LENGTH_TITLE": "%1\u7684\u957f\u5ea6", + "LISTS_LENGTH_TOOLTIP": "\u8fd4\u56de\u5217\u8868\u7684\u957f\u5ea6\u3002", + "LISTS_IS_EMPTY_TITLE": "%1\u662f\u7a7a\u7684", + "LISTS_INLIST": "\u5728\u5217\u8868\u4e2d", + "LISTS_INDEX_OF_HELPURL": "https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List", + "LISTS_GET_INDEX_GET": "\u83b7\u5f97", + "LISTS_GET_INDEX_REMOVE": "\u79fb\u9664", + "LISTS_GET_INDEX_FROM_START": "#", + "LISTS_GET_INDEX_FROM_END": "#\u6765\u81ea\u7ed3\u675f", + "LISTS_GET_INDEX_FIRST": "\u9996\u6b21", + "LISTS_GET_INDEX_LAST": "\u6700\u540e", + "LISTS_GET_INDEX_RANDOM": "\u968f\u673a", + "LISTS_GET_INDEX_TAIL": "\u7a7a\u767d", + "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "\u968f\u673a\u8fd4\u56de\u5217\u8868\u4e2d\u7684\u4e00\u4e2a\u9879\u76ee\u3002", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "\u79fb\u9664\u5e76\u8fd4\u56de\u5217\u8868\u4e2d\u7684\u7b2c\u4e00\u4e2a\u9879\u76ee\u3002", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "\u79fb\u9664\u5e76\u8fd4\u56de\u5217\u8868\u4e2d\u7684\u6700\u540e\u4e00\u4e2a\u9879\u76ee\u3002", + "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "\u79fb\u9664\u5e76\u8fd4\u56de\u5217\u8868\u4e2d\u7684\u4e00\u4e2a\u968f\u673a\u9879\u76ee\u4e2d\u3002", + "LISTS_SET_INDEX_HELPURL": "https://code.google.com/p/blockly/wiki/Lists#in_list_..._set", + "LISTS_SET_INDEX_SET": "\u8bbe\u7f6e", + "LISTS_SET_INDEX_INSERT": "\u63d2\u5165\u5728", + "LISTS_SET_INDEX_INPUT_TO": "\u4f5c\u4e3a", + "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "\u8bbe\u7f6e\u5217\u8868\u4e2d\u7684\u6700\u540e\u4e00\u9879\u3002", + "LISTS_GET_SUBLIST_HELPURL": "https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist", + "LISTS_GET_SUBLIST_END_FROM_START": "\u81f3#", + "LISTS_GET_SUBLIST_END_FROM_END": "\u4ece\u7ed3\u675f\u81f3#", + "LISTS_GET_SUBLIST_END_LAST": "\u81f3\u6700\u540e", + "LISTS_GET_SUBLIST_TAIL": "\u7a7a\u767d", + "ORDINAL_NUMBER_SUFFIX": "\u7a7a\u767d", + "VARIABLES_GET_TITLE": "\u7a7a\u767d", + "VARIABLES_GET_TAIL": "\u7a7a\u767d", + "VARIABLES_GET_CREATE_SET": "\u521b\u5efa'\u83b7\u5f97%1'", + "VARIABLES_SET_HELPURL": "http://code.google.com/p/blockly/wiki/Variables#Set", + "VARIABLES_SET_TITLE": "\u8bbe\u7f6e", + "VARIABLES_SET_TAIL": "\u81f3", + "VARIABLES_SET_CREATE_GET": "\u521b\u5efa'\u83b7\u5f97%1'", + "PROCEDURES_DEFNORETURN_HELPURL": "http://zh.wikipedia.org/wiki/\u5b50\u7a0b\u5e8f", + "PROCEDURES_DEFNORETURN_TITLE": "\u81f3", + "PROCEDURES_DEFNORETURN_PROCEDURE": "\u505a\u70b9\u4ec0\u4e48", + "PROCEDURES_BEFORE_PARAMS": "\u4e0e\uff1a", + "PROCEDURES_DEFNORETURN_DO": "\u7a7a\u767d", + "PROCEDURES_DEFRETURN_HELPURL": "http://zh.wikipedia.org/wiki/\u5b50\u7a0b\u5e8f", + "PROCEDURES_DEFRETURN_RETURN": "\u8fd4\u56de", + "PROCEDURES_CALLNORETURN_HELPURL": "http://zh.wikipedia.org/wiki/\u5b50\u7a0b\u5e8f", + "PROCEDURES_CALLNORETURN_CALL": "\u7a7a\u767d", + "PROCEDURES_CALLRETURN_HELPURL": "http://zh.wikipedia.org/wiki/\u5b50\u7a0b\u5e8f", + "PROCEDURES_MUTATORCONTAINER_TITLE": "\u6295\u5165", + "PROCEDURES_MUTATORARG_TITLE": "\u8f93\u5165\u540d\u79f0\uff1a", + "PROCEDURES_CREATE_DO": "\u521b\u5efa'%1'" +} \ No newline at end of file diff --git a/msg/json/zh_tw.json b/msg/json/zh_tw.json new file mode 100644 index 000000000..a577b7782 --- /dev/null +++ b/msg/json/zh_tw.json @@ -0,0 +1,100 @@ +{"DUPLICATE_BLOCK": "複製", +"REMOVE_COMMENT": "移除註解", +"ADD_COMMENT": "加入註解", +"EXTERNAL_INPUTS": "多行輸入", +"INLINE_INPUTS": "單行輸入", +"DELETE_BLOCK": "刪除積木", +"DELETE_X_BLOCKS": "刪除 %1 塊積木", +"COLLAPSE_BLOCK": "收合積木", +"EXPAND_BLOCK": "展開積木", +"DISABLE_BLOCK": "停用積木", +"ENABLE_BLOCK": "啟用積木", +"HELP": "說明", +"CHANGE_VALUE_TITLE": "修改值:", +"NEW_VARIABLE": "新變量...", +"NEW_VARIABLE_TITLE": "新變量名稱:", +"RENAME_VARIABLE": "重新命名變量...", +"RENAME_VARIABLE_TITLE": "將所有 \"%1\" 變量重新命名為:", +"CONTROLS_REPEAT_TITLE": "重複 %1 次數", +"CONTROLS_REPEAT_TITLE_REPEAT": "重複", +"CONTROLS_REPEAT_TITLE_TIMES": "次數", +"CONTROLS_REPEAT_INPUT_DO": "執行", +"CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "重複 當", +"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "重複 直到", +"CONTROLS_FOR_INPUT_WITH": "使用", +"VARIABLES_DEFAULT_NAME": "變量", +"CONTROLS_FOR_INPUT_FROM_TO_BY": "從範圍 %1 到 %2 每隔 %3", +"CONTROLS_FOREACH_INPUT_ITEM": "取出每個", +"CONTROLS_FOREACH_INPUT_INLIST": "自列表", +"CONTROLS_FOREACH_INPUT_INLIST_TAIL": "", +"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "停止 迴圈", +"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "繼續下一個 迴圈", +"CONTROLS_IF_MSG_ELSEIF": "否則如果", +"CONTROLS_IF_MSG_ELSE": "否則", +"LOGIC_OPERATION_AND": "且", +"LOGIC_OPERATION_OR": "或", +"LOGIC_NEGATE_TITLE": "非 %1", +"LOGIC_BOOLEAN_TRUE": "是", +"LOGIC_BOOLEAN_FALSE": "否", +"LOGIC_NULL": "空", +"MATH_SINGLE_OP_ROOT": "開根號", +"MATH_SINGLE_OP_ABSOLUTE": "絕對值", +"MATH_CHANGE_TITLE_CHANGE": "修改", +"MATH_CHANGE_TITLE_ITEM": "變量", +"MATH_CHANGE_INPUT_BY": "自", +"MATH_ROUND_OPERATOR_ROUND": "四捨五入", +"MATH_ROUND_OPERATOR_ROUNDUP": "無條件進位", +"MATH_ROUND_OPERATOR_ROUNDDOWN": "無條件捨去", +"MATH_ONLIST_OPERATOR_SUM": "總和 自列表", +"MATH_ONLIST_OPERATOR_MIN": "最小值 自列表", +"MATH_ONLIST_OPERATOR_MAX": "最大值 自列表", +"MATH_ONLIST_OPERATOR_AVERAGE": "平均值 自列表", +"MATH_ONLIST_OPERATOR_MEDIAN": "中位數 自列表", +"MATH_ONLIST_OPERATOR_MODE": "比較眾數 自列表", +"MATH_ONLIST_OPERATOR_STD_DEV": "標準差 自列表", +"MATH_ONLIST_OPERATOR_RANDOM": "隨機抽取 自列表", +"MATH_MODULO_TITLE": "取餘數自 %1 \u00f7 %2", +"MATH_CONSTRAIN_TITLE": "限制數字 %1 介於 (低) %2 到 (高) %3", +"MATH_RANDOM_INT_TITLE": "取隨機整數介於 (低) %1 到 %2", +"MATH_RANDOM_FLOAT_TITLE_RANDOM": "取隨機分數", +"TEXT_JOIN_TITLE_CREATEWITH": "建立字串使用", +"TEXT_CREATE_JOIN_TITLE_JOIN": "加入", +"TEXT_CREATE_JOIN_ITEM_TITLE_ITEM": "字串", +"TEXT_APPEND_TO": "在", +"TEXT_APPEND_APPENDTEXT": "後加入文字", +"TEXT_APPEND_VARIABLE": "變量", +"TEXT_LENGTH_TITLE": "長度 %1", +"TEXT_ISEMPTY_TITLE": "%1 為空", +"TEXT_INDEXOF_INPUT_INTEXT": "在字串", +"TEXT_INDEXOF_OPERATOR_FIRST": "尋找 第一個 出現的字串", +"TEXT_INDEXOF_OPERATOR_LAST": "尋找 最後一個 出現的字串", +"TEXT_CHARAT_INPUT_INTEXT": "的字元在字串", +"TEXT_CHARAT_TAIL": "", +"TEXT_CHANGECASE_OPERATOR_UPPERCASE": "改成 轉大寫", +"TEXT_CHANGECASE_OPERATOR_LOWERCASE": "改成 轉小寫", +"TEXT_CHANGECASE_OPERATOR_TITLECASE": "改成 頭字母大寫", +"TEXT_TRIM_OPERATOR_BOTH": "從 兩側 消除空格", +"TEXT_TRIM_OPERATOR_LEFT": "從 左側 消除空格", +"TEXT_TRIM_OPERATOR_RIGHT": "從 右側 消除空格", +"TEXT_PRINT_TITLE": "印出 %1", +"TEXT_PROMPT_TYPE_TEXT": "輸入 文字 並顯示提示訊息", +"TEXT_PROMPT_TYPE_NUMBER": "輸入 數字 並顯示提示訊息", +"LISTS_CREATE_EMPTY_TITLE": "建立空列表", +"LISTS_CREATE_WITH_INPUT_WITH": "使用這些值建立列表", +"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "加入", +"LISTS_CREATE_WITH_ITEM_TITLE": "項目", +"LISTS_REPEAT_TITLE": "建立列表使用項目 %1 重複 %2 次數", +"LISTS_LENGTH_TITLE": "長度 %1", +"LISTS_IS_EMPTY_TITLE": "%1 值為空", +"LISTS_INDEX_OF_FIRST": "找出 第一個 項目出現", +"LISTS_INDEX_OF_LAST": "找出 最後一個 項目出現", +"VARIABLES_GET_TITLE": "", +"VARIABLES_GET_TAIL": "", +"VARIABLES_SET_TITLE": "賦值", +"VARIABLES_SET_TAIL": "", +"PROCEDURES_DEFNORETURN_PROCEDURE": "流程", +"PROCEDURES_DEFRETURN_RETURN": "回傳", +"PROCEDURES_CALLNORETURN_CALL": "呼叫", +"PROCEDURES_MUTATORCONTAINER_TITLE": "參數", +"PROCEDURES_MUTATORARG_TITLE": "變量:" +} diff --git a/msg/messages.js b/msg/messages.js new file mode 100644 index 000000000..f33b970ca --- /dev/null +++ b/msg/messages.js @@ -0,0 +1,1080 @@ +/** + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview English strings. + * @author fraser@google.com (Neil Fraser) + * + * After modifying this file, either run "build.py" from the parent directory, + * or run (from this directory): + * ../i18n/js_to_json.py + * to regenerate json/{en,qqq,synonyms}.json. + * + * To convert all of the json files to .js files, run: + * ../i18n/create_messages.py json/*.json + */ +'use strict'; + +goog.provide('Blockly.Msg.en'); + +goog.require('Blockly.Msg'); + + +/** + * Due to the frequency of long strings, the 80-column wrap rule need not apply + * to message files. + */ + +/** + * Tip: Generate URLs for read-only blocks by creating the blocks in the Code app, + * then evaluating this in the console: + * 'http://blockly-demo.appspot.com/static/apps/code/readonly.html?lang=en&xml=' + encodeURIComponent(Blockly.Xml.domToText(Blockly.Xml.workspaceToDom(Blockly.mainWorkspace)).slice(5, -6)) + */ + +/// default name - A simple, general default name for a variable, preferably short. +/// For more context, see +/// [[Translating:Blockly#infrequent_message_types]]. +Blockly.Msg.VARIABLES_DEFAULT_NAME = 'item'; + +// Context menus. +/// context menu - Make a copy of the selected block (and any blocks it contains). +Blockly.Msg.DUPLICATE_BLOCK = 'Duplicate'; +/// context menu - Add a descriptive comment to the selected block. +Blockly.Msg.ADD_COMMENT = 'Add Comment'; +/// context menu - Remove the descriptive comment from the selected block. +Blockly.Msg.REMOVE_COMMENT = 'Remove Comment'; +/// context menu - Change from 'external' to 'inline' mode for displaying blocks used as inputs to the selected block. See [[Translating:Blockly#context_menus]]. +Blockly.Msg.EXTERNAL_INPUTS = 'External Inputs'; +/// context menu - Change from 'internal' to 'external' mode for displaying blocks used as inputs to the selected block. See [[Translating:Blockly#context_menus]]. +Blockly.Msg.INLINE_INPUTS = 'Inline Inputs'; +/// context menu - Permanently delete the selected block. +Blockly.Msg.DELETE_BLOCK = 'Delete Block'; +/// context menu - Permanently delete the %1 selected blocks.\n\nParameters:\n* %1 - an integer greater than 1. +Blockly.Msg.DELETE_X_BLOCKS = 'Delete %1 Blocks'; +/// context menu - Make the appearance of the selected block smaller by hiding some information about it. +Blockly.Msg.COLLAPSE_BLOCK = 'Collapse Block'; +/// context menu - Make the appearance of the selected blocks smaller by hiding some information about it. Use the same terminology as in the previous message. +Blockly.Msg.COLLAPSE_ALL = 'Collapse Blocks'; +/// context menu - Restore the appearance of the selected block by showing information about it that was hidden (collapsed) earlier. +Blockly.Msg.EXPAND_BLOCK = 'Expand Block'; +/// context menu - Restore the appearance of the selected block by showing information about it that was hidden (collapsed) earlier. Use the same terminology as in the previous message. +Blockly.Msg.EXPAND_ALL = 'Expand Blocks'; +/// context menu - Make the selected block have no effect (unless reenabled). +Blockly.Msg.DISABLE_BLOCK = 'Disable Block'; +/// context menu - Make the selected block have effect (after having been disabled earlier). +Blockly.Msg.ENABLE_BLOCK = 'Enable Block'; +/// context menu - Provide helpful information about the selected block.\n{{Identical|Help}} +Blockly.Msg.HELP = 'Help'; + +// Variable renaming. +/// prompt - This message is only seen in the Opera browser. With most browsers, users can edit numeric values in blocks by just clicking and typing. Opera does not allows this, so we have to open a new window and prompt users with this message to chanage a value. +Blockly.Msg.CHANGE_VALUE_TITLE = 'Change value:'; +/// dropdown choice - When the user clicks on a variable block, this is one of the dropdown menu choices. It is used to define a new variable. See [https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu]. +Blockly.Msg.NEW_VARIABLE = 'New variable...'; +/// prompt - Prompts the user to enter the name for a new variable. See [https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu]. +Blockly.Msg.NEW_VARIABLE_TITLE = 'New variable name:'; +/// dropdown choice - When the user clicks on a variable block, this is one of the dropdown menu choices. It is used to rename the current variable. See [https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu]. +Blockly.Msg.RENAME_VARIABLE = 'Rename variable...'; +/// prompt - Prompts the user to enter the new name for the selected variable. See [https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu].\n\nParameters:\n* %1 - the name of the variable to be renamed. +Blockly.Msg.RENAME_VARIABLE_TITLE = 'Rename all "%1" variables to:'; + +// Colour Blocks. +/// url - Information about colour. +Blockly.Msg.COLOUR_PICKER_HELPURL = 'http://en.wikipedia.org/wiki/Color'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Colour#Picking_a_colour_from_a_palette https://code.google.com/p/blockly/wiki/Colour#Picking_a_colour_from_a_palette]. +Blockly.Msg.COLOUR_PICKER_TOOLTIP = 'Choose a colour from the palette.'; +/// url - A link that displays a random colour each time you visit it. +Blockly.Msg.COLOUR_RANDOM_HELPURL = 'http://randomcolour.com'; +/// block text - Title of block that generates a colour at random. +Blockly.Msg.COLOUR_RANDOM_TITLE = 'random colour'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Colour#Generating_a_random_colour https://code.google.com/p/blockly/wiki/Colour#Generating_a_random_colour]. +Blockly.Msg.COLOUR_RANDOM_TOOLTIP = 'Choose a colour at random.'; +/// url - A link for color codes with percentages (0-100%) for each component, instead of the more common 0-255, which may be more difficult for beginners. +Blockly.Msg.COLOUR_RGB_HELPURL = 'http://www.december.com/html/spec/colorper.html'; +/// block text - Title of block for [https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components]. +Blockly.Msg.COLOUR_RGB_TITLE = 'colour with'; +/// block input text - The amount of red (from 0 to 100) to use when [https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components].\n{{Identical|Red}} +Blockly.Msg.COLOUR_RGB_RED = 'red'; +/// block input text - The amount of green (from 0 to 100) to use when [https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components]. +Blockly.Msg.COLOUR_RGB_GREEN = 'green'; +/// block input text - The amount of blue (from 0 to 100) to use when [https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components].\n{{Identical|Blue}} +Blockly.Msg.COLOUR_RGB_BLUE = 'blue'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components]. +Blockly.Msg.COLOUR_RGB_TOOLTIP = 'Create a colour with the specified amount of red, green, and blue. All values must be between 0 and 100.'; +/// url - A useful link that displays blending of two colors. +Blockly.Msg.COLOUR_BLEND_HELPURL = 'http://meyerweb.com/eric/tools/color-blend/'; +/// block text - A verb for blending two shades of paint. +Blockly.Msg.COLOUR_BLEND_TITLE = 'blend'; +/// block input text - The first of two colours to [https://code.google.com/p/blockly/wiki/Colour#Blending_colours blend]. +Blockly.Msg.COLOUR_BLEND_COLOUR1 = 'colour 1'; +/// block input text - The second of two colours to [https://code.google.com/p/blockly/wiki/Colour#Blending_colours blend]. +Blockly.Msg.COLOUR_BLEND_COLOUR2 = 'colour 2'; +/// block input text - The proportion of the [https://code.google.com/p/blockly/wiki/Colour#Blending_colours blend] containing the first color; the remaining proportion is of the second colour. For example, if the first colour is red and the second color blue, a ratio of 1 would yield pure red, a ratio of .5 would yield purple (equal amounts of red and blue), and a ratio of 0 would yield pure blue. +Blockly.Msg.COLOUR_BLEND_RATIO = 'ratio'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Colour#Blending_colours https://code.google.com/p/blockly/wiki/Colour#Blending_colours]. +Blockly.Msg.COLOUR_BLEND_TOOLTIP = 'Blends two colours together with a given ratio (0.0 - 1.0).'; + +// Loop Blocks. +/// url - Describes 'repeat loops' in computer programs; consider using the translation of the page [http://en.wikipedia.org/wiki/Control_flow http://en.wikipedia.org/wiki/Control_flow]. +Blockly.Msg.CONTROLS_REPEAT_HELPURL = 'http://en.wikipedia.org/wiki/For_loop'; +/// block input text - Title of [https://code.google.com/p/blockly/wiki/Loops#repeat repeat block].\n\nParameters:\n* %1 - the number of times the body of the loop should be repeated. +Blockly.Msg.CONTROLS_REPEAT_TITLE = 'repeat %1 times'; +/// block text - Text preceding the number of repetitions in a [https://code.google.com/p/blockly/wiki/Loops#repeat repeat block]. +/// (This is redundant with the previous message but is needed to support older code.) +Blockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = 'repeat'; +/// block text - Text following the number of times a [https://code.google.com/p/blockly/wiki/Loops#repeat repeat loop] should be repeated. +/// (This is redundant but is needed to support older code.) +Blockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = 'times'; +/// block text - Preceding the blocks in the body of the loop. See [https://code.google.com/p/blockly/wiki/Loops https://code.google.com/p/blockly/wiki/Loops]. +Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = 'do'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Loops#repeat https://code.google.com/p/blockly/wiki/Loops#repeat]. +Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = 'Do some statements several times.'; +/// url - Describes 'while loops' in computer programs; consider using the translation of [http://en.wikipedia.org/wiki/While_loop http://en.wikipedia.org/wiki/While_loop], if present, or [http://en.wikipedia.org/wiki/Control_flow http://en.wikipedia.org/wiki/Control_flow]. +Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = 'http://code.google.com/p/blockly/wiki/Repeat'; +Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +/// dropdown - Specifies that a loop should [https://code.google.com/p/blockly/wiki/Loops#Repeat_while repeat while] the following condition is true. +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = 'repeat while'; +/// dropdown - Specifies that a loop should [https://code.google.com/p/blockly/wiki/Loops#Repeat_until repeat until] the following condition becomes true. +Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = 'repeat until'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Loops#repeat_while Loops#repeat_while https://code.google.com/p/blockly/wiki/Loops#repeat_while Loops#repeat_while]. +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = 'While a value is true, then do some statements.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Loops#repeat_until https://code.google.com/p/blockly/wiki/Loops#repeat_until]. +Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = 'While a value is false, then do some statements.'; + +/// url - Describes 'for loops' in computer programs. Consider using your language's translation of [http://en.wikipedia.org/wiki/For_loop http://en.wikipedia.org/wiki/For_loop], if present. +Blockly.Msg.CONTROLS_FOR_HELPURL = 'https://code.google.com/p/blockly/wiki/Loops#count_with'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Loops#count_with https://code.google.com/p/blockly/wiki/Loops#count_with].\n\nParameters:\n* %1 - the name of the loop variable. +Blockly.Msg.CONTROLS_FOR_TOOLTIP = 'Have the variable %1 take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks.'; +/// block title - Title of [https://code.google.com/p/blockly/wiki/Loops#count_with count with] blocks. +/// [[File:Blockly-count-with.png]] +Blockly.Msg.CONTROLS_FOR_INPUT_WITH = 'count with'; +/// block text - Starting with a (usually lower) number in a range (%1), +/// ending with a (usually higher) number in a range (%2), and counting the +/// iterations by a number of steps (%3). As in +/// [https://code.google.com/p/blockly/wiki/Loops#count_with +/// https://code.google.com/p/blockly/wiki/Loops#count_with]. +/// [[File:Blockly-count-with.png]] +Blockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = 'from %1 to %2 by %3'; +Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; + +/// url - Describes 'for-each loops' in computer programs. Consider using your language's translation of [http://en.wikipedia.org/wiki/Foreach http://en.wikipedia.org/wiki/Foreach] if present. +Blockly.Msg.CONTROLS_FOREACH_HELPURL = 'https://code.google.com/p/blockly/wiki/Loops#for_each for each block'; +/// block text - Title of [https://code.google.com/p/blockly/wiki/Loops#for_each for each block]. +Blockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = 'for each item'; +/// block text - Preceding the list that should be iterated over in a [https://code.google.com/p/blockly/wiki/Loops#for_each for each loop]. +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = 'in list'; +/// block text - Following the list that should be iterated over in a [https://code.google.com/p/blockly/wiki/Loops#for_each for each loop]. This is empty in most, but not all, languages. +Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = ''; +Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +/// block text - Description of [https://code.google.com/p/blockly/wiki/Loops#for_each for each blocks].\n\nParameters:\n* %1 - the name of the loop variable. +Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = 'For each item in a list, set the variable "%1" to the item, and then do some statements.'; + +/// url - Describes control flow in computer programs. Consider using your language's translation of [http://en.wikipedia.org/wiki/Control_flow http://en.wikipedia.org/wiki/Control_flow], if it exists. +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = 'https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks'; +/// dropdown - The current loop should be exited. See [https://code.google.com/p/blockly/wiki/Loops#break https://code.google.com/p/blockly/wiki/Loops#break]. +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = 'break out of loop'; +/// dropdown - The current iteration of the loop should be ended and the next should begin. See [https://code.google.com/p/blockly/wiki/Loops#continue_with_next_iteration https://code.google.com/p/blockly/wiki/Loops#continue_with_next_iteration]. +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = 'continue with next iteration of loop'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Loops#break_out_of_loop https://code.google.com/p/blockly/wiki/Loops#break_out_of_loop]. +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = 'Break out of the containing loop.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Loops#continue_with_next_iteration https://code.google.com/p/blockly/wiki/Loops#continue_with_next_iteration]. +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = 'Skip the rest of this loop, and continue with the next iteration.'; +/// warning - The user has tried placing a block outside of a loop (for each, while, repeat, etc.), but this type of block may only be used within a loop. See [https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks]. +Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = 'Warning: This block may only be used within a loop.'; + +// Logic Blocks. +/// url - Describes conditional statements (if-then-else) in computer programs. Consider using your language's translation of [http://en.wikipedia.org/wiki/If_else http://en.wikipedia.org/wiki/If_else], if present. +Blockly.Msg.CONTROLS_IF_HELPURL = 'http://code.google.com/p/blockly/wiki/If_Then'; +/// tooltip - Describes [https://code.google.com/p/blockly/wiki/IfElse#If_blocks 'if' blocks]. Consider using your language's translation of [http://en.wikipedia.org/wiki/If_statement http://en.wikipedia.org/wiki/If_statement], if present. +Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = 'If a value is true, then do some statements.'; +/// tooltip - Describes [https://code.google.com/p/blockly/wiki/IfElse#If-Else_blocks if-else blocks]. Consider using your language's translation of [http://en.wikipedia.org/wiki/If_statement http://en.wikipedia.org/wiki/If_statement], if present. +Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = 'If a value is true, then do the first block of statements. Otherwise, do the second block of statements.'; +/// tooltip - Describes [https://code.google.com/p/blockly/wiki/IfElse#If-Else-If_blocks if-else-if blocks]. Consider using your language's translation of [http://en.wikipedia.org/wiki/If_statement http://en.wikipedia.org/wiki/If_statement], if present. +Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = 'If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements.'; +/// tooltip - Describes [https://code.google.com/p/blockly/wiki/IfElse#If-Else-If-Else_blocks if-else-if-else blocks]. Consider using your language's translation of [http://en.wikipedia.org/wiki/If_statement http://en.wikipedia.org/wiki/If_statement], if present. +Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = 'If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements. If none of the values are true, do the last block of statements.'; +/// block text - See [https://code.google.com/p/blockly/wiki/IfElse https://code.google.com/p/blockly/wiki/IfElse]. +/// It is recommended, but not essential, that this have text in common with the translation of 'else if' +Blockly.Msg.CONTROLS_IF_MSG_IF = 'if'; +/// block text - See [https://code.google.com/p/blockly/wiki/IfElse https://code.google.com/p/blockly/wiki/IfElse]. The English words "otherwise if" would probably be clearer than "else if", but the latter is used because it is traditional and shorter. +Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = 'else if'; +/// block text - See [https://code.google.com/p/blockly/wiki/IfElse https://code.google.com/p/blockly/wiki/IfElse]. The English word "otherwise" would probably be superior to "else", but the latter is used because it is traditional and shorter. +Blockly.Msg.CONTROLS_IF_MSG_ELSE = 'else'; +Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; +Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; +/// tooltip - Describes [https://code.google.com/p/blockly/wiki/IfElse#Block_Modification if block modification]. +Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = 'Add, remove, or reorder sections to reconfigure this if block.'; +Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; +/// tooltip - Describes the 'else if' subblock during [https://code.google.com/p/blockly/wiki/IfElse#Block_Modification if block modification]. +Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = 'Add a condition to the if block.'; +Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; +/// tooltip - Describes the 'else' subblock during [https://code.google.com/p/blockly/wiki/IfElse#Block_Modification if block modification]. +Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = 'Add a final, catch-all condition to the if block.'; + +/// url - Information about comparisons. +Blockly.Msg.LOGIC_COMPARE_HELPURL = 'http://en.wikipedia.org/wiki/Inequality_(mathematics)'; +/// tooltip - Describes the equals (=) block. +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = 'Return true if both inputs equal each other.'; +/// tooltip - Describes the equals (\u0026ne;) block. +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = 'Return true if both inputs are not equal to each other.'; +/// tooltip - Describes the equals (\u0026lt;) block. +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = 'Return true if the first input is smaller than the second input.'; +/// tooltip - Describes the equals (\u0026le;) block. +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = 'Return true if the first input is smaller than or equal to the second input.'; +/// tooltip - Describes the equals (\u0026gt;) block. +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = 'Return true if the first input is greater than the second input.'; +/// tooltip - Describes the equals (\u0026ge;) block. +Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = 'Return true if the first input is greater than or equal to the second input.'; + +/// url - Information about the Boolean conjunction ("and") and disjunction ("or") operators. Consider using the translation of [http://en.wikipedia.org/wiki/Boolean_logic http://en.wikipedia.org/wiki/Boolean_logic], if it exists in your language. +Blockly.Msg.LOGIC_OPERATION_HELPURL = 'http://code.google.com/p/blockly/wiki/And_Or'; +/// tooltip - See [http://en.wikipedia.org/wiki/Logical_conjunction http://en.wikipedia.org/wiki/Logical_conjunction]. +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = 'Return true if both inputs are true.'; +/// block text - See [http://en.wikipedia.org/wiki/Logical_conjunction http://en.wikipedia.org/wiki/Logical_conjunction]. +Blockly.Msg.LOGIC_OPERATION_AND = 'and'; +/// block text - See [http://en.wikipedia.org/wiki/Disjunction http://en.wikipedia.org/wiki/Disjunction]. +Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = 'Return true if at least one of the inputs is true.'; +/// block text - See [http://en.wikipedia.org/wiki/Disjunction http://en.wikipedia.org/wiki/Disjunction]. +Blockly.Msg.LOGIC_OPERATION_OR = 'or'; + +/// url - Information about logical negation. The translation of [http://en.wikipedia.org/wiki/Logical_negation http://en.wikipedia.org/wiki/Logical_negation] is recommended if it exists in the target language. +Blockly.Msg.LOGIC_NEGATE_HELPURL = 'http://code.google.com/p/blockly/wiki/Not'; +/// block text - This is a unary operator that returns ''false'' when the input is ''true'', and ''true'' when the input is ''false''. +/// \n\nParameters:\n* %1 - the input (which should be either the value "true" or "false") +Blockly.Msg.LOGIC_NEGATE_TITLE = 'not %1'; +/// tooltip - See [http://en.wikipedia.org/wiki/Logical_negation http://en.wikipedia.org/wiki/Logical_negation]. +Blockly.Msg.LOGIC_NEGATE_TOOLTIP = 'Returns true if the input is false. Returns false if the input is true.'; + +/// url - Information about the logic values ''true'' and ''false''. Consider using the translation of [http://en.wikipedia.org/wiki/Truth_value http://en.wikipedia.org/wiki/Truth_value] if it exists in your language. +Blockly.Msg.LOGIC_BOOLEAN_HELPURL = 'http://code.google.com/p/blockly/wiki/True_False'; +/// block text - The word for the [http://en.wikipedia.org/wiki/Truth_value logical value] ''true''. +Blockly.Msg.LOGIC_BOOLEAN_TRUE = 'true'; +/// block text - The word for the [http://en.wikipedia.org/wiki/Truth_value logical value] ''false''. +Blockly.Msg.LOGIC_BOOLEAN_FALSE = 'false'; +/// tooltip - Indicates that the block returns either of the two possible [http://en.wikipedia.org/wiki/Truth_value logical values]. +Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = 'Returns either true or false.'; + +/// url - Provide a link to the translation of [http://en.wikipedia.org/wiki/Nullable_type http://en.wikipedia.org/wiki/Nullable_type], if it exists in your language; otherwise, do not worry about translating this advanced concept. +Blockly.Msg.LOGIC_NULL_HELPURL = 'http://en.wikipedia.org/wiki/Nullable_type'; +/// block text - In computer languages, ''null'' is a special value that indicates that no value has been set. You may use your language's word for "nothing" or "invalid". +Blockly.Msg.LOGIC_NULL = 'null'; +/// tooltip - This should use the word from the previous message. +Blockly.Msg.LOGIC_NULL_TOOLTIP = 'Returns null.'; + +/// url - Describes the programming language operator known as the ''ternary'' or ''conditional'' operator. It is recommended that you use the translation of [http://en.wikipedia.org/wiki/%3F: http://en.wikipedia.org/wiki/%3F:] if it exists. +Blockly.Msg.LOGIC_TERNARY_HELPURL = 'http://en.wikipedia.org/wiki/%3F:'; +/// block input text - Label for the input whose value determines which of the other two inputs is returned. In some programming languages, this is called a ''''predicate''''. +Blockly.Msg.LOGIC_TERNARY_CONDITION = 'test'; +/// block input text - Indicates that the following input should be returned (used as output) if the test input is true. Remember to try to keep block text terse (short). +Blockly.Msg.LOGIC_TERNARY_IF_TRUE = 'if true'; +/// block input text - Indicates that the following input should be returned (used as output) if the test input is false. +Blockly.Msg.LOGIC_TERNARY_IF_FALSE = 'if false'; +/// tooltip - See [http://en.wikipedia.org/wiki/%3F: http://en.wikipedia.org/wiki/%3F:]. +Blockly.Msg.LOGIC_TERNARY_TOOLTIP = 'Check the condition in "test". If the condition is true, returns the "if true" value; otherwise returns the "if false" value.'; + +// Math Blocks. +/// url - Information about (real) numbers. +Blockly.Msg.MATH_NUMBER_HELPURL = 'http://en.wikipedia.org/wiki/Number'; +/// tooltip - Any positive or negative number, not necessarily an integer. +Blockly.Msg.MATH_NUMBER_TOOLTIP = 'A number.'; + +/// math - The symbol for the binary operation addition. +Blockly.Msg.MATH_ADDITION_SYMBOL = '+'; +/// math - The symbol for the binary operation indicating that the right operand should be +/// subtracted from the left operand. +Blockly.Msg.MATH_SUBTRACTION_SYMBOL = '-'; +/// math - The binary operation indicating that the left operand should be divided by +/// the right operand. +Blockly.Msg.MATH_DIVISION_SYMBOL = '\u00F7'; +/// math - The symbol for the binary operation multiplication. +Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = '\u00D7'; +/// math - The symbol for the binary operation exponentiation. Specifically, if the +/// value of the left operand is L and the value of the right operand (the exponent) is +/// R, multiply L by itself R times. (Fractional and negative exponents are also legal.) +Blockly.Msg.MATH_POWER_SYMBOL = '^'; + +/// math - The short name of the trigonometric function +/// [http://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent sine]. +Blockly.Msg.MATH_TRIG_SIN = 'sin'; +/// math - The short name of the trigonometric function +/// [http://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent cosine]. +Blockly.Msg.MATH_TRIG_COS = 'cos'; +/// math - The short name of the trigonometric function +/// [http://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent tangent]. +Blockly.Msg.MATH_TRIG_TAN = 'tan'; +/// math - The short name of the ''inverse of'' the trigonometric function +/// [http://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent sine]. +Blockly.Msg.MATH_TRIG_ASIN = 'asin'; +/// math - The short name of the ''inverse of'' the trigonometric function +/// [http://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent cosine]. +Blockly.Msg.MATH_TRIG_ACOS = 'acos'; +/// math - The short name of the ''inverse of'' the trigonometric function +/// [http://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent tangent]. +Blockly.Msg.MATH_TRIG_ATAN = 'atan'; + +/// url - Information about addition, subtraction, multiplication, division, and exponentiation. +Blockly.Msg.MATH_ARITHMETIC_HELPURL = 'http://en.wikipedia.org/wiki/Arithmetic'; +/// tooltip - See [http://en.wikipedia.org/wiki/Addition http://en.wikipedia.org/wiki/Addition]. +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = 'Return the sum of the two numbers.'; +/// tooltip - See [http://en.wikipedia.org/wiki/Subtraction http://en.wikipedia.org/wiki/Subtraction]. +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = 'Return the difference of the two numbers.'; +/// tooltip - See [http://en.wikipedia.org/wiki/Multiplication http://en.wikipedia.org/wiki/Multiplication]. +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = 'Return the product of the two numbers.'; +/// tooltip - See [http://en.wikipedia.org/wiki/Division_(mathematics) http://en.wikipedia.org/wiki/Division_(mathematics)]. +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = 'Return the quotient of the two numbers.'; +/// tooltip - See [http://en.wikipedia.org/wiki/Exponentiation http://en.wikipedia.org/wiki/Exponentiation]. +Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = 'Return the first number raised to the power of the second number.'; + +/// url - Information about the square root operation. +Blockly.Msg.MATH_SINGLE_HELPURL = 'http://en.wikipedia.org/wiki/Square_root'; +/// dropdown - This computes the positive [http://en.wikipedia.org/wiki/Square_root square root] of its input. For example, the square root of 16 is 4. +Blockly.Msg.MATH_SINGLE_OP_ROOT = 'square root'; +/// tooltip - Please use the same term as in the previous message. +Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = 'Return the square root of a number.'; +/// dropdown - This leaves positive numeric inputs changed and inverts negative inputs. For example, the absolute value of 5 is 5; the absolute value of -5 is also 5. For more information, see [http://en.wikipedia.org/wiki/Absolute_value http://en.wikipedia.org/wiki/Absolute_value]. +Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = 'absolute'; +/// tooltip - Please use the same term as in the previous message. +Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = 'Return the absolute value of a number.'; + +/// tooltip - Calculates '''0-n''', where '''n''' is the single numeric input. +Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = 'Return the negation of a number.'; +/// tooltip - Calculates the [http://en.wikipedia.org/wiki/Natural_logarithm|natural logarithm] of its single numeric input. +Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = 'Return the natural logarithm of a number.'; +/// tooltip - Calculates the [http://en.wikipedia.org/wiki/Common_logarithm common logarithm] of its single numeric input. +Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = 'Return the base 10 logarithm of a number.'; +/// tooltip - Multiplies [http://en.wikipedia.org/wiki/E_%28mathematical_constant%29 e] by itself n times, where n is the single numeric input. +Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = 'Return e to the power of a number.'; +/// tooltip - Multiplies 10 by itself n times, where n is the single numeric input. +Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = 'Return 10 to the power of a number.'; + +/// url - Information about the trigonometric functions sine, cosine, tangent, and their inverses (ideally using degrees, not radians). +Blockly.Msg.MATH_TRIG_HELPURL = 'http://en.wikipedia.org/wiki/Trigonometric_functions'; +/// tooltip - Return the [http://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent sine] of an [http://en.wikipedia.org/wiki/Degree_(angle) angle in degrees], not radians. +Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = 'Return the sine of a degree (not radian).'; +/// tooltip - Return the [http://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent cosine] of an [http://en.wikipedia.org/wiki/Degree_(angle) angle in degrees], not radians. +Blockly.Msg.MATH_TRIG_TOOLTIP_COS = 'Return the cosine of a degree (not radian).'; +/// tooltip - Return the [http://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent tangent] of an [http://en.wikipedia.org/wiki/Degree_(angle) angle in degrees], not radians. +Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = 'Return the tangent of a degree (not radian).'; +/// tooltip - The [http://en.wikipedia.org/wiki/Inverse_trigonometric_functions inverse] of the [http://en.wikipedia.org/wiki/Cosine#Sine.2C_cosine_and_tangent sine function], using [http://en.wikipedia.org/wiki/Degree_(angle) degrees], not radians. +Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = 'Return the arcsine of a number.'; +/// tooltip - The [http://en.wikipedia.org/wiki/Inverse_trigonometric_functions inverse] of the [http://en.wikipedia.org/wiki/Cosine#Sine.2C_cosine_and_tangent cosine] function, using [http://en.wikipedia.org/wiki/Degree_(angle) degrees], not radians. +Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = 'Return the arccosine of a number.'; +/// tooltip - The [http://en.wikipedia.org/wiki/Inverse_trigonometric_functions inverse] of the [http://en.wikipedia.org/wiki/Cosine#Sine.2C_cosine_and_tangent tangent] function, using [http://en.wikipedia.org/wiki/Degree_(angle) degrees], not radians. +Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = 'Return the arctangent of a number.'; + +/// url - Information about the mathematical constants \u0026pi;, e, the golden ratio (\u0026phi;), \u0026radic; 2, \u0026radic; 1/2, and infinity (\u0026infin;). +Blockly.Msg.MATH_CONSTANT_HELPURL = 'http://en.wikipedia.org/wiki/Mathematical_constant'; +/// tooltip - Provides the specified [http://en.wikipedia.org/wiki/Mathematical_constant mathematical constant]. +Blockly.Msg.MATH_CONSTANT_TOOLTIP = 'Return one of the common constants: \u03c0 (3.141\u2026), e (2.718\u2026), \u03c6 (1.618\u2026), sqrt(2) (1.414\u2026), sqrt(\u00bd) (0.707\u2026), or \u221e (infinity).'; +/// dropdown - A number is '''even''' if it is a multiple of 2. For example, 4 is even (yielding true), but 3 is not (false). +Blockly.Msg.MATH_IS_EVEN = 'is even'; +/// dropdown - A number is '''odd''' if it is not a multiple of 2. For example, 3 is odd (yielding true), but 4 is not (false). The opposite of "odd" is "even". +Blockly.Msg.MATH_IS_ODD = 'is odd'; +/// dropdown - A number is [http://en.wikipedia.org/wiki/Prime prime] if it cannot be evenly divided by any positive integers except for 1 and itself. For example, 5 is prime, but 6 is not because 2 \u0026times; 3 = 6. +Blockly.Msg.MATH_IS_PRIME = 'is prime'; +/// dropdown - A number is '''whole''' if it is an [http://en.wikipedia.org/wiki/Integer integer]. For example, 5 is whole, but 5.1 is not. +Blockly.Msg.MATH_IS_WHOLE = 'is whole'; +/// dropdown - A number is '''positive''' if it is greater than 0. (0 is neither negative nor positive.) +Blockly.Msg.MATH_IS_POSITIVE = 'is positive'; +/// dropdown - A number is '''negative''' if it is less than 0. (0 is neither negative nor positive.) +Blockly.Msg.MATH_IS_NEGATIVE = 'is negative'; +/// dropdown - A number x is divisible by y if y goes into x evenly. For example, 10 is divisible by 5, but 10 is not divisible by 3. +Blockly.Msg.MATH_IS_DIVISIBLE_BY = 'is divisible by'; +/// tooltip - This block lets the user specify via a dropdown menu whether to check if the numeric input is even, odd, prime, whole, positive, negative, or divisible by a given value. +Blockly.Msg.MATH_IS_TOOLTIP = 'Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false.'; + +/// url - Information about incrementing (increasing the value of) a variable. +Blockly.Msg.MATH_CHANGE_HELPURL = 'http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter'; +/// - As in: '''change''' [the value of variable] ''item by'' 1 (e.g., if the variable named 'item' had the value 5, change it to 6). +Blockly.Msg.MATH_CHANGE_TITLE_CHANGE = 'change'; +Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +/// - As in: ''change'' [the value of variable] ''item'' '''by''' 1 (e.g., if the variable named 'item' had the value 5, change it to 6). +Blockly.Msg.MATH_CHANGE_INPUT_BY = 'by'; +/// tooltip - This updates the value of the variable by adding to it the following numeric input.\n\nParameters:\n* %1 - the name of the variable whose value should be increased. +Blockly.Msg.MATH_CHANGE_TOOLTIP = 'Add a number to variable "%1".'; + +/// url - Information about how numbers are rounded to the nearest integer +Blockly.Msg.MATH_ROUND_HELPURL = 'http://en.wikipedia.org/wiki/Rounding'; +/// tooltip - See [http://en.wikipedia.org/wiki/Rounding http://en.wikipedia.org/wiki/Rounding]. +Blockly.Msg.MATH_ROUND_TOOLTIP = 'Round a number up or down.'; +/// dropdown - This rounds its input to the nearest whole number. For example, 3.4 is rounded to 3. +Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = 'round'; +/// dropdown - This rounds its input up to the nearest whole number. For example, if the input was 2.2, the result would be 3. +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = 'round up'; +/// dropdown - This rounds its input down to the nearest whole number. For example, if the input was 3.8, the result would be 3. +Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = 'round down'; + +/// url - Information about applying a function to a list of numbers. (We were unable to find such information in English. Feel free to skip this and any other URLs that are difficult.) +Blockly.Msg.MATH_ONLIST_HELPURL = ''; +/// dropdown - This computes the sum of the numeric elements in the list. For example, the sum of the list {1, 4} is 5. +Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = 'sum of list'; +/// tooltip - Please use the same term for "sum" as in the previous message. +Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = 'Return the sum of all the numbers in the list.'; +/// dropdown - This finds the smallest (minimum) number in a list. For example, the smallest number in the list [-5, 0, 3] is -5. +Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = 'min of list'; +/// tooltip - Please use the same term for "min" or "minimum" as in the previous message. +Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = 'Return the smallest number in the list.'; +/// dropdown - This finds the largest (maximum) number in a list. For example, the largest number in the list [-5, 0, 3] is 3. +Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = 'max of list'; +/// tooltip +Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = 'Return the largest number in the list.'; +/// dropdown - This adds up all of the numbers in a list and divides the sum by the number of elements in the list. For example, the [http://en.wikipedia.org/wiki/Arithmetic_mean average] of the list [1, 2, 3, 4] is 2.5 (10/4). +Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = 'average of list'; +/// tooltip - See [http://en.wikipedia.org/wiki/Arithmetic_mean http://en.wikipedia.org/wiki/Arithmetic_mean] for more informatin. +Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = 'Return the average (arithmetic mean) of the numeric values in the list.'; +/// dropdown - This finds the [http://en.wikipedia.org/wiki/Median median] of the numeric values in a list. For example, the median of the list {1, 2, 7, 12, 13} is 7. +Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = 'median of list'; +/// tooltip - See [http://en.wikipedia.org/wiki/Median median http://en.wikipedia.org/wiki/Median median] for more information. +Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = 'Return the median number in the list.'; +/// dropdown - This finds the most common numbers ([http://en.wikipedia.org/wiki/Mode_(statistics) modes]) in a list. For example, the modes of the list {1, 3, 9, 3, 9} are {3, 9}. +Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = 'modes of list'; +/// tooltip - See [http://en.wikipedia.org/wiki/Mode_(statistics) http://en.wikipedia.org/wiki/Mode_(statistics)] for more information. +Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = 'Return a list of the most common item(s) in the list.'; +/// dropdown - This finds the [http://en.wikipedia.org/wiki/Standard_deviation standard deviation] of the numeric values in a list. +Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = 'standard deviation of list'; +/// tooltip - See [http://en.wikipedia.org/wiki/Standard_deviation http://en.wikipedia.org/wiki/Standard_deviation] for more information. +Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = 'Return the standard deviation of the list.'; +/// dropdown - This choose an element at random from a list. Each element is chosen with equal probability. +Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = 'random item of list'; +/// tooltip - Please use same term for 'random' as in previous entry. +Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = 'Return a random element from the list.'; + +/// url - information about the modulo (remainder) operation. +Blockly.Msg.MATH_MODULO_HELPURL = 'http://en.wikipedia.org/wiki/Modulo_operation'; +/// block text - Title of block providing the remainder when dividing the first numerical input by the second. For example, the remainder of 10 divided by 3 is 1.\n\nParameters:\n* %1 - the dividend (10, in our example)\n* %2 - the divisor (3 in our example). +Blockly.Msg.MATH_MODULO_TITLE = 'remainder of %1 ÷ %2'; +/// tooltip - For example, the remainder of 10 divided by 3 is 1. +Blockly.Msg.MATH_MODULO_TOOLTIP = 'Return the remainder from dividing the two numbers.'; + +/// url - Information about constraining a numeric value to be in a specific range. (The English URL is not ideal. Recall that translating URLs is the lowest priority.) +Blockly.Msg.MATH_CONSTRAIN_HELPURL = 'http://en.wikipedia.org/wiki/Clamping_%28graphics%29'; +/// block text - The title of the block that '''constrain'''s (forces) a number to be in a given range. +///For example, if the number 150 is constrained to be between 5 and 100, the result will be 100. +///\n\nParameters:\n* %1 - the value to constrain (e.g., 150)\n* %2 - the minimum value (e.g., 5)\n* %3 - the maximum value (e.g., 100). +Blockly.Msg.MATH_CONSTRAIN_TITLE = 'constrain %1 low %2 high %3'; +/// tooltip - This compares a number ''x'' to a low value ''L'' and a high value ''H''. If ''x'' is less then ''L'', the result is ''L''. If ''x'' is greater than ''H'', the result is ''H''. Otherwise, the result is ''x''. +Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = 'Constrain a number to be between the specified limits (inclusive).'; + +/// url - Information about how computers generate random numbers. +Blockly.Msg.MATH_RANDOM_INT_HELPURL = 'http://en.wikipedia.org/wiki/Random_number_generation'; +/// block text - The title of the block that generates a random integer (whole number) in the specified range. For example, if the range is from 5 to 7, this returns 5, 6, or 7 with equal likelihood. %1 is a placeholder for the lower number, %2 is the placeholder for the larger number. +Blockly.Msg.MATH_RANDOM_INT_TITLE = 'random integer from %1 to %2'; +/// tooltip - Return a random integer between two values specified as inputs. For example, if one input was 7 and another 9, any of the numbers 7, 8, or 9 could be produced. +Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = 'Return a random integer between the two specified limits, inclusive.'; + +/// url - Information about how computers generate random numbers (specifically, numbers in the range from 0 to just below 1). +Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = 'http://en.wikipedia.org/wiki/Random_number_generation'; +/// block text - The title of the block that generates a random number greater than or equal to 0 and less than 1. +Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = 'random fraction'; +/// tooltip - Return a random fraction between 0 and 1. The value may be equal to 0 but must be less than 1. +Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = 'Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive).'; + +// Text Blocks. +/// url - Information about how computers represent text (sometimes referred to as ''string''s). +Blockly.Msg.TEXT_TEXT_HELPURL = 'http://en.wikipedia.org/wiki/String_(computer_science)'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Text#Introduction https://code.google.com/p/blockly/wiki/Text#Introduction]. +Blockly.Msg.TEXT_TEXT_TOOLTIP = 'A letter, word, or line of text.'; + +/// url - Information on concatenating/appending pieces of text. +Blockly.Msg.TEXT_JOIN_HELPURL = 'https://code.google.com/p/blockly/wiki/Text#Text_creation'; +/// block text - See [https://code.google.com/p/blockly/wiki/Text#Text_creation https://code.google.com/p/blockly/wiki/Text#Text_creation]. +Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = 'create text with'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Text#Text_creation create text with] for more information. +Blockly.Msg.TEXT_JOIN_TOOLTIP = 'Create a piece of text by joining together any number of items.'; + +/// block text - This is shown when the programmer wants to change the number of pieces of text being joined together. See [https://code.google.com/p/blockly/wiki/Text#Text_creation https://code.google.com/p/blockly/wiki/Text#Text_creation], specifically the last picture in the 'Text creation' section. +Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = 'join'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Text#Text_creation https://code.google.com/p/blockly/wiki/Text#Text_creation], specifically the last picture in the 'Text creation' section. +Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = 'Add, remove, or reorder sections to reconfigure this text block.'; +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +/// block text - See [https://code.google.com/p/blockly/wiki/Text#Text_creation https://code.google.com/p/blockly/wiki/Text#Text_creation], specifically the last picture in the 'Text creation' section. +Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = 'Add an item to the text.'; + +/// url - This and the other text-related URLs are going to be hard to translate. As always, it is okay to leave untranslated or paste in the English-language URL. For these URLs, you might also consider a general URL about how computers represent text (such as the translation of [http://en.wikipedia.org/wiki/String_(computer_science) this Wikipedia page]). +Blockly.Msg.TEXT_APPEND_HELPURL = 'https://code.google.com/p/blockly/wiki/Text#Text_modification'; +/// block input text - Message preceding the name of a variable to which text should be appended. +/// [[File:blockly-append-text.png]] +Blockly.Msg.TEXT_APPEND_TO = 'to'; +/// block input text - Message following the variable and preceding the piece of text that should +/// be appended, as shown below. +/// [[File:blockly-append-text.png]] +Blockly.Msg.TEXT_APPEND_APPENDTEXT = 'append text'; +Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Text#Text_modification https://code.google.com/p/blockly/wiki/Text#Text_modification] for more information.\n\nParameters:\n* %1 - the name of the variable to which text should be appended +Blockly.Msg.TEXT_APPEND_TOOLTIP = 'Append some text to variable "%1".'; + +/// url - Information about text on computers (usually referred to as 'strings'). +Blockly.Msg.TEXT_LENGTH_HELPURL = 'https://code.google.com/p/blockly/wiki/Text#Text_modification'; +/// block text - See [https://code.google.com/p/blockly/wiki/Text#Text_length https://code.google.com/p/blockly/wiki/Text#Text_length]. +/// \n\nParameters:\n* %1 - the piece of text to take the length of +Blockly.Msg.TEXT_LENGTH_TITLE = 'length of %1'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Text#Text_length https://code.google.com/p/blockly/wiki/Text#Text_length]. +Blockly.Msg.TEXT_LENGTH_TOOLTIP = 'Returns the number of letters (including spaces) in the provided text.'; + +/// url - Information about empty pieces of text on computers (usually referred to as 'empty strings'). +Blockly.Msg.TEXT_ISEMPTY_HELPURL = 'https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text'; +/// block text - See [https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text]. +/// \n\nParameters:\n* %1 - the piece of text to test for emptiness +Blockly.Msg.TEXT_ISEMPTY_TITLE = '%1 is empty'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text]. +Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = 'Returns true if the provided text is empty.'; + +/// url - Information about finding a character in a piece of text. +Blockly.Msg.TEXT_INDEXOF_HELPURL = 'https://code.google.com/p/blockly/wiki/Text#Finding_text'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Text#Finding_text https://code.google.com/p/blockly/wiki/Text#Finding_text]. +Blockly.Msg.TEXT_INDEXOF_TOOLTIP = 'Returns the index of the first/last occurrence of first text in the second text. Returns 0 if text is not found.'; +/// block text - Title of blocks allowing users to find text. See +/// [https://code.google.com/p/blockly/wiki/Text#Finding_text +/// https://code.google.com/p/blockly/wiki/Text#Finding_text]. +/// [[File:Blockly-find-text.png]]. +Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = 'in text'; +/// dropdown - See [https://code.google.com/p/blockly/wiki/Text#Finding_text +/// https://code.google.com/p/blockly/wiki/Text#Finding_text]. +/// [[File:Blockly-find-text.png]]. +Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = 'find first occurrence of text'; +/// dropdown - See [https://code.google.com/p/blockly/wiki/Text#Finding_text +/// https://code.google.com/p/blockly/wiki/Text#Finding_text]. This would +/// replace "find first occurrence of text" below. (For more information on +/// how common text is factored out of dropdown menus, see +/// [http://translatewiki.net/wiki/Translating:Blockly#Drop-Down_Menus +/// http://translatewiki.net/wiki/Translating:Blockly#Drop-Down_Menus)].) +/// [[File:Blockly-find-text.png]]. +Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = 'find last occurrence of text'; +/// block text - Optional text to follow the rightmost block in a +/// [https://code.google.com/p/blockly/wiki/Text#Finding_text +/// https://code.google.com/p/blockly/wiki/Text#Finding_text in text ... find block] +/// (after the "a" in the below picture). This will be the empty string in most languages. +/// [[File:Blockly-find-text.png]]. +Blockly.Msg.TEXT_INDEXOF_TAIL = ''; + +/// url - Information about extracting characters (letters, number, symbols, etc.) from text. +Blockly.Msg.TEXT_CHARAT_HELPURL = 'https://code.google.com/p/blockly/wiki/Text#Extracting_text'; +/// block text - Appears before the piece of text from which a letter (or number, +/// punctuation character, etc.) should be extracted, as shown below. See +/// [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character +/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character]. +/// [[File:Blockly-text-get.png]] +Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = 'in text'; +/// dropdown - Indicates that the letter (or number, punctuation character, etc.) with the +/// specified index should be obtained from the preceding piece of text. See +/// [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character +/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character]. +/// [[File:Blockly-text-get.png]] +Blockly.Msg.TEXT_CHARAT_FROM_START = 'get letter #'; +/// block text - Indicates that the letter (or number, punctuation character, etc.) with the +/// specified index from the end of a given piece of text should be obtained. See +/// [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character +/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character]. +/// [[File:Blockly-text-get.png]] +Blockly.Msg.TEXT_CHARAT_FROM_END = 'get letter # from end'; +/// block text - Indicates that the first letter of the following piece of text should be +/// retrieved. See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character +/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character]. +/// [[File:Blockly-text-get.png]] +Blockly.Msg.TEXT_CHARAT_FIRST = 'get first letter'; +/// block text - Indicates that the last letter (or number, punctuation mark, etc.) of the +/// following piece of text should be retrieved. See +/// [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character +/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character]. +/// [[File:Blockly-text-get.png]] +Blockly.Msg.TEXT_CHARAT_LAST = 'get last letter'; +/// block text - Indicates that any letter (or number, punctuation mark, etc.) in the +/// following piece of text should be randomly selected. See +/// [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character +/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character]. +/// [[File:Blockly-text-get.png]] +Blockly.Msg.TEXT_CHARAT_RANDOM = 'get random letter'; +/// block text - Text that goes after the rightmost block/dropdown when getting a single letter from +/// a piece of text, as in [http://blockly-demo.appspot.com/static/apps/code/index.html#3m23km these +/// blocks] or shown below. For most languages, this will be blank. +/// [[File:Blockly-text-get.png]] +Blockly.Msg.TEXT_CHARAT_TAIL = ''; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character +/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character]. +/// [[File:Blockly-text-get.png]] +Blockly.Msg.TEXT_CHARAT_TOOLTIP = 'Returns the letter at the specified position.'; + +/// See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text +/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text]. +Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = 'Returns a specified portion of the text.'; +/// url - Information about extracting characters from text. Reminder: urls are the +/// lowest priority translations. Feel free to skip. +Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = 'http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text'; +/// block text - Precedes a piece of text from which a portion should be extracted. +/// [[File:Blockly-get-substring.png]] +Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = 'in text'; +/// dropdown - Indicates that the following number specifies the position (relative to the start +/// position) of the beginning of the region of text that should be obtained from the preceding +/// piece of text. See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text +/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text]. +/// [[File:Blockly-get-substring.png]] +Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = 'get substring from letter #'; +/// dropdown - Indicates that the following number specifies the position (relative to the end +/// position) of the beginning of the region of text that should be obtained from the preceding +/// piece of text. See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text +/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text]. +/// Note: If {{msg-Blockly|ORDINAL_NUMBER_SUFFIX}} is defined, it will +/// automatically appear ''after'' this and any other +/// [http://translatewiki.net/wiki/Translating:Blockly#Ordinal_numbers ordinal numbers] +/// on this block. +/// [[File:Blockly-get-substring.png]] +Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = 'get substring from letter # from end'; +/// block text - Indicates that a region starting with the first letter of the preceding piece +/// of text should be extracted. See +/// [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text +/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text]. +/// [[File:Blockly-get-substring.png]] +Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = 'get substring from first letter'; +/// dropdown - Indicates that the following number specifies the position (relative to +/// the start position) of the end of the region of text that should be obtained from the +/// preceding piece of text. See [ +/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text +/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text]. +/// [[File:Blockly-get-substring.png]] +Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = 'to letter #'; +/// dropdown - Indicates that the following number specifies the position (relative to the +/// end position) of the end of the region of text that should be obtained from the preceding +/// piece of text. See +/// [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text +/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text]. +/// [[File:Blockly-get-substring.png]] +Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = 'to letter # from end'; +/// block text - Indicates that a region ending with the last letter of the preceding piece +/// of text should be extracted. See +/// [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text +/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text]. +/// [[File:Blockly-get-substring.png]] +Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = 'to last letter'; +/// block text - Text that should go after the rightmost block/dropdown when +/// [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text +/// extracting a region of text]. In most languages, this will be the empty string. +/// [[File:Blockly-get-substring.png]] +Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ''; + +/// url - Information about the case of letters (upper-case and lower-case). +Blockly.Msg.TEXT_CHANGECASE_HELPURL = 'https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case' +/// tooltip - Describes a block to adjust the case of letters. For more information on this block, +/// see [https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case +/// https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case]. +Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = 'Return a copy of the text in a different case.'; +/// block text - Indicates that all of the letters in the following piece of text should be +/// capitalized. If your language does not use case, you may indicate that this is not +/// applicable to your language. For more information on this block, see +/// [https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case +/// https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case]. +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = 'to UPPER CASE'; +/// block text - Indicates that all of the letters in the following piece of text should be converted to lower-case. If your language does not use case, you may indicate that this is not applicable to your language. For more information on this block, see [https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case]. +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = 'to lower case'; +/// block text - Indicates that the first letter of each of the following words should be capitalized and the rest converted to lower-case. If your language does not use case, you may indicate that this is not applicable to your language. For more information on this block, see [https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case]. +Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = 'to Title Case'; + +/// url - Information about trimming (removing) text off the beginning and ends of pieces of text. +Blockly.Msg.TEXT_TRIM_HELPURL = 'https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces +/// https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces]. +Blockly.Msg.TEXT_TRIM_TOOLTIP = 'Return a copy of the text with spaces removed from one or both ends.'; +/// dropdown - Removes spaces from the beginning and end of a piece of text. See +/// [https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces +/// https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces]. Note that neither +/// this nor the other options modify the original piece of text (that appears to the right); +/// the block just returns a version of the text without the specified spaces. +Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = 'trim spaces from both sides'; +/// dropdown - Removes spaces from the beginning of a piece of text. See +/// [https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces +/// https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces]. +/// Note that in right-to-left scripts, this will remove spaces from the right side. +Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = 'trim spaces from left side'; +/// dropdown - Removes spaces from the end of a piece of text. See +/// [https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces +/// https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces]. +/// Note that in right-to-left scripts, this will remove spaces from the left side. +Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = 'trim spaces from right side'; + +/// url - Information about displaying text on computers. +Blockly.Msg.TEXT_PRINT_HELPURL = 'https://code.google.com/p/blockly/wiki/Text#Printing_text'; +/// block text - Display the input on the screen. See +/// [https://code.google.com/p/blockly/wiki/Text#Printing_text +/// https://code.google.com/p/blockly/wiki/Text#Printing_text]. +/// \n\nParameters:\n* %1 - the value to print +Blockly.Msg.TEXT_PRINT_TITLE = 'print %1'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Text#Printing_text +/// https://code.google.com/p/blockly/wiki/Text#Printing_text]. +Blockly.Msg.TEXT_PRINT_TOOLTIP = 'Print the specified text, number or other value.'; +/// url - Information about getting text from users. +Blockly.Msg.TEXT_PROMPT_HELPURL = 'https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user'; +/// dropdown - Specifies that a piece of text should be requested from the user with +/// the following message. See [https://code.google.com/p/blockly/wiki/Text#Printing_text +/// https://code.google.com/p/blockly/wiki/Text#Printing_text]. +Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = 'prompt for text with message'; +/// dropdown - Specifies that a number should be requested from the user with the +/// following message. See [https://code.google.com/p/blockly/wiki/Text#Printing_text +/// https://code.google.com/p/blockly/wiki/Text#Printing_text]. +Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = 'prompt for number with message'; +/// dropdown - Precedes the message with which the user should be prompted for +/// a number. See [https://code.google.com/p/blockly/wiki/Text#Printing_text +/// https://code.google.com/p/blockly/wiki/Text#Printing_text]. +Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = 'Prompt for user for a number.'; +/// dropdown - Precedes the message with which the user should be prompted for some text. +/// See [https://code.google.com/p/blockly/wiki/Text#Printing_text +/// https://code.google.com/p/blockly/wiki/Text#Printing_text]. +Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = 'Prompt for user for some text.'; + +// Lists Blocks. +/// url - Information on empty lists. +Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = 'http://en.wikipedia.org/wiki/Linked_list#Empty_lists'; +/// block text - See [https://code.google.com/p/blockly/wiki/Lists#create_empty_list https://code.google.com/p/blockly/wiki/Lists#create_empty_list]. +Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = 'create empty list'; +/// block text - See [https://code.google.com/p/blockly/wiki/Lists#create_empty_list https://code.google.com/p/blockly/wiki/Lists#create_empty_list]. +Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = 'Returns a list, of length 0, containing no data records'; + +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#create_list_with https://code.google.com/p/blockly/wiki/Lists#create_list_with]. +Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = 'Create a list with any number of items.'; +/// block text - See [https://code.google.com/p/blockly/wiki/Lists#create_list_with https://code.google.com/p/blockly/wiki/Lists#create_list_with]. +Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = 'create list with'; +/// block text - This appears in a sub-block when [https://code.google.com/p/blockly/wiki/Lists#changing_number_of_inputs changing the number of inputs in a ''''create list with'''' block]. +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = 'list'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#changing_number_of_inputs https://code.google.com/p/blockly/wiki/Lists#changing_number_of_inputs]. +Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = 'Add, remove, or reorder sections to reconfigure this list block.'; +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#changing_number_of_inputs https://code.google.com/p/blockly/wiki/Lists#changing_number_of_inputs]. +Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = 'Add an item to the list.'; + +/// url - Information about [https://code.google.com/p/blockly/wiki/Lists#create_list_with creating a list with multiple copies of a single item]. +Blockly.Msg.LISTS_REPEAT_HELPURL = 'https://code.google.com/p/blockly/wiki/Lists#create_list_with'; +/// url - See [https://code.google.com/p/blockly/wiki/Lists#create_list_with creating a list with multiple copies of a single item]. +Blockly.Msg.LISTS_REPEAT_TOOLTIP = 'Creates a list consisting of the given value repeated the specified number of times.'; +/// block text - See [https://code.google.com/p/blockly/wiki/Lists#create_list_with +/// https://code.google.com/p/blockly/wiki/Lists#create_list_with]. +///\n\nParameters:\n* %1 - the item (text) to be repeated\n* %2 - the number of times to repeat it +Blockly.Msg.LISTS_REPEAT_TITLE = 'create list with item %1 repeated %2 times'; + +/// url - Information about how the length of a list is computed (i.e., by the total number of elements, not the number of different elements). +Blockly.Msg.LISTS_LENGTH_HELPURL = 'https://code.google.com/p/blockly/wiki/Lists#length_of'; +/// block text - See [https://code.google.com/p/blockly/wiki/Lists#length_of https://code.google.com/p/blockly/wiki/Lists#length_of]. +/// \n\nParameters:\n* %1 - the list whose length is desired +Blockly.Msg.LISTS_LENGTH_TITLE = 'length of %1'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#length_of https://code.google.com/p/blockly/wiki/Lists#length_of Blockly:Lists:length of]. +Blockly.Msg.LISTS_LENGTH_TOOLTIP = 'Returns the length of a list.'; + +/// url - See [https://code.google.com/p/blockly/wiki/Lists#is_empty https://code.google.com/p/blockly/wiki/Lists#is_empty]. +Blockly.Msg.LISTS_IS_EMPTY_HELPURL = 'https://code.google.com/p/blockly/wiki/Lists#is_empty'; +/// block text - See [https://code.google.com/p/blockly/wiki/Lists#is_empty +/// https://code.google.com/p/blockly/wiki/Lists#is_empty]. +/// \n\nParameters:\n* %1 - the list to test +Blockly.Msg.LISTS_IS_EMPTY_TITLE = '%1 is empty'; +/// block tooltip - See [https://code.google.com/p/blockly/wiki/Lists#is_empty +/// https://code.google.com/p/blockly/wiki/Lists#is_empty]. +Blockly.Msg.LISTS_TOOLTIP = 'Returns true if the list is empty.'; + +/// block text - Title of blocks operating on [https://code.google.com/p/blockly/wiki/Lists lists]. +Blockly.Msg.LISTS_INLIST = 'in list'; + +/// url - See [https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List +/// https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List]. +Blockly.Msg.LISTS_INDEX_OF_HELPURL = 'https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List'; +Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +/// dropdown - See [https://code.google.com/p/blockly/wiki/Lists#Finding_Items_in_a_List +/// Lists#Finding_Items_in_a_List]. +/// [[File:Blockly-list-find.png]] +Blockly.Msg.LISTS_INDEX_OF_FIRST = 'find first occurrence of item'; +/// dropdown - See [https://code.google.com/p/blockly/wiki/Lists#Finding_Items_in_a_List +/// https://code.google.com/p/blockly/wiki/Lists#Finding_Items_in_a_List]. +/// [[File:Blockly-list-find.png]] +Blockly.Msg.LISTS_INDEX_OF_LAST = 'find last occurrence of item'; +/// dropdown - See [https://code.google.com/p/blockly/wiki/Lists#Finding_Items_in_a_List +/// https://code.google.com/p/blockly/wiki/Lists#Finding_Items_in_a_List]. +/// [[File:Blockly-list-find.png]] +Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = 'Returns the index of the first/last occurrence of the item in the list. Returns 0 if text is not found.'; + +Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; +/// dropdown - Indicates that the user wishes to +/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item +/// get an item from a list] without removing it from the list. +Blockly.Msg.LISTS_GET_INDEX_GET = 'get'; +/// dropdown - Indicates that the user wishes to +/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item +/// get and remove an item from a list], as opposed to merely getting +/// it without modifying the list. +Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = 'get and remove'; +/// dropdown - Indicates that the user wishes to +/// [https://code.google.com/p/blockly/wiki/Lists#Removing_an_item +/// remove an item from a list]. +Blockly.Msg.LISTS_GET_INDEX_REMOVE = 'remove'; +/// dropdown - Indicates that an index relative to the front of the list should be used to +/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item get and/or remove +/// an item from a list]. Note: If {{msg-Blockly|ORDINAL_NUMBER_SUFFIX}} is defined, it will +/// automatically appear ''after'' this number (and any other ordinal numbers on this block). +/// See [[Translating:Blockly#Ordinal_numbers]] for more information on ordinal numbers in Blockly. +/// [[File:Blockly-list-get-item.png]] +Blockly.Msg.LISTS_GET_INDEX_FROM_START = '#'; +/// dropdown - Indicates that an index relative to the end of the list should be used +/// to [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item access an item in a list]. +/// [[File:Blockly-list-get-item.png]] +Blockly.Msg.LISTS_GET_INDEX_FROM_END = '# from end'; +/// dropdown - Indicates that the '''first''' item should be +/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item accessed in a list]. +/// [[File:Blockly-list-get-item.png]] +Blockly.Msg.LISTS_GET_INDEX_FIRST = 'first'; +/// dropdown - Indicates that the '''last''' item should be +/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item accessed in a list]. +/// [[File:Blockly-list-get-item.png]] +Blockly.Msg.LISTS_GET_INDEX_LAST = 'last'; +/// dropdown - Indicates that a '''random''' item should be +/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item accessed in a list]. +/// [[File:Blockly-list-get-item.png]] +Blockly.Msg.LISTS_GET_INDEX_RANDOM = 'random'; +/// block text - Text that should go after the rightmost block/dropdown when +/// [http://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item +/// accessing an item from a list]. In most languages, this will be the empty string. +/// [[File:Blockly-list-get-item.png]] +Blockly.Msg.LISTS_GET_INDEX_TAIL = ''; +Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item +/// https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for more information. +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = 'Returns the item at the specified position in a list. #1 is the first item.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item +/// https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for more information. +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = 'Returns the item at the specified position in a list. #1 is the last item.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item +/// https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for more information. +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = 'Returns the first item in a list.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item +/// https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for more information. +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = 'Returns the last item in a list.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item +/// https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for more information. +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = 'Returns a random item in a list.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] +/// (for remove and return) and +/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for '# from start'. +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = 'Removes and returns the item at the specified position in a list. #1 is the first item.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for '# from end'. +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = 'Removes and returns the item at the specified position in a list. #1 is the last item.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'first'. +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = 'Removes and returns the first item in a list.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'last'. +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = 'Removes and returns the last item in a list.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'random'. +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = 'Removes and returns a random item in a list.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for '# from start'. +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = 'Removes the item at the specified position in a list. #1 is the first item.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for '# from end'. +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = 'Removes the item at the specified position in a list. #1 is the last item.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'first'. +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = 'Removes the first item in a list.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'last'. +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = 'Removes the last item in a list.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'random'. +Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = 'Removes a random item in a list.'; +/// url - Information about putting items in lists. +Blockly.Msg.LISTS_SET_INDEX_HELPURL = 'https://code.google.com/p/blockly/wiki/Lists#in_list_..._set'; +Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +/// block text - [https://code.google.com/p/blockly/wiki/Lists#in_list_..._set +/// Replaces an item in a list]. +/// [[File:Blockly-in-list-set-insert.png]] +Blockly.Msg.LISTS_SET_INDEX_SET = 'set'; +/// block text - [https://code.google.com/p/blockly/wiki/Lists#in_list_..._insert_at +/// Inserts an item into a list]. +/// [[File:Blockly-in-list-set-insert.png]] +Blockly.Msg.LISTS_SET_INDEX_INSERT = 'insert at'; +/// block text - The word(s) after the position in the list and before the item to be set/inserted. +/// [[File:Blockly-in-list-set-insert.png]] +Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = 'as'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the "get" block, the idea is the same for the "set" block). +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = 'Sets the item at the specified position in a list. #1 is the first item.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the "get" block, the idea is the same for the "set" block). +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = 'Sets the item at the specified position in a list. #1 is the last item.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the "get" block, the idea is the same for the "set" block). +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = 'Sets the first item in a list.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the "get" block, the idea is the same for the "set" block). +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = 'Sets the last item in a list.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the "get" block, the idea is the same for the "set" block). +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = 'Sets a random item in a list.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the "get" block, the idea is the same for the "insert" block). +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = 'Inserts the item at the specified position in a list. #1 is the first item.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the "get" block, the idea is the same for the "insert" block). +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = 'Inserts the item at the specified position in a list. #1 is the last item.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the "get" block, the idea is the same for the "insert" block). +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = 'Inserts the item at the start of a list.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the "get" block, the idea is the same for the "insert" block). +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = 'Append the item to the end of a list.'; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the "get" block, the idea is the same for the "insert" block). +Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = 'Inserts the item randomly in a list.'; + +/// url - Information describing extracting a sublist from an existing list. +Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = 'https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist'; +Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; +/// dropdown - Indicates that an index relative to the front of the list should be used +/// to specify the beginning of the range from which to +/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist get a sublist]. +/// [[File:Blockly-get-sublist.png]] +/// Note: If {{msg-Blockly|ORDINAL_NUMBER_SUFFIX}} is defined, it will +/// automatically appear ''after'' this number (and any other ordinal numbers on this block). +/// See [[Translating:Blockly#Ordinal_numbers]] for more information on ordinal numbers in Blockly. +Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = 'get sub-list from #'; +/// dropdown - Indicates that an index relative to the end of the list should be used +/// to specify the beginning of the range from which to +/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist get a sublist]. +Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = 'get sub-list from # from end'; +/// dropdown - Indicates that the +/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist sublist to extract] +/// should begin with the list's first item. +Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = 'get sub-list from first'; +/// dropdown - Indicates that an index relative to the front of the list should be +/// used to specify the end of the range from which to +/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist get a sublist]. +/// [[File:Blockly-get-sublist.png]] +Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = 'to #'; +/// dropdown - Indicates that an index relative to the end of the list should be +/// used to specify the end of the range from which to +/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist get a sublist]. +/// [[File:Blockly-get-sublist.png]] +Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = 'to # from end'; +/// dropdown - Indicates that the '''last''' item in the given list should be +/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist the end +/// of the selected sublist]. +/// [[File:Blockly-get-sublist.png]] +Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = 'to last'; +/// block text - This appears in the rightmost position ("tail") of the +/// sublist block, as described at +/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist +/// https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist]. +/// In English and most other languages, this is the empty string. +/// [[File:Blockly-get-sublist.png]] +Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ''; +/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist +/// https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist] for more information. +/// [[File:Blockly-get-sublist.png]] +Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = 'Creates a copy of the specified portion of a list.'; + +/// grammar - Text that follows an ordinal number (a number that indicates +/// position relative to other numbers). In most languages, such text appears +/// before the number, so this should be blank. An exception is Hungarian. +/// See [[Translating:Blockly#Ordinal_numbers]] for more information. +Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ''; + +// Variables Blocks. +/// url - Information about ''variables'' in computer programming. Consider using your language's translation of [http://en.wikipedia.org/wiki/Variable_(computer_science) http://en.wikipedia.org/wiki/Variable_(computer_science)], if it exists. +Blockly.Msg.VARIABLES_GET_HELPURL = 'http://code.google.com/p/blockly/wiki/Variables#Get'; +/// block text - This precedes the name of a variable when getting its values. In most (all?) languages, it should be the empty string. If unsure, ask yourself if any word should go before "x" in the expression "x + 1". +Blockly.Msg.VARIABLES_GET_TITLE = ''; +Blockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +/// block text - This follows the name of a variable. In most (all?) languages, it should be the empty string. If unsure, ask yourself if any word should go after "x" in the expression "x + 1". +Blockly.Msg.VARIABLES_GET_TAIL = ''; +/// tooltip - This gets the value of the named variable without modifying it. +Blockly.Msg.VARIABLES_GET_TOOLTIP = 'Returns the value of this variable.'; +/// context menu - Selecting this creates a block to set (change) the value of this variable. +/// \n\nParameters:\n* %1 - the name of the variable. +Blockly.Msg.VARIABLES_GET_CREATE_SET = 'Create "set %1"'; + +/// url - Information about ''variables'' in computer programming. Consider using your language's translation of [http://en.wikipedia.org/wiki/Variable_(computer_science) http://en.wikipedia.org/wiki/Variable_(computer_science)], if it exists. +Blockly.Msg.VARIABLES_SET_HELPURL = 'http://code.google.com/p/blockly/wiki/Variables#Set'; +/// block text - The imperative or infinitive form of the verb "set", as in: '''set''' [the value of] x to 7. +Blockly.Msg.VARIABLES_SET_TITLE = 'set'; +Blockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; +/// block text - The word that goes after the name of the variable and before its new +/// value in: set [the value of] x '''to''' 7. +Blockly.Msg.VARIABLES_SET_TAIL = 'to'; +/// tooltip - This initializes or changes the value of the named variable. +Blockly.Msg.VARIABLES_SET_TOOLTIP = 'Sets this variable to be equal to the input.'; +/// context menu - Selecting this creates a block to get (change) the value of +/// this variable.\n\nParameters:\n* %1 - the name of the variable. +Blockly.Msg.VARIABLES_SET_CREATE_GET = 'Create "get %1"'; + +// Procedures Blocks. +/// url - Information about defining [http://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that do not have return values. +Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = 'http://en.wikipedia.org/wiki/Procedure_%28computer_science%29'; +/// block text - This precedes the name of the procedure when defining it. See +/// [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#c84aoc this sample +/// procedure definition]. +Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = 'to'; +/// default name - This acts as a placeholder for the name of a function on a +/// function definition block, as shown on +/// [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#w7cfju this block]. +/// The user will replace it with the function's name. +Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = 'do something'; +/// block text - This precedes the list of parameters to a function. See +/// [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#6ot5y5 this sample +/// function with parameters]. +Blockly.Msg.PROCEDURES_BEFORE_PARAMS = 'with:'; +/// block text - This appears next to the function's "body", the blocks that should be +/// run when the function is called, as shown in +/// [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#c84aoc this sample +/// procedure definition]. + +Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ''; +/// tooltip +Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = 'Creates a function with no output.'; + +/// url - Information about defining [http://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that have return values. +Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = 'http://en.wikipedia.org/wiki/Procedure_%28computer_science%29'; +Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; +Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; +Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; +/// block text - This imperative or infinite verb precedes the value that is used as the return value +/// (output) of this function. See +/// [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#6ot5y5 this sample +/// function that returns a value]. + +Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = 'return'; +/// tooltip +Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = 'Creates a function with an output.'; + +/// alert - The user has created a function with two parameters that have the same name. Every parameter must have a different name. +Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = 'Warning: This function has duplicate parameters.'; + +/// url - Information about calling [http://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that do not return values. +Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = 'http://en.wikipedia.org/wiki/Procedure_%28computer_science%29'; +/// block text - In most (if not all) languages, this will be the empty string. +/// It precedes the name of the function that should be run. See, for example, +/// the "draw square" block in [https://blockly-demo.appspot.com/static/apps/turtle/index.html#ztz96g]. +Blockly.Msg.PROCEDURES_CALLNORETURN_CALL = ''; +/// tooltip - This block causes the body (blocks inside) of the named function definition to be run. +Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = 'Run the user-defined function "%1".'; + +/// url - Information about calling [http://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that return values. +Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = 'http://en.wikipedia.org/wiki/Procedure_%28computer_science%29'; +Blockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL; +/// tooltip - This block causes the body (blocks inside) of the named function definition to be run.\n\nParameters:\n* %1 - the name of the function. +Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = 'Run the user-defined function "%1" and use its output.'; + +/// block text - This text appears on a block in a window that appears when the user clicks +/// on the plus sign or star on a function definition block. It refers to the set of parameters +/// (referred to by the simpler term "inputs") to the function. See +/// [[Translating:Blockly#function_definitions]]. +Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = 'inputs'; +/// block text - This text appears on a block in a window that appears when the user clicks +/// on the plus sign or star on a function definition block]. It appears on the block for +/// adding an individual parameter (referred to by the simpler term "inputs") to the function. +/// See [[Translating:Blockly#function_definitions]]. +Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = 'input name:'; + +/// context menu - This appears on the context menu for function calls. Selecting +/// it causes the corresponding function definition to be highlighted (as shown at +/// [[Translating:Blockly#context_menus]]. +Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = 'Highlight function definition'; +/// context menu - This appears on the context menu for function definitions. +/// Selecting it creates a block to call the function. \n\nParameters:\n* %1 - the name of the function. +Blockly.Msg.PROCEDURES_CREATE_DO = 'Create "%1"'; + +/// tooltip - If the first value is true, this causes the second value to be returned +/// immediately from the enclosing function. +Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = 'If a value is true, then return a second value.'; +/// warning - This appears if the user tries to use this block outside of a function definition. +Blockly.Msg.PROCEDURES_IFRETURN_WARNING = 'Warning: This block may be used only within a function definition.'; diff --git a/python_compressed.js b/python_compressed.js new file mode 100644 index 000000000..a5c78b538 --- /dev/null +++ b/python_compressed.js @@ -0,0 +1,70 @@ +// Do not edit this file; automatically generated by build.py. +"use strict"; + +Blockly.Python=new Blockly.Generator("Python");Blockly.Python.addReservedWords("and,as,assert,break,class,continue,def,del,elif,else,except,exec,finally,for,from,global,if,import,in,is,lambda,not,or,pass,print,raise,return,try,while,with,yield,True,False,None,NotImplemented,Ellipsis,__debug__,quit,exit,copyright,license,credits,abs,divmod,input,open,staticmethod,all,enumerate,int,ord,str,any,eval,isinstance,pow,sum,basestring,execfile,issubclass,print,super,bin,file,iter,property,tuple,bool,filter,len,range,type,bytearray,float,list,raw_input,unichr,callable,format,locals,reduce,unicode,chr,frozenset,long,reload,vars,classmethod,getattr,map,repr,xrange,cmp,globals,max,reversed,zip,compile,hasattr,memoryview,round,__import__,complex,hash,min,set,apply,delattr,help,next,setattr,buffer,dict,hex,object,slice,coerce,dir,id,oct,sorted,intern"); +Blockly.Python.ORDER_ATOMIC=0;Blockly.Python.ORDER_COLLECTION=1;Blockly.Python.ORDER_STRING_CONVERSION=1;Blockly.Python.ORDER_MEMBER=2;Blockly.Python.ORDER_FUNCTION_CALL=2;Blockly.Python.ORDER_EXPONENTIATION=3;Blockly.Python.ORDER_UNARY_SIGN=4;Blockly.Python.ORDER_BITWISE_NOT=4;Blockly.Python.ORDER_MULTIPLICATIVE=5;Blockly.Python.ORDER_ADDITIVE=6;Blockly.Python.ORDER_BITWISE_SHIFT=7;Blockly.Python.ORDER_BITWISE_AND=8;Blockly.Python.ORDER_BITWISE_XOR=9;Blockly.Python.ORDER_BITWISE_OR=10; +Blockly.Python.ORDER_RELATIONAL=11;Blockly.Python.ORDER_LOGICAL_NOT=12;Blockly.Python.ORDER_LOGICAL_AND=13;Blockly.Python.ORDER_LOGICAL_OR=14;Blockly.Python.ORDER_CONDITIONAL=15;Blockly.Python.ORDER_LAMBDA=16;Blockly.Python.ORDER_NONE=99;Blockly.Python.INFINITE_LOOP_TRAP=null;Blockly.Python.FUNCTION_NAME_PLACEHOLDER_="{{{}}}";Blockly.Python.FUNCTION_NAME_PLACEHOLDER_REGEXP_=RegExp(Blockly.Python.FUNCTION_NAME_PLACEHOLDER_,"g"); +Blockly.Python.init=function(){Blockly.Python.definitions_=Object.create(null);Blockly.Python.functionNames_=Object.create(null);if(Blockly.Variables){Blockly.Python.variableDB_?Blockly.Python.variableDB_.reset():Blockly.Python.variableDB_=new Blockly.Names(Blockly.Python.RESERVED_WORDS_);for(var a=[],b=Blockly.Variables.allVariables(),c=0;ca?Blockly.Python.ORDER_UNARY_SIGN:Blockly.Python.ORDER_ATOMIC]}; +Blockly.Python.math_arithmetic=function(a){var b={ADD:[" + ",Blockly.Python.ORDER_ADDITIVE],MINUS:[" - ",Blockly.Python.ORDER_ADDITIVE],MULTIPLY:[" * ",Blockly.Python.ORDER_MULTIPLICATIVE],DIVIDE:[" / ",Blockly.Python.ORDER_MULTIPLICATIVE],POWER:[" ** ",Blockly.Python.ORDER_EXPONENTIATION]}[a.getTitleValue("OP")],c=b[0],b=b[1],d=Blockly.Python.valueToCode(a,"A",b)||"0";a=Blockly.Python.valueToCode(a,"B",b)||"0";return[d+c+a,b]}; +Blockly.Python.math_single=function(a){var b=a.getTitleValue("OP"),c;if("NEG"==b)return c=Blockly.Python.valueToCode(a,"NUM",Blockly.Python.ORDER_UNARY_SIGN)||"0",["-"+c,Blockly.Python.ORDER_UNARY_SIGN];Blockly.Python.definitions_.import_math="import math";a="SIN"==b||"COS"==b||"TAN"==b?Blockly.Python.valueToCode(a,"NUM",Blockly.Python.ORDER_MULTIPLICATIVE)||"0":Blockly.Python.valueToCode(a,"NUM",Blockly.Python.ORDER_NONE)||"0";switch(b){case "ABS":c="math.fabs("+a+")";break;case "ROOT":c="math.sqrt("+ +a+")";break;case "LN":c="math.log("+a+")";break;case "LOG10":c="math.log10("+a+")";break;case "EXP":c="math.exp("+a+")";break;case "POW10":c="math.pow(10,"+a+")";break;case "ROUND":c="round("+a+")";break;case "ROUNDUP":c="math.ceil("+a+")";break;case "ROUNDDOWN":c="math.floor("+a+")";break;case "SIN":c="math.sin("+a+" / 180.0 * math.pi)";break;case "COS":c="math.cos("+a+" / 180.0 * math.pi)";break;case "TAN":c="math.tan("+a+" / 180.0 * math.pi)"}if(c)return[c,Blockly.Python.ORDER_FUNCTION_CALL];switch(b){case "ASIN":c= +"math.asin("+a+") / math.pi * 180";break;case "ACOS":c="math.acos("+a+") / math.pi * 180";break;case "ATAN":c="math.atan("+a+") / math.pi * 180";break;default:throw"Unknown math operator: "+b;}return[c,Blockly.Python.ORDER_MULTIPLICATIVE]}; +Blockly.Python.math_constant=function(a){var b={PI:["math.pi",Blockly.Python.ORDER_MEMBER],E:["math.e",Blockly.Python.ORDER_MEMBER],GOLDEN_RATIO:["(1 + math.sqrt(5)) / 2",Blockly.Python.ORDER_MULTIPLICATIVE],SQRT2:["math.sqrt(2)",Blockly.Python.ORDER_MEMBER],SQRT1_2:["math.sqrt(1.0 / 2)",Blockly.Python.ORDER_MEMBER],INFINITY:["float('inf')",Blockly.Python.ORDER_ATOMIC]};a=a.getTitleValue("CONSTANT");"INFINITY"!=a&&(Blockly.Python.definitions_.import_math="import math");return b[a]}; +Blockly.Python.math_number_property=function(a){var b=Blockly.Python.valueToCode(a,"NUMBER_TO_CHECK",Blockly.Python.ORDER_MULTIPLICATIVE)||"0",c=a.getTitleValue("PROPERTY"),d;if("PRIME"==c)return Blockly.Python.definitions_.import_math="import math",d=Blockly.Python.provideFunction_("isPrime",["def "+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+"(n):"," # http://en.wikipedia.org/wiki/Primality_test#Naive_methods"," # If n is not a number but a string, try parsing it."," if type(n) not in (int, float, long):", +" try:"," n = float(n)"," except:"," return False"," if n == 2 or n == 3:"," return True"," # False if n is negative, is 1, or not whole, or if n is divisible by 2 or 3."," if n <= 1 or n % 1 != 0 or n % 2 == 0 or n % 3 == 0:"," return False"," # Check all the numbers of form 6k +/- 1, up to sqrt(n)."," for x in range(6, int(math.sqrt(n)) + 2, 6):"," if n % (x - 1) == 0 or n % (x + 1) == 0:"," return False"," return True"])+"("+b+")",[d,Blockly.Python.ORDER_FUNCTION_CALL]; +switch(c){case "EVEN":d=b+" % 2 == 0";break;case "ODD":d=b+" % 2 == 1";break;case "WHOLE":d=b+" % 1 == 0";break;case "POSITIVE":d=b+" > 0";break;case "NEGATIVE":d=b+" < 0";break;case "DIVISIBLE_BY":a=Blockly.Python.valueToCode(a,"DIVISOR",Blockly.Python.ORDER_MULTIPLICATIVE);if(!a||"0"==a)return["False",Blockly.Python.ORDER_ATOMIC];d=b+" % "+a+" == 0"}return[d,Blockly.Python.ORDER_RELATIONAL]}; +Blockly.Python.math_change=function(a){var b=Blockly.Python.valueToCode(a,"DELTA",Blockly.Python.ORDER_ADDITIVE)||"0";a=Blockly.Python.variableDB_.getName(a.getTitleValue("VAR"),Blockly.Variables.NAME_TYPE);return a+" = ("+a+" if type("+a+") in (int, float, long) else 0) + "+b+"\n"};Blockly.Python.math_round=Blockly.Python.math_single;Blockly.Python.math_trig=Blockly.Python.math_single; +Blockly.Python.math_on_list=function(a){var b=a.getTitleValue("OP");a=Blockly.Python.valueToCode(a,"LIST",Blockly.Python.ORDER_NONE)||"[]";switch(b){case "SUM":b="sum("+a+")";break;case "MIN":b="min("+a+")";break;case "MAX":b="max("+a+")";break;case "AVERAGE":b=Blockly.Python.provideFunction_("math_mean",["def "+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+"(myList):"," localList = [e for e in myList if type(e) in (int, float, long)]"," if not localList: return"," return float(sum(localList)) / len(localList)"]); +b=b+"("+a+")";break;case "MEDIAN":b=Blockly.Python.provideFunction_("math_median",["def "+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+"(myList):"," localList = sorted([e for e in myList if type(e) in (int, float, long)])"," if not localList: return"," if len(localList) % 2 == 0:"," return (localList[len(localList) / 2 - 1] + localList[len(localList) / 2]) / 2.0"," else:"," return localList[(len(localList) - 1) / 2]"]);b=b+"("+a+")";break;case "MODE":b=Blockly.Python.provideFunction_("math_modes", +["def "+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+"(some_list):"," modes = []"," # Using a lists of [item, count] to keep count rather than dict",' # to avoid "unhashable" errors when the counted item is itself a list or dict.'," counts = []"," maxCount = 1"," for item in some_list:"," found = False"," for count in counts:"," if count[0] == item:"," count[1] += 1"," maxCount = max(maxCount, count[1])"," found = True"," if not found:"," counts.append([item, 1])", +" for counted_item, item_count in counts:"," if item_count == maxCount:"," modes.append(counted_item)"," return modes"]);b=b+"("+a+")";break;case "STD_DEV":Blockly.Python.definitions_.import_math="import math";b=Blockly.Python.provideFunction_("math_standard_deviation",["def "+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+"(numbers):"," n = len(numbers)"," if n == 0: return"," mean = float(sum(numbers)) / n"," variance = sum((x - mean) ** 2 for x in numbers) / n"," return math.sqrt(variance)"]); +b=b+"("+a+")";break;case "RANDOM":Blockly.Python.definitions_.import_random="import random";b="random.choice("+a+")";break;default:throw"Unknown operator: "+b;}return[b,Blockly.Python.ORDER_FUNCTION_CALL]};Blockly.Python.math_modulo=function(a){var b=Blockly.Python.valueToCode(a,"DIVIDEND",Blockly.Python.ORDER_MULTIPLICATIVE)||"0";a=Blockly.Python.valueToCode(a,"DIVISOR",Blockly.Python.ORDER_MULTIPLICATIVE)||"0";return[b+" % "+a,Blockly.Python.ORDER_MULTIPLICATIVE]}; +Blockly.Python.math_constrain=function(a){var b=Blockly.Python.valueToCode(a,"VALUE",Blockly.Python.ORDER_NONE)||"0",c=Blockly.Python.valueToCode(a,"LOW",Blockly.Python.ORDER_NONE)||"0";a=Blockly.Python.valueToCode(a,"HIGH",Blockly.Python.ORDER_NONE)||"float('inf')";return["min(max("+b+", "+c+"), "+a+")",Blockly.Python.ORDER_FUNCTION_CALL]}; +Blockly.Python.math_random_int=function(a){Blockly.Python.definitions_.import_random="import random";var b=Blockly.Python.valueToCode(a,"FROM",Blockly.Python.ORDER_NONE)||"0";a=Blockly.Python.valueToCode(a,"TO",Blockly.Python.ORDER_NONE)||"0";return["random.randint("+b+", "+a+")",Blockly.Python.ORDER_FUNCTION_CALL]};Blockly.Python.math_random_float=function(a){Blockly.Python.definitions_.import_random="import random";return["random.random()",Blockly.Python.ORDER_FUNCTION_CALL]};Blockly.Python.procedures={}; +Blockly.Python.procedures_defreturn=function(a){for(var b=Blockly.Variables.allVariables(a),c=b.length-1;0<=c;c--){var d=b[c];-1==a.arguments_.indexOf(d)?b[c]=Blockly.Python.variableDB_.getName(d,Blockly.Variables.NAME_TYPE):b.splice(c,1)}b=b.length?" global "+b.join(", ")+"\n":"";c=Blockly.Python.variableDB_.getName(a.getTitleValue("NAME"),Blockly.Procedures.NAME_TYPE);d=Blockly.Python.statementToCode(a,"STACK");Blockly.Python.INFINITE_LOOP_TRAP&&(d=Blockly.Python.INFINITE_LOOP_TRAP.replace(/%1/g,'"'+ +a.id+'"')+d);var e=Blockly.Python.valueToCode(a,"RETURN",Blockly.Python.ORDER_NONE)||"";e?e=" return "+e+"\n":d||(d=" pass");for(var g=[],f=0;f",GTE:">="}[a.getTitleValue("OP")],c=Blockly.Python.ORDER_RELATIONAL,d=Blockly.Python.valueToCode(a,"A",c)||"0";a=Blockly.Python.valueToCode(a,"B",c)||"0";return[d+" "+b+" "+a,c]}; +Blockly.Python.logic_operation=function(a){var b="AND"==a.getTitleValue("OP")?"and":"or",c="and"==b?Blockly.Python.ORDER_LOGICAL_AND:Blockly.Python.ORDER_LOGICAL_OR,d=Blockly.Python.valueToCode(a,"A",c);a=Blockly.Python.valueToCode(a,"B",c);if(d||a){var e="and"==b?"True":"False";d||(d=e);a||(a=e)}else a=d="False";return[d+" "+b+" "+a,c]};Blockly.Python.logic_negate=function(a){return["not "+(Blockly.Python.valueToCode(a,"BOOL",Blockly.Python.ORDER_LOGICAL_NOT)||"True"),Blockly.Python.ORDER_LOGICAL_NOT]}; +Blockly.Python.logic_boolean=function(a){return["TRUE"==a.getTitleValue("BOOL")?"True":"False",Blockly.Python.ORDER_ATOMIC]};Blockly.Python.logic_null=function(a){return["None",Blockly.Python.ORDER_ATOMIC]}; +Blockly.Python.logic_ternary=function(a){var b=Blockly.Python.valueToCode(a,"IF",Blockly.Python.ORDER_CONDITIONAL)||"False",c=Blockly.Python.valueToCode(a,"THEN",Blockly.Python.ORDER_CONDITIONAL)||"None";a=Blockly.Python.valueToCode(a,"ELSE",Blockly.Python.ORDER_CONDITIONAL)||"None";return[c+" if "+b+" else "+a,Blockly.Python.ORDER_CONDITIONAL]};Blockly.Python.lists={};Blockly.Python.lists_create_empty=function(a){return["[]",Blockly.Python.ORDER_ATOMIC]};Blockly.Python.lists_create_with=function(a){for(var b=Array(a.itemCount_),c=0;c= stop:"," yield start"," start -= abs(step)"])};if(Blockly.isNumber(c)&&Blockly.isNumber(d)&&Blockly.isNumber(e))c=parseFloat(c), +d=parseFloat(d),e=Math.abs(parseFloat(e)),0===c%1&&0===d%1&&0===e%1?(c<=d?(d++,a=0==c&&1==e?d:c+", "+d,1!=e&&(a+=", "+e)):(d--,a=c+", "+d+", -"+e),a="range("+a+")"):(a=c + + + + Unit tests for Blockly + + + + + + + + + + diff --git a/tests/blockly_test.js b/tests/blockly_test.js new file mode 100644 index 000000000..a964f3ce1 --- /dev/null +++ b/tests/blockly_test.js @@ -0,0 +1,178 @@ +/** + * Visual Blocks Editor + * + * Copyright 2011 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ +'use strict'; + +function verify_DB_(msg, expected, db) { + var equal = (expected.length == db.length); + if (equal) { + for (var x = 0; x < expected.length; x++) { + if (expected[x] != db[x]) { + equal = false; + break; + } + } + } + if (equal) { + assertTrue(msg, true); + } else { + assertEquals(msg, expected, db); + } +} + +function test_DB_addConnection() { + var db = new Blockly.ConnectionDB(); + var o2 = {y_: 2}; + db.addConnection_(o2); + verify_DB_('Adding connection #2', [o2], db); + + var o4 = {y_: 4}; + db.addConnection_(o4); + verify_DB_('Adding connection #4', [o2, o4], db); + + var o1 = {y_: 1}; + db.addConnection_(o1); + verify_DB_('Adding connection #1', [o1, o2, o4], db); + + var o3a = {y_: 3}; + db.addConnection_(o3a); + verify_DB_('Adding connection #3a', [o1, o2, o3a, o4], db); + + var o3b = {y_: 3}; + db.addConnection_(o3b); + verify_DB_('Adding connection #3b', [o1, o2, o3b, o3a, o4], db); +} + +function test_DB_removeConnection() { + var db = new Blockly.ConnectionDB(); + var o1 = {y_: 1}; + var o2 = {y_: 2}; + var o3a = {y_: 3}; + var o3b = {y_: 3}; + var o3c = {y_: 3}; + var o4 = {y_: 4}; + db.addConnection_(o1); + db.addConnection_(o2); + db.addConnection_(o3c); + db.addConnection_(o3b); + db.addConnection_(o3a); + db.addConnection_(o4); + verify_DB_('Adding connections 1-4', [o1, o2, o3a, o3b, o3c, o4], db); + + db.removeConnection_(o2); + verify_DB_('Removing connection #2', [o1, o3a, o3b, o3c, o4], db); + + db.removeConnection_(o4); + verify_DB_('Removing connection #4', [o1, o3a, o3b, o3c], db); + + db.removeConnection_(o1); + verify_DB_('Removing connection #1', [o3a, o3b, o3c], db); + + db.removeConnection_(o3a); + verify_DB_('Removing connection #3a', [o3b, o3c], db); + + db.removeConnection_(o3c); + verify_DB_('Removing connection #3c', [o3b], db); + + db.removeConnection_(o3b); + verify_DB_('Removing connection #3b', [], db); +} + +function test_addClass() { + var p = document.createElement('p'); + Blockly.addClass_(p, 'one'); + assertEquals('Adding "one"', 'one', p.className); + Blockly.addClass_(p, 'one'); + assertEquals('Adding duplicate "one"', 'one', p.className); + Blockly.addClass_(p, 'two'); + assertEquals('Adding "two"', 'one two', p.className); + Blockly.addClass_(p, 'two'); + assertEquals('Adding duplicate "two"', 'one two', p.className); + Blockly.addClass_(p, 'three'); + assertEquals('Adding "three"', 'one two three', p.className); +} + +function test_removeClass() { + var p = document.createElement('p'); + p.className = ' one three two three '; + Blockly.removeClass_(p, 'two'); + assertEquals('Removing "two"', 'one three three', p.className); + Blockly.removeClass_(p, 'four'); + assertEquals('Removing "four"', 'one three three', p.className); + Blockly.removeClass_(p, 'three'); + assertEquals('Removing "three"', 'one', p.className); + Blockly.removeClass_(p, 'ne'); + assertEquals('Removing "ne"', 'one', p.className); + Blockly.removeClass_(p, 'one'); + assertEquals('Removing "one"', '', p.className); + Blockly.removeClass_(p, 'zero'); + assertEquals('Removing "zero"', '', p.className); +} + +function test_shortestStringLength() { + var len = Blockly.shortestStringLength('one,two,three,four,five'.split(',')); + assertEquals('Length of "one"', 3, len); + len = Blockly.shortestStringLength('one,two,three,four,five,'.split(',')); + assertEquals('Length of ""', 0, len); + len = Blockly.shortestStringLength(['Hello World']); + assertEquals('List of one', 11, len); + len = Blockly.shortestStringLength([]); + assertEquals('Empty list', 0, len); +} + +function test_commonWordPrefix() { + var len = Blockly.commonWordPrefix('one,two,three,four,five'.split(',')); + assertEquals('No prefix', 0, len); + len = Blockly.commonWordPrefix('Xone,Xtwo,Xthree,Xfour,Xfive'.split(',')); + assertEquals('No word prefix', 0, len); + len = Blockly.commonWordPrefix('abc de,abc de,abc de,abc de'.split(',')); + assertEquals('Full equality', 6, len); + len = Blockly.commonWordPrefix('abc deX,abc deY'.split(',')); + assertEquals('One word prefix', 4, len); + len = Blockly.commonWordPrefix('abc de,abc deY'.split(',')); + assertEquals('Overflow no', 4, len); + len = Blockly.commonWordPrefix('abc de,abc de Y'.split(',')); + assertEquals('Overflow yes', 6, len); + len = Blockly.commonWordPrefix(['Hello World']); + assertEquals('List of one', 11, len); + len = Blockly.commonWordPrefix([]); + assertEquals('Empty list', 0, len); + len = Blockly.commonWordPrefix('turn left,turn right'.split(',')); + assertEquals('No prefix due to &nbsp;', 0, len); + len = Blockly.commonWordPrefix('turn\u00A0left,turn\u00A0right'.split(',')); + assertEquals('No prefix due to \\u00A0', 0, len); +} + +function test_commonWordSuffix() { + var len = Blockly.commonWordSuffix('one,two,three,four,five'.split(',')); + assertEquals('No prefix', 0, len); + len = Blockly.commonWordSuffix('oneX,twoX,threeX,fourX,fiveX'.split(',')); + assertEquals('No word prefix', 0, len); + len = Blockly.commonWordSuffix('abc de,abc de,abc de,abc de'.split(',')); + assertEquals('Full equality', 6, len); + len = Blockly.commonWordSuffix('Xabc de,Yabc de'.split(',')); + assertEquals('One word prefix', 3, len); + len = Blockly.commonWordSuffix('abc de,Yabc de'.split(',')); + assertEquals('Overflow no', 3, len); + len = Blockly.commonWordSuffix('abc de,Y abc de'.split(',')); + assertEquals('Overflow yes', 6, len); + len = Blockly.commonWordSuffix(['Hello World']); + assertEquals('List of one', 11, len); + len = Blockly.commonWordSuffix([]); + assertEquals('Empty list', 0, len); +} diff --git a/tests/generator_test.js b/tests/generator_test.js new file mode 100644 index 000000000..776a0c9ad --- /dev/null +++ b/tests/generator_test.js @@ -0,0 +1,27 @@ +/** + * Blockly Tests + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ +'use strict'; + +function test_prefix() { + var generator = new Blockly.Generator('INTERCAL'); + assertEquals('Prefix nothing.', '', generator.prefixLines('', '')); + assertEquals('Prefix a word.', '@Hello', generator.prefixLines('Hello', '@')); + assertEquals('Prefix one line.', '12Hello\n', generator.prefixLines('Hello\n', '12')); + assertEquals('Prefix two lines.', '***Hello\n***World\n', generator.prefixLines('Hello\nWorld\n', '***')); +} diff --git a/tests/generators/colour.xml b/tests/generators/colour.xml new file mode 100644 index 000000000..6d52f81bb --- /dev/null +++ b/tests/generators/colour.xml @@ -0,0 +1,241 @@ + + + + test rgb + + + from rgb + + + + + 100 + + + + + 40 + + + + + 0 + + + + + + + #ff6600 + + + + + + + + test colour picker + + + static colour + + + #ff6600 + + + + + #ff6600 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + test blend + + + blend + + + + + #ff0000 + + + + + + + 100 + + + + + 40 + + + + + 0 + + + + + + + 0.4 + + + + + + + #ff2900 + + + + + + + + test colour random + + + + + 100 + + + + + item + + + + + + test name + + + + + item + + + + + + + 7 + + + + + test name + + + + FIRST + + + item + + + + + + + # + + + + + i + + + 2 + + + + + 7 + + + + + test name + TRUE + + + NEQ + + + 0 + + + + + FIRST + + + abcdefABDEF0123456789 + + + + + + FROM_START + + + item + + + + + i + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/generators/index.html b/tests/generators/index.html new file mode 100644 index 000000000..af38cb54c --- /dev/null +++ b/tests/generators/index.html @@ -0,0 +1,357 @@ + + + + +Blockly Generator Test + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +
    +

    Blockly Generator Test

    + +

    + + +

    + +

    + Generate: + + + +

    +
    + +
    + + diff --git a/tests/generators/lists.xml b/tests/generators/lists.xml new file mode 100644 index 000000000..139bcf3ab --- /dev/null +++ b/tests/generators/lists.xml @@ -0,0 +1,2147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + test create + + + test create empty + + + + + + + + + + + test create items + + + + + + TRUE + + + + + love + + + + + + + + + + TRUE + + + + + love + + + + + + + test create repeated + + + + + Eject + + + + + 3 + + + + + + + + + + Eject + + + + + Eject + + + + + Eject + + + + + + + + + + + + + + test empty + + + not empty + FALSE + + + + + + + + 0 + + + + + + + + + empty + TRUE + + + + + + + + + + + + + + + test length + + + zero length + + + + + + + + + + 0 + + + + + one length + + + + + + + + cat + + + + + + + + + 1 + + + + + three length + + + + + + + + cat + + + + + TRUE + + + + + + + + + + + + 3 + + + + + + + + + + + + test find + + + find first + + + FIRST + + + + + + Alice + + + + + Eve + + + + + Bob + + + + + Eve + + + + + + + Eve + + + + + + + 2 + + + + + find last + + + LAST + + + + + + Alice + + + + + Eve + + + + + Bob + + + + + Eve + + + + + + + Eve + + + + + + + 4 + + + + + find none + + + FIRST + + + + + + Alice + + + + + Bob + + + + + Carol + + + + + Dave + + + + + + + Eve + + + + + + + 0 + + + + + + + + + + + + test get + + + list + + + + + + Kirk + + + + + Spock + + + + + McCoy + + + + + + + get first + + + + GET + FIRST + + + list + + + + + + + Kirk + + + + + get last + + + + GET + LAST + + + list + + + + + + + McCoy + + + + + get random + TRUE + + + + POSITIVE + + + FIRST + + + list + + + + + + GET + RANDOM + + + list + + + + + + + + + + + get # + + + + GET + FROM_START + + + list + + + + + 2 + + + + + + + Spock + + + + + get #-end + + + + GET + FROM_END + + + list + + + + + 3 + + + + + + + Kirk + + + + + + + + + + + + + + + + + + test get remove + + + list + + + + + + Kirk + + + + + Spock + + + + + McCoy + + + + + + + getremove first + + + + GET_REMOVE + FIRST + + + list + + + + + + + Kirk + + + + + getremove first list + + + list + + + + + + + + Spock + + + + + McCoy + + + + + + + list + + + + + + Kirk + + + + + Spock + + + + + McCoy + + + + + + + getremove last + + + + GET_REMOVE + LAST + + + list + + + + + + + McCoy + + + + + getremove last list + + + list + + + + + + + + Kirk + + + + + Spock + + + + + + + list + + + + + + Kirk + + + + + Spock + + + + + McCoy + + + + + + + getremove random + TRUE + + + EQ + + + FIRST + + + list + + + + + + GET_REMOVE + RANDOM + + + list + + + + + + + + + 0 + + + + + + + getremove random list + + + + + list + + + + + + + 2 + + + + + list + + + + + + Kirk + + + + + Spock + + + + + McCoy + + + + + + + getremove # + + + + GET_REMOVE + FROM_START + + + list + + + + + 2 + + + + + + + Spock + + + + + getremove # list + + + list + + + + + + + + Kirk + + + + + McCoy + + + + + + + list + + + + + + Kirk + + + + + Spock + + + + + McCoy + + + + + + + getremove #-end + + + + GET_REMOVE + FROM_END + + + list + + + + + 3 + + + + + + + Kirk + + + + + getremove #-end list + + + list + + + + + + + + Spock + + + + + McCoy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + test remove + + + list + + + + + + Kirk + + + + + Spock + + + + + McCoy + + + + + + + + REMOVE + FIRST + + + list + + + + + remove first list + + + list + + + + + + + + Spock + + + + + McCoy + + + + + + + list + + + + + + Kirk + + + + + Spock + + + + + McCoy + + + + + + + + REMOVE + LAST + + + list + + + + + remove last list + + + list + + + + + + + + Kirk + + + + + Spock + + + + + + + list + + + + + + Kirk + + + + + Spock + + + + + McCoy + + + + + + + + REMOVE + RANDOM + + + list + + + + + remove random list + + + + + list + + + + + + + 2 + + + + + list + + + + + + Kirk + + + + + Spock + + + + + McCoy + + + + + + + + REMOVE + FROM_START + + + list + + + + + 2 + + + + + remove # list + + + list + + + + + + + + Kirk + + + + + McCoy + + + + + + + list + + + + + + Kirk + + + + + Spock + + + + + McCoy + + + + + + + + REMOVE + FROM_END + + + list + + + + + 3 + + + + + remove #-end list + + + list + + + + + + + + Spock + + + + + McCoy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + test set + + + x + + + + + + Picard + + + + + Riker + + + + + Crusher + + + + + + + + SET + FIRST + + + x + + + + + Jean-Luc + + + + + set first list + + + x + + + + + + + + Jean-Luc + + + + + Riker + + + + + Crusher + + + + + + + x + + + + + + Picard + + + + + Riker + + + + + Crusher + + + + + + + + SET + LAST + + + x + + + + + Beverly + + + + + set last list + + + x + + + + + + + + Picard + + + + + Riker + + + + + Beverly + + + + + + + x + + + + + + Picard + + + + + Riker + + + + + Crusher + + + + + + + + SET + RANDOM + + + x + + + + + Data + + + + + set random list + + + + + x + + + + + + + 3 + + + + + x + + + + + + Picard + + + + + Riker + + + + + Crusher + + + + + + + + SET + FROM_START + + + x + + + + + 3 + + + + + Pulaski + + + + + set # list + + + x + + + + + + + + Picard + + + + + Riker + + + + + Pulaski + + + + + + + x + + + + + + Picard + + + + + Riker + + + + + Crusher + + + + + + + + SET + FROM_END + + + x + + + + + 1 + + + + + Pulaski + + + + + set #-end list + + + x + + + + + + + + Picard + + + + + Riker + + + + + Pulaski + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + test insert + + + x + + + + + + Picard + + + + + Riker + + + + + Crusher + + + + + + + + INSERT + FIRST + + + x + + + + + Data + + + + + insert first list + + + x + + + + + + + + Data + + + + + Picard + + + + + Riker + + + + + Crusher + + + + + + + x + + + + + + Picard + + + + + Riker + + + + + Crusher + + + + + + + + INSERT + LAST + + + x + + + + + Data + + + + + insert last list + + + x + + + + + + + + Picard + + + + + Riker + + + + + Crusher + + + + + Data + + + + + + + x + + + + + + Picard + + + + + Riker + + + + + Crusher + + + + + + + + INSERT + RANDOM + + + x + + + + + Data + + + + + insert random list + + + + + x + + + + + + + 4 + + + + + x + + + + + + Picard + + + + + Riker + + + + + Crusher + + + + + + + + INSERT + FROM_START + + + x + + + + + 3 + + + + + Data + + + + + insert # list + + + x + + + + + + + + Picard + + + + + Riker + + + + + Data + + + + + Crusher + + + + + + + x + + + + + + Picard + + + + + Riker + + + + + Crusher + + + + + + + + INSERT + FROM_END + + + x + + + + + 1 + + + + + Data + + + + + insert #-end list + + + x + + + + + + + + Picard + + + + + Riker + + + + + Data + + + + + Crusher + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + test sublist + + + list + + + + + + Columbia + + + + + Challenger + + + + + Discovery + + + + + Atlantis + + + + + Endeavour + + + + + + + sublist # start + + + + FROM_START + FROM_START + + + list + + + + + 2 + + + + + 3 + + + + + + + + + + Challenger + + + + + Discovery + + + + + + + sublist # end + + + + FROM_END + FROM_END + + + list + + + + + 3 + + + + + 2 + + + + + + + + + + Discovery + + + + + Atlantis + + + + + + + sublist first-last + + + + FIRST + LAST + + + list + + + + + + + list + + + + + + + + + + + + diff --git a/tests/generators/logic.xml b/tests/generators/logic.xml new file mode 100644 index 000000000..07fdccfe7 --- /dev/null +++ b/tests/generators/logic.xml @@ -0,0 +1,791 @@ + + + + + True + TRUE + + + TRUE + + + + + False + FALSE + + + FALSE + + + + + Not true + TRUE + + + + + FALSE + + + + + + + Not false + FALSE + + + + + TRUE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + test if + + + + + FALSE + + + + + if false + + + + + ok + + + FALSE + + + + + + + TRUE + + + + + ok + + + TRUE + + + + + + + if true + TRUE + + + ok + + + + + ok + + + FALSE + + + + + + + + FALSE + + + + + if/else false + + + + + ok + + + TRUE + + + + + + + if/else false + TRUE + + + ok + + + + + ok + + + FALSE + + + + + + + + TRUE + + + + + ok + + + TRUE + + + + + + + if/else true + + + + + if/else true + TRUE + + + ok + + + + + ok + + + FALSE + + + + + + + + FALSE + + + + + elseif 1 + + + + + TRUE + + + + + ok + + + TRUE + + + + + + + TRUE + + + + + elseif 2 + + + + + elseif 3 + + + + + elseif 4 + TRUE + + + ok + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + test equalities + + + Equal yes + TRUE + + + EQ + + + 2 + + + + + 2 + + + + + + + Equal no + FALSE + + + EQ + + + 3 + + + + + 4 + + + + + + + Not equal yes + TRUE + + + NEQ + + + 5 + + + + + 6 + + + + + + + Not equal no + FALSE + + + EQ + + + 3 + + + + + 4 + + + + + + + Smaller yes + TRUE + + + LT + + + 5 + + + + + 6 + + + + + + + Smaller no + FALSE + + + LT + + + 7 + + + + + 7 + + + + + + + Greater yes + TRUE + + + GT + + + 9 + + + + + 8 + + + + + + + Greater no + FALSE + + + GT + + + 10 + + + + + 10 + + + + + + + Smaller-equal yes + TRUE + + + LTE + + + 11 + + + + + 11 + + + + + + + Smaller-equal no + FALSE + + + LTE + + + 13 + + + + + 12 + + + + + + + Greater-equal yes + TRUE + + + GTE + + + 14 + + + + + 14 + + + + + + + Greater-equal no + FALSE + + + GTE + + + 15 + + + + + 16 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + test or + + + Or true/true + TRUE + + + OR + + + TRUE + + + + + TRUE + + + + + + + Or false/true + TRUE + + + OR + + + FALSE + + + + + TRUE + + + + + + + Or true/false + TRUE + + + OR + + + TRUE + + + + + FALSE + + + + + + + Or false/false + FALSE + + + OR + + + FALSE + + + + + FALSE + + + + + + + + + + + + + + + + test and + + + And true/true + TRUE + + + AND + + + TRUE + + + + + TRUE + + + + + + + And false/true + FALSE + + + AND + + + FALSE + + + + + TRUE + + + + + + + And true/false + FALSE + + + AND + + + TRUE + + + + + FALSE + + + + + + + And false/false + FALSE + + + AND + + + FALSE + + + + + FALSE + + + + + + + + + + + + + + + + test ternary + + + if true + + + + + TRUE + + + + + 42 + + + + + 99 + + + + + + + 42 + + + + + if true + + + + + FALSE + + + + + 42 + + + + + 99 + + + + + + + 99 + + + + + + + + diff --git a/tests/generators/loops1.xml b/tests/generators/loops1.xml new file mode 100644 index 000000000..0fe572c4c --- /dev/null +++ b/tests/generators/loops1.xml @@ -0,0 +1,275 @@ + + + + + + + + + + + + + + + + + + + + + test foreach + + + log + + + + + + + + x + + + + + + a + + + + + b + + + + + c + + + + + + + log + + + x + + + + + + + for loop + + + log + + + + + abc + + + + + + + + + + + + test while + + + WHILE + + + FALSE + + + + + while 0 + + + + + UNTIL + + + TRUE + + + + + until 0 + + + + + count + + + 1 + + + + + WHILE + + + NEQ + + + count + + + + + 10 + + + + + + + count + + + 1 + + + + + + + while 10 + + + count + + + + + 10 + + + + + count + + + 1 + + + + + UNTIL + + + EQ + + + count + + + + + 10 + + + + + + + count + + + 1 + + + + + + + until 10 + + + count + + + + + 10 + + + + + + + + + + + + + + + + + + + + + + test repeat + + + count + + + 0 + + + + + + + 10 + + + + + count + + + 1 + + + + + + + repeat 10 + + + count + + + + + 10 + + + + + + + + + + diff --git a/tests/generators/loops2.xml b/tests/generators/loops2.xml new file mode 100644 index 000000000..8947dc2cd --- /dev/null +++ b/tests/generators/loops2.xml @@ -0,0 +1,853 @@ + + + + test count by + + + log + + + + + + + + x + + + 1 + + + + + 8 + + + + + 2 + + + + + log + + + x + + + + + + + count up ints + + + log + + + + + 1357 + + + + + log + + + + + + + + x + + + 8 + + + + + 1 + + + + + 2 + + + + + log + + + x + + + + + + + count down ints + + + log + + + + + 8642 + + + + + loglist + + + + + + x + + + 1 + + + + + 8 + + + + + 1.5 + + + + + + INSERT + LAST + + + loglist + + + + + x + + + + + + + count with floats + + + loglist + + + + + + + + 1 + + + + + 2.5 + + + + + 4 + + + + + 5.5 + + + + + 7 + + + + + + + loglist + + + + + + x + + + ADD + + + 1 + + + + + 0 + + + + + + + ADD + + + 8 + + + + + 0 + + + + + + + MINUS + + + 1 + + + + + 2 + + + + + + + + INSERT + LAST + + + loglist + + + + + x + + + + + + + count up non-trivial ints + + + loglist + + + + + + + + 1 + + + + + 2 + + + + + 3 + + + + + 4 + + + + + 5 + + + + + 6 + + + + + 7 + + + + + 8 + + + + + + + loglist + + + + + + x + + + ADD + + + 8 + + + + + 0 + + + + + + + ADD + + + 1 + + + + + 0 + + + + + + + 2 + + + + + + INSERT + LAST + + + loglist + + + + + x + + + + + + + count down non-trivial ints + + + loglist + + + + + + + + 8 + + + + + 6 + + + + + 4 + + + + + 2 + + + + + + + loglist + + + + + + x + + + ADD + + + 5 + + + + + 0.5 + + + + + + + ADD + + + 1 + + + + + 0 + + + + + + + ADD + + + 1 + + + + + 0 + + + + + + + + INSERT + LAST + + + loglist + + + + + x + + + + + + + count with floats + + + loglist + + + + + + + + 5.5 + + + + + 4.5 + + + + + 3.5 + + + + + 2.5 + + + + + 1.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + test count + + + log + + + + + + + + x + + + 1 + + + + + 8 + + + + + log + + + x + + + + + + + count up + + + log + + + + + 12345678 + + + + + log + + + + + + + + x + + + 8 + + + + + 1 + + + + + log + + + x + + + + + + + count down + + + log + + + + + 87654321 + + + + + loglist + + + + + + x + + + ADD + + + 1 + + + + + 0 + + + + + + + ADD + + + 4 + + + + + 0 + + + + + + + + INSERT + LAST + + + loglist + + + + + x + + + + + + + count up non-trivial + + + loglist + + + + + + + + 1 + + + + + 2 + + + + + 3 + + + + + 4 + + + + + + + loglist + + + + + + x + + + ADD + + + 3 + + + + + 1 + + + + + + + ADD + + + 1 + + + + + 0 + + + + + + + + INSERT + LAST + + + loglist + + + + + x + + + + + + + count down non-trivial + + + loglist + + + + + + + + 4 + + + + + 3 + + + + + 2 + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/generators/loops3.xml b/tests/generators/loops3.xml new file mode 100644 index 000000000..1118f8a1c --- /dev/null +++ b/tests/generators/loops3.xml @@ -0,0 +1,704 @@ + + + + + + + + + + + + + + + + test break + + + count + + + 1 + + + + + WHILE + + + NEQ + + + count + + + + + 10 + + + + + + + + + EQ + + + count + + + + + 5 + + + + + + + BREAK + + + + + count + + + 1 + + + + + + + + + while break + + + count + + + + + 5 + + + + + count + + + 1 + + + + + UNTIL + + + EQ + + + count + + + + + 10 + + + + + + + + + EQ + + + count + + + + + 5 + + + + + + + BREAK + + + + + count + + + 1 + + + + + + + + + until break + + + count + + + + + 5 + + + + + log + + + + + + + + x + + + 1 + + + + + 8 + + + + + + + EQ + + + x + + + + + 5 + + + + + + + BREAK + + + + + log + + + x + + + + + + + + + count break + + + log + + + + + 1234 + + + + + log + + + + + + + + x + + + + + + a + + + + + b + + + + + c + + + + + d + + + + + + + + + EQ + + + x + + + + + c + + + + + + + BREAK + + + + + log + + + x + + + + + + + + + for break + + + log + + + + + ab + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + test continue + + + log + + + + + + + + count + + + 0 + + + + + WHILE + + + NEQ + + + count + + + + + 8 + + + + + + + count + + + 1 + + + + + + + EQ + + + count + + + + + 5 + + + + + + + CONTINUE + + + + + log + + + count + + + + + + + + + + + while continue + + + log + + + + + 1234678 + + + + + log + + + + + + + + count + + + 0 + + + + + UNTIL + + + EQ + + + count + + + + + 8 + + + + + + + count + + + 1 + + + + + + + EQ + + + count + + + + + 5 + + + + + + + CONTINUE + + + + + log + + + count + + + + + + + + + + + until continue + + + log + + + + + 1234678 + + + + + log + + + + + + + + x + + + 1 + + + + + 8 + + + + + + + EQ + + + x + + + + + 5 + + + + + + + CONTINUE + + + + + log + + + x + + + + + + + + + count continue + + + log + + + + + 1234678 + + + + + log + + + + + + + + x + + + + + + a + + + + + b + + + + + c + + + + + d + + + + + + + + + EQ + + + x + + + + + c + + + + + + + CONTINUE + + + + + log + + + x + + + + + + + + + for continue + + + log + + + + + abd + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/generators/math.xml b/tests/generators/math.xml new file mode 100644 index 000000000..a412f806d --- /dev/null +++ b/tests/generators/math.xml @@ -0,0 +1,1595 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + test operations on single + + + sqrt + + + ROOT + + + 25 + + + + + + + 5 + + + + + abs + + + ABS + + + -25 + + + + + + + 25 + + + + + negate + + + NEG + + + -25 + + + + + + + 25 + + + + + ln + + + LN + + + 1 + + + + + + + 0 + + + + + log10 + + + LOG10 + + + 100 + + + + + + + 2 + + + + + exp + + + EXP + + + 2 + + + + + + + 7.38905609893065 + + + + + power10 + + + POW10 + + + 2 + + + + + + + 100 + + + + + + + + + + + + + + + + + + + + test arithmetic + + + add + + + ADD + + + 1 + + + + + 2 + + + + + + + 3 + + + + + subtract + + + MINUS + + + 1 + + + + + 2 + + + + + + + -1 + + + + + multiply + + + MULTIPLY + + + 4 + + + + + 2.5 + + + + + + + 10 + + + + + divide + + + DIVIDE + + + 8.2 + + + + + -5 + + + + + + + -1.64 + + + + + power + + + POWER + + + 10 + + + + + 4 + + + + + + + 10000 + + + + + + + + + + + + + + + + test trig + + + sin + + + SIN + + + 90 + + + + + + + 1 + + + + + cos + + + COS + + + 180 + + + + + + + -1 + + + + + tan + + + TAN + + + 0 + + + + + + + 0 + + + + + asin + + + ASIN + + + -1 + + + + + + + -90 + + + + + acos + + + ACOS + + + 1 + + + + + + + 0 + + + + + atan + + + ATAN + + + 1 + + + + + + + 45 + + + + + + + + + + + + + + + + + + test constant + + + const pi + + + ROUNDDOWN + + + MULTIPLY + + + PI + + + + + 1000 + + + + + + + + + 3141 + + + + + const e + + + ROUNDDOWN + + + MULTIPLY + + + E + + + + + 1000 + + + + + + + + + 2718 + + + + + const golden + + + ROUNDDOWN + + + MULTIPLY + + + GOLDEN_RATIO + + + + + 1000 + + + + + + + + + 1618 + + + + + const sqrt 2 + + + ROUNDDOWN + + + MULTIPLY + + + SQRT2 + + + + + 1000 + + + + + + + + + 1414 + + + + + const sqrt 0.5 + + + ROUNDDOWN + + + MULTIPLY + + + SQRT1_2 + + + + + 1000 + + + + + + + + + 707 + + + + + const infinity + TRUE + + + LT + + + 9999 + + + + + INFINITY + + + + + + + + + + + + + + + + + + + + test number properties + + + even + TRUE + + + + EVEN + + + 42 + + + + + + + odd + FALSE + + + + ODD + + + 42.1 + + + + + + + prime 5 + TRUE + + + + PRIME + + + 5 + + + + + + + prime 25 + FALSE + + + + PRIME + + + 25 + + + + + + + prime negative + FALSE + + + + PRIME + + + -31.1 + + + + + + + whole + FALSE + + + + WHOLE + + + PI + + + + + + + positive + TRUE + + + + POSITIVE + + + INFINITY + + + + + + + negative + TRUE + + + + NEGATIVE + + + -42 + + + + + + + divisible + TRUE + + + + DIVISIBLE_BY + + + 42 + + + + + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + test round + + + round + + + ROUND + + + 42.42 + + + + + + + 42 + + + + + round up + + + ROUNDUP + + + -42.42 + + + + + + + -42 + + + + + round down + + + ROUNDDOWN + + + 42.42 + + + + + + + 42 + + + + + + + + + + + + test change + + + varToChange + + + 100 + + + + + varToChange + + + 42 + + + + + change + + + varToChange + + + + + 142 + + + + + + + + + + + + + + + assert list equal + + + equal + + + TRUE + + + + + + + + NEQ + + + + + a + + + + + + + + + b + + + + + + + + + equal + + + FALSE + + + + + + + x + + + 1 + + + + + + + a + + + + + + + + + NEQ + + + + GET + FROM_START + + + x + + + + + a + + + + + + + + GET + FROM_START + + + x + + + + + b + + + + + + + + + equal + + + FALSE + + + + + BREAK + + + + + + + + + + + + + + + equal + + + + + + + list equality + + + a + + + + + b + + + + + + + + + + + + + equal + + + + + + test operations on list + + + sum + + + SUM + + + + + + 3 + + + + + 4 + + + + + 5 + + + + + + + + + 12 + + + + + min + + + MIN + + + + + + 3 + + + + + 4 + + + + + 5 + + + + + + + + + 3 + + + + + max + + + MAX + + + + + + 3 + + + + + 4 + + + + + 5 + + + + + + + + + 5 + + + + + average + + + AVERAGE + + + + + + 3 + + + + + 4 + + + + + 5 + + + + + + + + + 4 + + + + + median + + + MEDIAN + + + + + + 3 + + + + + 4 + + + + + 5 + + + + + 1 + + + + + + + + + 3.5 + + + + + modes + TRUE + + + + + + + + + MODE + + + + + + 3 + + + + + 4 + + + + + 3 + + + + + + + + + + + + 3 + + + + + + + + + standard dev + + + STD_DEV + + + + + + 3 + + + + + 3 + + + + + 3 + + + + + + + + + 0 + + + + + random + TRUE + + + GT + + + FIRST + + + RANDOM + + + + + + 3 + + + + + 4 + + + + + 5 + + + + + + + + + + + + 3 + + + + + 4 + + + + + 5 + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + test mod + + + mod + + + + + 42 + + + + + 5 + + + + + + + 2 + + + + + + + + test constraint + + + constraint + + + + + 100 + + + + + 0 + + + + + 42 + + + + + + + 42 + + + + + + + + test random integer + + + rand + + + + + 5 + + + + + 10 + + + + + + + randRange + TRUE + + + AND + + + GTE + + + rand + + + + + 5 + + + + + + + LTE + + + rand + + + + + 10 + + + + + + + + + randInteger + TRUE + + + + WHOLE + + + rand + + + + + + + + + + + + + + test random fraction + + + rand + + + + + + randFloat + TRUE + + + AND + + + GTE + + + rand + + + + + 0 + + + + + + + LTE + + + rand + + + + + 1 + + + + + + + + + + + + diff --git a/tests/generators/procedures.xml b/tests/generators/procedures.xml new file mode 100644 index 000000000..dab575126 --- /dev/null +++ b/tests/generators/procedures.xml @@ -0,0 +1,521 @@ + + + + + + + + + + + test recurse + + + + + + + + 3 + + + + + + + -1-2-1-3-1-2-1- + + + + + + + + + + + + test procedure + + + + + + + + + 8 + + + + + 2 + + + + + procedure with global + + + proc z + + + + + 4 + + + + + proc w + + + FALSE + + + + + + + + + + FALSE + + + + + procedure no return + TRUE + + + proc w + + + + + proc w + + + FALSE + + + + + + + + + + TRUE + + + + + procedure return + FALSE + + + proc w + + + + + + + + + + + + + + + + + + + + + + + + + procedure 1 + + + proc z + + + DIVIDE + + + proc x + + + + + proc y + + + + + + + + + + + + procedure 2 + + + + + + proc x + + + + + proc w + + + TRUE + + + + + + + + + + test function + + + function with arguments + + + + + + + + + 2 + + + + + 3 + + + + + + + -1 + + + + + function with side effect + + + func z + + + + + side effect + + + + + func a + + + unchanged + + + + + func c + + + global + + + + + function with global + + + + + + + + 2 + + + + + + + 3global + + + + + function with scope + + + func a + + + + + unchanged + + + + + function return + TRUE + + + + + + + + TRUE + + + + + + + function no return + FALSE + + + + + + + + FALSE + + + + + + + + + + + + + + + + + + + + + + + + + + + function 1 + + + func z + + + side effect + + + + + + + MINUS + + + func x + + + + + func y + + + + + + + + + + function 2 + + + func a + + + 1 + + + + + + + + + + func a + + + + + func c + + + + + + + + + + function 3 + + + + + + func a + + + + + TRUE + + + + + + + FALSE + + + + + + + + recurse + + + + + + GT + + + n + + + + + 0 + + + + + + + text + + + + + + + + + + + MINUS + + + n + + + + + 1 + + + + + + + + + n + + + + + + + + + + MINUS + + + n + + + + + 1 + + + + + + + + + + + + + text + + + - + + + + + + + + + text + + + + diff --git a/tests/generators/text.xml b/tests/generators/text.xml new file mode 100644 index 000000000..ccdc151f1 --- /dev/null +++ b/tests/generators/text.xml @@ -0,0 +1,719 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + test length + + + length + + + + + Google + + + + + + + 6 + + + + + length + + + + + + + + + + + + 0 + + + + + + + + + + test empty + + + not empty + FALSE + + + + + Google + + + + + + + empty + TRUE + + + + + + + + + + + + + + + + + test create text + + + single text + + + + + + Hello + + + + + + + Hello + + + + + double text + + + + + + K + + + + + 9 + + + + + + + K9 + + + + + triple text + + + + + + 1 + + + + + 2 + + + + + 3 + + + + + + + 123 + + + + + + + + + + + + test append item + + + item + + + Miserable + + + + + item + + + Failure + + + + + append text + + + item + + + + + MiserableFailure + + + + + item + + + 12 + + + + + item + + + 34 + + + + + append number + + + item + + + + + 1234 + + + + + + + + + + + + + + + + + + test substring + + + text + + + 123456789 + + + + + substring # start + + + + FROM_START + FROM_START + + + text + + + + + 2 + + + + + 3 + + + + + + + 23 + + + + + substring # end + + + + FROM_END + FROM_END + + + text + + + + + 3 + + + + + 2 + + + + + + + 78 + + + + + substring first-last + + + + FIRST + LAST + + + text + + + + + + + text + + + + + + + + + + + + + + test find + + + first find + + + FIRST + + + Banana + + + + + an + + + + + + + 2 + + + + + last find + + + LAST + + + Banana + + + + + an + + + + + + + 4 + + + + + no find + + + FIRST + + + Banana + + + + + Peel + + + + + + + 0 + + + + + + + + + + + + test letter + + + letter # + + + + FROM_START + + + Blockly + + + + + 3 + + + + + + + o + + + + + letter # from end + + + + FROM_END + + + Blockly + + + + + 3 + + + + + + + k + + + + + first letter + + + + FIRST + + + Blockly + + + + + + + B + + + + + last letter + + + + LAST + + + Blockly + + + + + + + y + + + + + random letter + TRUE + + + + POSITIVE + + + FIRST + + + Blockly + + + + + + RANDOM + + + Blockly + + + + + + + + + + + + + + + + + + + + + + test case + + + uppercase + + + UPPERCASE + + + Hello World + + + + + + + HELLO WORLD + + + + + lowercase + + + LOWERCASE + + + Hello World + + + + + + + hello world + + + + + titlecase + + + TITLECASE + + + heLLo WorlD + + + + + + + Hello World + + + + + + + + + + + + test trim + + + trim both + + + + BOTH + + + abc def + + + + + + + abc def + + + + + trim left + + + + LEFT + + + abc def + + + + + + + abc def + + + + + trim right + + + + RIGHT + + + abc def + + + + + + + abc def + + + + + + + + + + diff --git a/tests/generators/unittest.js b/tests/generators/unittest.js new file mode 100644 index 000000000..f8c00c38a --- /dev/null +++ b/tests/generators/unittest.js @@ -0,0 +1,93 @@ +/** + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Unit test blocks for Blockly. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +Blockly.Blocks['unittest_main'] = { + // Container for unit tests. + init: function() { + this.setColour(65); + this.appendDummyInput() + .appendTitle('run tests'); + this.appendStatementInput('DO'); + this.setTooltip('Executes the enclosed unit tests,\n' + + 'then prints a summary.'); + }, + getVars: function() { + return ['unittestResults']; + } +}; + +Blockly.Blocks['unittest_assertequals'] = { + // Asserts that a value equals another value. + init: function() { + this.setColour(65); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.appendDummyInput() + .appendTitle(new Blockly.FieldTextInput('test name'), 'MESSAGE'); + this.appendValueInput('ACTUAL', null) + .appendTitle('actual'); + this.appendValueInput('EXPECTED', null) + .appendTitle('expected'); + this.setTooltip('Tests that "actual == expected".'); + }, + getVars: function() { + return ['unittestResults']; + } +}; + +Blockly.Blocks['unittest_assertvalue'] = { + // Asserts that a value is true, false, or null. + init: function() { + this.setColour(65); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.appendDummyInput() + .appendTitle(new Blockly.FieldTextInput('test name'), 'MESSAGE'); + this.appendValueInput('ACTUAL', Boolean) + .appendTitle('assert') + .appendTitle(new Blockly.FieldDropdown( + [['true', 'TRUE'], ['false', 'FALSE'], ['null', 'NULL']]), 'EXPECTED'); + this.setTooltip('Tests that the value is true, false, or null.'); + }, + getVars: function() { + return ['unittestResults']; + } +}; + +Blockly.Blocks['unittest_fail'] = { + // Always assert an error. + init: function() { + this.setColour(65); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.appendDummyInput() + .appendTitle(new Blockly.FieldTextInput('test name'), 'MESSAGE') + .appendTitle('fail'); + this.setTooltip('Records an error.'); + }, + getVars: function() { + return ['unittestResults']; + } +}; diff --git a/tests/generators/unittest_javascript.js b/tests/generators/unittest_javascript.js new file mode 100644 index 000000000..4a3d2dcff --- /dev/null +++ b/tests/generators/unittest_javascript.js @@ -0,0 +1,191 @@ +/** + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Generating JavaScript for unit test blocks. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +Blockly.JavaScript['unittest_main'] = function(block) { + // Container for unit tests. + var resultsVar = Blockly.JavaScript.variableDB_.getName('unittestResults', + Blockly.Variables.NAME_TYPE); + if (!Blockly.JavaScript.definitions_['unittest_report']) { + var functionName = Blockly.JavaScript.variableDB_.getDistinctName( + 'testReport', Blockly.Generator.NAME_TYPE); + Blockly.JavaScript['unittest_main'].report = functionName; + var func = []; + func.push('function ' + functionName + '() {'); + func.push(' // Create test report.'); + func.push(' var report = [];'); + func.push(' var summary = [];'); + func.push(' var fails = 0;'); + func.push(' for (var x = 0; x < ' + resultsVar + '.length; x++) {'); + func.push(' if (' + resultsVar + '[x][0]) {'); + func.push(' summary.push(".");'); + func.push(' } else {'); + func.push(' summary.push("F");'); + func.push(' fails++;'); + func.push(' report.push("");'); + func.push(' report.push("FAIL: " + ' + resultsVar + '[x][2]);'); + func.push(' report.push(' + resultsVar + '[x][1]);'); + func.push(' }'); + func.push(' }'); + func.push(' report.unshift(summary.join(""));'); + func.push(' report.push("");'); + func.push(' report.push("Number of tests run: " + ' + resultsVar + + '.length);'); + func.push(' report.push("");'); + func.push(' if (fails) {'); + func.push(' report.push("FAILED (failures=" + fails + ")");'); + func.push(' } else {'); + func.push(' report.push("OK");'); + func.push(' }'); + func.push(' return report.join("\\n");'); + func.push('}'); + func.push(''); + Blockly.JavaScript.definitions_['unittest_report'] = func.join('\n'); + } + // Setup global to hold test results. + var code = resultsVar + ' = [];\n'; + // Run tests (unindented). + code += Blockly.JavaScript.statementToCode(block, 'DO') + .replace(/^ /, '').replace(/\n /g, '\n'); + var reportVar = Blockly.JavaScript.variableDB_.getDistinctName( + 'report', Blockly.Variables.NAME_TYPE); + code += 'var ' + reportVar + ' = ' + + Blockly.JavaScript['unittest_main'].report + '();\n'; + // Destroy results. + code += resultsVar + ' = null;\n'; + // Send the report to the console (that's where errors will go anyway). + code += 'console.log(' + reportVar + ');\n'; + return code; +}; + +// Code by Tomáš Zato on Stack Overflow [overflow.com/questions/7837456] +// with minor changes for style. +Array.prototype.equals = function(array) { + // Is it an array? + if (!array || !(array instanceof Array)) { + return false; + } + + // Are they the same length? + if (this.length != array.length) { + return false; + } + + for (var i = 0; i < this.length; i++) { + // Check for nested arrays. + if (this[i] instanceof Array && array[i] instanceof Array) { + // Recurse into the nested arrays. + if (!this[i].equals(array[i])) { + return false; + } + } + else if (this[i] !== array[i]) { + return false; + } + } + return true; +}; + +Blockly.JavaScript['unittest_main'].defineAssert_ = function(block) { + if (!Blockly.JavaScript.definitions_['unittest_assertequals']) { + var resultsVar = Blockly.JavaScript.variableDB_.getName('unittestResults', + Blockly.Variables.NAME_TYPE); + var functionName = Blockly.JavaScript.variableDB_.getDistinctName( + 'assertEquals', Blockly.Generator.NAME_TYPE); + Blockly.JavaScript['unittest_main'].assert_ = functionName; + var func = []; + func.push('function ' + functionName + '(actual, expected, message) {'); + func.push(' // Asserts that a value equals another value.'); + func.push(' if (!' + resultsVar + ') {'); + func.push(' throw "Orphaned assert: " + message;'); + func.push(' }'); + func.push(' if ((expected instanceof Array &&'); + func.push(' expected.equals(actual)) ||'); + func.push(' actual === expected) {'); + func.push(' ' + resultsVar + '.push([true, "OK", message]);'); + func.push(' } else {'); + func.push(' ' + resultsVar + '.push([false, ' + + '"Expected: " + expected + "\\nActual: " + actual, message]);'); + func.push(' }'); + func.push('}'); + func.push(''); + Blockly.JavaScript.definitions_['unittest_assertequals'] = func.join('\n'); + } + return Blockly.JavaScript['unittest_main'].assert_; +}; + +Blockly.JavaScript['unittest_assertequals'] = function(block) { + // Asserts that a value equals another value. + var resultsVar = Blockly.JavaScript.variableDB_.getName('unittestResults', + Blockly.Variables.NAME_TYPE); + var message = Blockly.JavaScript.quote_(block.getTitleValue('MESSAGE')); + var actual = Blockly.JavaScript.valueToCode(block, 'ACTUAL', + Blockly.JavaScript.ORDER_COMMA) || 'null'; + var expected = Blockly.JavaScript.valueToCode(block, 'EXPECTED', + Blockly.JavaScript.ORDER_COMMA) || 'null'; + return Blockly.JavaScript['unittest_main'].defineAssert_() + + '(' + actual + ', ' + expected + ', ' + message + ');\n'; +}; + +Blockly.JavaScript['unittest_assertvalue'] = function(block) { + // Asserts that a value is true, false, or null. + var resultsVar = Blockly.JavaScript.variableDB_.getName('unittestResults', + Blockly.Variables.NAME_TYPE); + var message = Blockly.JavaScript.quote_(block.getTitleValue('MESSAGE')); + var actual = Blockly.JavaScript.valueToCode(block, 'ACTUAL', + Blockly.JavaScript.ORDER_COMMA) || 'null'; + var expected = block.getTitleValue('EXPECTED'); + if (expected == 'TRUE') { + expected = 'true'; + } else if (expected == 'FALSE') { + expected = 'false'; + } else if (expected == 'NULL') { + expected = 'null'; + } + return Blockly.JavaScript['unittest_main'].defineAssert_() + + '(' + actual + ', ' + expected + ', ' + message + ');\n'; +}; + +Blockly.JavaScript['unittest_fail'] = function(block) { + // Always assert an error. + var resultsVar = Blockly.JavaScript.variableDB_.getName('unittestResults', + Blockly.Variables.NAME_TYPE); + var message = Blockly.JavaScript.quote_(block.getTitleValue('MESSAGE')); + if (!Blockly.JavaScript.definitions_['unittest_fail']) { + var functionName = Blockly.JavaScript.variableDB_.getDistinctName( + 'fail', Blockly.Generator.NAME_TYPE); + Blockly.JavaScript['unittest_fail'].assert = functionName; + var func = []; + func.push('function ' + functionName + '(message) {'); + func.push(' // Always assert an error.'); + func.push(' if (!' + resultsVar + ') {'); + func.push(' throw "Orphaned assert fail: ' + message + '";'); + func.push(' }'); + func.push(' ' + resultsVar + '.push([false, "Fail.", message]);'); + func.push('}'); + func.push(''); + Blockly.JavaScript.definitions_['unittest_fail'] = func.join('\n'); + } + return Blockly.JavaScript['unittest_fail'].assert + '(' + message + ');\n'; +}; diff --git a/tests/generators/unittest_python.js b/tests/generators/unittest_python.js new file mode 100644 index 000000000..7fc205f6e --- /dev/null +++ b/tests/generators/unittest_python.js @@ -0,0 +1,130 @@ +/** + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ + +/** + * @fileoverview Generating Python for unit test blocks. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +Blockly.Python['unittest_main'] = function(block) { + // Container for unit tests. + var resultsVar = Blockly.Python.variableDB_.getName('unittestResults', + Blockly.Variables.NAME_TYPE); + var functionName = Blockly.Python.provideFunction_( + 'unittest_report', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '():', + ' # Create test report.', + ' report = []', + ' summary = []', + ' fails = 0', + ' for (success, log, message) in ' + resultsVar + ':', + ' if success:', + ' summary.append(".")', + ' else:', + ' summary.append("F")', + ' fails += 1', + ' report.append("")', + ' report.append("FAIL: " + message)', + ' report.append(log)', + ' report.insert(0, "".join(summary))', + ' report.append("")', + ' report.append("Number of tests run: %d" % len(' + resultsVar + '))', + ' report.append("")', + ' if fails:', + ' report.append("FAILED (failures=%d)" % fails)', + ' else:', + ' report.append("OK")', + ' return "\\n".join(report)']); + + // Setup global to hold test results. + var code = resultsVar + ' = []\n'; + // Run tests (unindented). + code += Blockly.Python.statementToCode(block, 'DO') + .replace(/^ /, '').replace(/\n /g, '\n'); + var reportVar = Blockly.Python.variableDB_.getDistinctName( + 'report', Blockly.Variables.NAME_TYPE); + code += reportVar + ' = ' + functionName + '()\n'; + // Destroy results. + code += resultsVar + ' = None\n'; + // Print the report. + code += 'print(' + reportVar + ')\n'; + return code; +}; + +Blockly.Python['unittest_main'].defineAssert_ = function() { + var resultsVar = Blockly.Python.variableDB_.getName('unittestResults', + Blockly.Variables.NAME_TYPE); + var functionName = Blockly.Python.provideFunction_( + 'assertEquals', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + + '(actual, expected, message):', + ' # Asserts that a value equals another value.', + ' if ' + resultsVar + ' == None:', + ' raise Exception("Orphaned assert equals: " + message)', + ' if actual == expected:', + ' ' + resultsVar + '.append((True, "OK", message))', + ' else:', + ' ' + resultsVar + '.append((False, ' + + '"Expected: %s\\nActual: %s" % (expected, actual), message))']); + return functionName; +}; + +Blockly.Python['unittest_assertequals'] = function(block) { + // Asserts that a value equals another value. + var message = Blockly.Python.quote_(block.getTitleValue('MESSAGE')); + var actual = Blockly.Python.valueToCode(block, 'ACTUAL', + Blockly.Python.ORDER_NONE) || 'None'; + var expected = Blockly.Python.valueToCode(block, 'EXPECTED', + Blockly.Python.ORDER_NONE) || 'None'; + return Blockly.Python['unittest_main'].defineAssert_() + + '(' + actual + ', ' + expected + ', ' + message + ')\n'; +}; + +Blockly.Python['unittest_assertvalue'] = function(block) { + // Asserts that a value is true, false, or null. + var message = Blockly.Python.quote_(block.getTitleValue('MESSAGE')); + var actual = Blockly.Python.valueToCode(block, 'ACTUAL', + Blockly.Python.ORDER_NONE) || 'None'; + var expected = block.getTitleValue('EXPECTED'); + if (expected == 'TRUE') { + expected = 'True'; + } else if (expected == 'FALSE') { + expected = 'False'; + } else if (expected == 'NULL') { + expected = 'None'; + } + return Blockly.Python['unittest_main'].defineAssert_() + + '(' + actual + ', ' + expected + ', ' + message + ')\n'; +}; + +Blockly.Python['unittest_fail'] = function(block) { + // Always assert an error. + var resultsVar = Blockly.Python.variableDB_.getName('unittestResults', + Blockly.Variables.NAME_TYPE); + var message = Blockly.Python.quote_(block.getTitleValue('MESSAGE')); + var functionName = Blockly.Python.provideFunction_( + 'fail', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(message):', + ' # Always assert an error.', + ' if ' + resultsVar + ' == None:', + ' raise Exception("Orphaned assert equals: ' + message + '")', + ' ' + resultsVar + '.append((False, "Fail.", message))']); + return functionName + '(' + message + ')\n'; +}; diff --git a/tests/generators/variables.xml b/tests/generators/variables.xml new file mode 100644 index 000000000..1fa627058 --- /dev/null +++ b/tests/generators/variables.xml @@ -0,0 +1,54 @@ + + + + + item + + + 123 + + + + + variable + + + item + + + + + 123 + + + + + if + + + 123 + + + + + reserved variable + + + if + + + + + 123 + + + + + + + + + + + + diff --git a/tests/names_test.js b/tests/names_test.js new file mode 100644 index 000000000..3affb4e31 --- /dev/null +++ b/tests/names_test.js @@ -0,0 +1,61 @@ +/** + * Blockly Tests + * + * Copyright 2012 Google Inc. + * http://blockly.googlecode.com/ + * + * 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. + */ +'use strict'; + +function test_safeName() { + var varDB = new Blockly.Names('window,door'); + assertEquals('SafeName empty.', 'unnamed', varDB.safeName_('')); + assertEquals('SafeName ok.', 'foobar', varDB.safeName_('foobar')); + assertEquals('SafeName number start.', 'my_9lives', + varDB.safeName_('9lives')); + assertEquals('SafeName number end.', 'lives9', varDB.safeName_('lives9')); + assertEquals('SafeName special chars.', '____', varDB.safeName_('!@#$')); + assertEquals('SafeName reserved.', 'door', varDB.safeName_('door')); +} + +function test_getName() { + var varDB = new Blockly.Names('window,door'); + assertEquals('Name add #1.', 'Foo_bar', varDB.getName('Foo.bar', 'var')); + assertEquals('Name get #1.', 'Foo_bar', varDB.getName('Foo.bar', 'var')); + assertEquals('Name add #2.', 'Foo_bar2', varDB.getName('Foo bar', 'var')); + assertEquals('Name get #2.', 'Foo_bar2', varDB.getName('foo BAR', 'var')); + assertEquals('Name add #3.', 'door2', varDB.getName('door', 'var')); + assertEquals('Name add #4.', 'Foo_bar3', varDB.getName('Foo.bar', 'proc')); + assertEquals('Name get #1b.', 'Foo_bar', varDB.getName('Foo.bar', 'var')); + assertEquals('Name get #4.', 'Foo_bar3', varDB.getName('Foo.bar', 'proc')); +} + +function test_getDistinctName() { + var varDB = new Blockly.Names('window,door'); + assertEquals('Name distinct #1.', 'Foo_bar', + varDB.getDistinctName('Foo.bar', 'var')); + assertEquals('Name distinct #2.', 'Foo_bar2', + varDB.getDistinctName('Foo.bar', 'var')); + assertEquals('Name distinct #3.', 'Foo_bar3', + varDB.getDistinctName('Foo.bar', 'proc')); + varDB.reset(); + assertEquals('Name distinct #4.', 'Foo_bar', + varDB.getDistinctName('Foo.bar', 'var')); +} + +function test_nameEquals() { + assertTrue('Name equals #1.', Blockly.Names.equals('Foo.bar', 'Foo.bar')); + assertFalse('Name equals #2.', Blockly.Names.equals('Foo.bar', 'Foo_bar')); + assertTrue('Name equals #3.', Blockly.Names.equals('Foo.bar', 'FOO.BAR')); +} diff --git a/tests/playground.html b/tests/playground.html new file mode 100644 index 000000000..edc3e8446 --- /dev/null +++ b/tests/playground.html @@ -0,0 +1,310 @@ + + + + +Blockly Playground + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + +

    Blockly Playground

    + +

    Show + - Hide

    + + + +

    + +   + +
    + +   + +
    + +

    +
    + +

    + Stress test with an +

    + + + + +