diff --git a/helpers/DATA/sugar-toolkit-gtk3/git-20201017.patch b/helpers/DATA/sugar-toolkit-gtk3/git-20201017.patch new file mode 100644 index 0000000000000000000000000000000000000000..8ecfad1e9d5e481ce53dbb939f45325e4a6809d5 --- /dev/null +++ b/helpers/DATA/sugar-toolkit-gtk3/git-20201017.patch @@ -0,0 +1,5017 @@ +diff --git b/.flake8 a/.flake8 +new file mode 100644 +index 0000000..0146a5f +--- /dev/null ++++ a/.flake8 +@@ -0,0 +1,6 @@ ++[flake8] ++ ++# E402 module level import not at top of file ++# gi.require_version() is required before later imports ++ ++ignore = E402 +diff --git b/MAINTAINERS a/MAINTAINERS +new file mode 100644 +index 0000000..d9dcae7 +--- /dev/null ++++ a/MAINTAINERS +@@ -0,0 +1,3 @@ ++Daniel Drake dsd@laptop.org ++Simon Schampijer simon@laptop.org ++ +diff --git b/README.md a/README.md +new file mode 100644 +index 0000000..c074e93 +--- /dev/null ++++ a/README.md +@@ -0,0 +1,47 @@ ++Sugar Toolkit ++============= ++ ++Sugar Toolkit provides services and a set of GTK+ widgets to build ++activities and other Sugar components on Linux based computers. ++ ++This is the GTK+ 3 binding of the Sugar Toolkit. ++ ++https://www.sugarlabs.org/ ++ ++https://wiki.sugarlabs.org/ ++ ++Installing on Debian or Ubuntu ++------------------------------ ++ ++Automatically done when you install [Sugar ++desktop](https://github.com/sugarlabs/sugar). ++ ++To install Sugar Toolkit alone without Sugar desktop, ++ ++``` ++sudo apt install python-sugar3 ++``` ++ ++Installing on Fedora ++-------------------- ++ ++Automatically done when you install [Sugar ++desktop](https://github.com/sugarlabs/sugar). ++ ++To install Sugar Toolkit alone without Sugar desktop, ++ ++``` ++sudo dnf install sugar-toolkit-gtk3 ++``` ++ ++Building ++-------- ++ ++Sugar Toolkit follows the [GNU Coding ++Standards](https://www.gnu.org/prep/standards/). ++ ++Install all dependencies, especially sugar-artwork and ++sugar-datastore. ++ ++Clone the repository, run `autogen.sh`, then `make` and `make ++install`. +diff --git b/autogen.sh a/autogen.sh +new file mode 100755 +index 0000000..dac7bf4 +--- /dev/null ++++ a/autogen.sh +@@ -0,0 +1,15 @@ ++#!/bin/sh ++ ++test -n "${srcdir}" || srcdir=`dirname "$0"` ++test -n "${srcdir}" || srcdir="$(pwd)" ++ ++olddir="$(pwd)" ++cd "$srcdir" ++ ++mkdir -p m4 ++ ++intltoolize ++autoreconf -i ++ ++cd "$olddir" ++"$srcdir/configure" --enable-maintainer-mode "$@" +diff --git b/bin/sugar-activity-web a/bin/sugar-activity-web +index 8fd7a59..d1db3fd 100644 +--- b/bin/sugar-activity-web ++++ a/bin/sugar-activity-web +@@ -17,8 +17,4 @@ + # Free Software Foundation, Inc., 59 Temple Place - Suite 330, + # Boston, MA 02111-1307, USA. + +-if [ "$SUGAR_USE_WEBKIT1" = "yes" ]; then +- exec sugar-activity3 sugar3.activity.webkit1.WebActivity $@ +-else +- exec sugar-activity3 sugar3.activity.webactivity.WebActivity $@ +-fi ++exec sugar-activity3 sugar3.activity.webactivity.WebActivity $@ +diff --git b/doc/Makefile a/doc/Makefile +new file mode 100644 +index 0000000..60e9ad5 +--- /dev/null ++++ a/doc/Makefile +@@ -0,0 +1,193 @@ ++# Makefile for Sphinx documentation ++# ++ ++# You can set these variables from the command line. ++SPHINXOPTS = ++SPHINXBUILD = sphinx-build ++PAPER = ++BUILDDIR = _build ++ ++# User-friendly check for sphinx-build ++ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) ++$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) ++endif ++ ++# Internal variables. ++PAPEROPT_a4 = -D latex_paper_size=a4 ++PAPEROPT_letter = -D latex_paper_size=letter ++ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . ++# the i18n builder cannot share the environment and doctrees with the others ++I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . ++ ++.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext ++ ++help: ++ @echo "Please use \`make <target>' where <target> is one of" ++ @echo " html to make standalone HTML files" ++ @echo " dirhtml to make HTML files named index.html in directories" ++ @echo " singlehtml to make a single large HTML file" ++ @echo " pickle to make pickle files" ++ @echo " json to make JSON files" ++ @echo " htmlhelp to make HTML files and a HTML help project" ++ @echo " qthelp to make HTML files and a qthelp project" ++ @echo " applehelp to make an Apple Help Book" ++ @echo " devhelp to make HTML files and a Devhelp project" ++ @echo " epub to make an epub" ++ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" ++ @echo " latexpdf to make LaTeX files and run them through pdflatex" ++ @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" ++ @echo " text to make text files" ++ @echo " man to make manual pages" ++ @echo " texinfo to make Texinfo files" ++ @echo " info to make Texinfo files and run them through makeinfo" ++ @echo " gettext to make PO message catalogs" ++ @echo " changes to make an overview of all changed/added/deprecated items" ++ @echo " xml to make Docutils-native XML files" ++ @echo " pseudoxml to make pseudoxml-XML files for display purposes" ++ @echo " linkcheck to check all external links for integrity" ++ @echo " doctest to run all doctests embedded in the documentation (if enabled)" ++ @echo " coverage to run coverage check of the documentation (if enabled)" ++ ++clean: ++ rm -rf $(BUILDDIR)/* ++ ++html: ++ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html ++ @echo ++ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." ++ ++dirhtml: ++ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml ++ @echo ++ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." ++ ++singlehtml: ++ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml ++ @echo ++ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." ++ ++pickle: ++ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle ++ @echo ++ @echo "Build finished; now you can process the pickle files." ++ ++json: ++ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json ++ @echo ++ @echo "Build finished; now you can process the JSON files." ++ ++htmlhelp: ++ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp ++ @echo ++ @echo "Build finished; now you can run HTML Help Workshop with the" \ ++ ".hhp project file in $(BUILDDIR)/htmlhelp." ++ ++qthelp: ++ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp ++ @echo ++ @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ++ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" ++ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/SugarToolkitGTK3.qhcp" ++ @echo "To view the help file:" ++ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/SugarToolkitGTK3.qhc" ++ ++applehelp: ++ $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp ++ @echo ++ @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." ++ @echo "N.B. You won't be able to view it unless you put it in" \ ++ "~/Library/Documentation/Help or install it in your application" \ ++ "bundle." ++ ++devhelp: ++ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp ++ @echo ++ @echo "Build finished." ++ @echo "To view the help file:" ++ @echo "# mkdir -p $$HOME/.local/share/devhelp/SugarToolkitGTK3" ++ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/SugarToolkitGTK3" ++ @echo "# devhelp" ++ ++epub: ++ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub ++ @echo ++ @echo "Build finished. The epub file is in $(BUILDDIR)/epub." ++ ++latex: ++ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex ++ @echo ++ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." ++ @echo "Run \`make' in that directory to run these through (pdf)latex" \ ++ "(use \`make latexpdf' here to do that automatically)." ++ ++latexpdf: ++ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex ++ @echo "Running LaTeX files through pdflatex..." ++ $(MAKE) -C $(BUILDDIR)/latex all-pdf ++ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." ++ ++latexpdfja: ++ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex ++ @echo "Running LaTeX files through platex and dvipdfmx..." ++ $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja ++ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." ++ ++text: ++ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text ++ @echo ++ @echo "Build finished. The text files are in $(BUILDDIR)/text." ++ ++man: ++ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man ++ @echo ++ @echo "Build finished. The manual pages are in $(BUILDDIR)/man." ++ ++texinfo: ++ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo ++ @echo ++ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." ++ @echo "Run \`make' in that directory to run these through makeinfo" \ ++ "(use \`make info' here to do that automatically)." ++ ++info: ++ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo ++ @echo "Running Texinfo files through makeinfo..." ++ make -C $(BUILDDIR)/texinfo info ++ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." ++ ++gettext: ++ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale ++ @echo ++ @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." ++ ++changes: ++ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes ++ @echo ++ @echo "The overview file is in $(BUILDDIR)/changes." ++ ++linkcheck: ++ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck ++ @echo ++ @echo "Link check complete; look for any errors in the above output " \ ++ "or in $(BUILDDIR)/linkcheck/output.txt." ++ ++doctest: ++ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest ++ @echo "Testing of doctests in the sources finished, look at the " \ ++ "results in $(BUILDDIR)/doctest/output.txt." ++ ++coverage: ++ $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage ++ @echo "Testing of coverage in the sources finished, look at the " \ ++ "results in $(BUILDDIR)/coverage/python.txt." ++ ++xml: ++ $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml ++ @echo ++ @echo "Build finished. The XML files are in $(BUILDDIR)/xml." ++ ++pseudoxml: ++ $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml ++ @echo ++ @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." ++ +diff --git b/doc/conf.py a/doc/conf.py +new file mode 100644 +index 0000000..26a811e +--- /dev/null ++++ a/doc/conf.py +@@ -0,0 +1,305 @@ ++# -*- coding: utf-8 -*- ++# ++# Sugar Toolkit GTK3 documentation build configuration file, created by ++# sphinx-quickstart on Sat Aug 1 21:36:44 2015. ++# ++# This file is execfile()d with the current directory set to its ++# containing dir. ++# ++# Note that not all possible configuration values are present in this ++# autogenerated file. ++# ++# All configuration values have a default; values that are commented out ++# serve to show the default. ++ ++import sys ++import os ++from sphinx import version_info ++ ++major, minor, patch, label, label_number = version_info ++ ++# If extensions (or modules to document with autodoc) are in another directory, ++# add these directories to sys.path here. If the directory is relative to the ++# documentation root, use os.path.abspath to make it absolute, like shown here. ++sys.path.insert(0, os.path.abspath('../src')) ++ ++# -- General configuration ------------------------------------------------ ++ ++# If your documentation needs a minimal Sphinx version, state it here. ++#needs_sphinx = '1.0' ++ ++# Add any Sphinx extension module names here, as strings. They can be ++# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ++# ones. ++extensions = [ ++ 'sphinx.ext.autodoc', ++ 'sphinx.ext.intersphinx' ++] ++if major >= 1 and minor >= 3: ++ # Included in Sphinx 1.3 ++ extensions.append('sphinx.ext.napoleon') ++else: ++ extensions.append('sphinxcontrib.napoleon') ++ ++intersphinx_mapping = { ++ 'glib': ('http://lazka.github.io/pgi-docs/GLib-2.0', None), ++ 'gobject': ('http://lazka.github.io/pgi-docs/GObject-2.0', None), ++ 'gio': ('http://lazka.github.io/pgi-docs/Gio-2.0', None), ++ 'gtk': ('http://lazka.github.io/pgi-docs/Gtk-3.0', None) ++} ++ ++primary_domain = "py" ++ ++# Add any paths that contain templates here, relative to this directory. ++templates_path = ['_templates'] ++ ++# The suffix(es) of source filenames. ++# You can specify multiple suffix as a list of string: ++# source_suffix = ['.rst', '.md'] ++source_suffix = '.rst' ++ ++# The encoding of source files. ++#source_encoding = 'utf-8-sig' ++ ++# The master toctree document. ++master_doc = 'index' ++ ++# General information about the project. ++project = u'Sugar Toolkit GTK3' ++copyright = u'2017, Sugar Labs' ++author = u'Sugar Labs' ++ ++# The version info for the project you're documenting, acts as replacement for ++# |version| and |release|, also used in various other places throughout the ++# built documents. ++# ++# The short X.Y version. ++version = '0.117' ++# The full version, including alpha/beta/rc tags. ++release = '0.117' ++ ++# The language for content autogenerated by Sphinx. Refer to documentation ++# for a list of supported languages. ++# ++# This is also used if you do content translation via gettext catalogs. ++# Usually you set "language" from the command line for these cases. ++language = None ++ ++# There are two options for replacing |today|: either, you set today to some ++# non-false value, then it is used: ++#today = '' ++# Else, today_fmt is used as the format for a strftime call. ++#today_fmt = '%B %d, %Y' ++ ++# List of patterns, relative to source directory, that match files and ++# directories to ignore when looking for source files. ++exclude_patterns = ['_build'] ++ ++# The reST default role (used for this markup: `text`) to use for all ++# documents. ++#default_role = None ++ ++# If true, '()' will be appended to :func: etc. cross-reference text. ++#add_function_parentheses = True ++ ++# If true, the current module name will be prepended to all description ++# unit titles (such as .. function::). ++#add_module_names = True ++ ++# If true, sectionauthor and moduleauthor directives will be shown in the ++# output. They are ignored by default. ++#show_authors = False ++ ++# The name of the Pygments (syntax highlighting) style to use. ++pygments_style = 'sphinx' ++ ++# A list of ignored prefixes for module index sorting. ++#modindex_common_prefix = [] ++ ++# If true, keep warnings as "system message" paragraphs in the built documents. ++#keep_warnings = False ++ ++# If true, `todo` and `todoList` produce output, else they produce nothing. ++todo_include_todos = False ++ ++ ++# -- Options for HTML output ---------------------------------------------- ++ ++# The theme to use for HTML and HTML Help pages. See the documentation for ++# a list of builtin themes. ++if major >= 1 and minor >= 3: ++ # Added in Sphinx 1.3 ++ html_theme = 'alabaster' ++ ++# Theme options are theme-specific and customize the look and feel of a theme ++# further. For a list of options available for each theme, see the ++# documentation. ++#html_theme_options = {} ++ ++# Add any paths that contain custom themes here, relative to this directory. ++#html_theme_path = [] ++ ++# The name for this set of Sphinx documents. If None, it defaults to ++# "<project> v<release> documentation". ++#html_title = None ++ ++# A shorter title for the navigation bar. Default is the same as html_title. ++#html_short_title = None ++ ++# The name of an image file (relative to this directory) to place at the top ++# of the sidebar. ++#html_logo = None ++ ++# The name of an image file (within the static path) to use as favicon of the ++# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 ++# pixels large. ++#html_favicon = None ++ ++# Add any paths that contain custom static files (such as style sheets) here, ++# relative to this directory. They are copied after the builtin static files, ++# so a file named "default.css" will overwrite the builtin "default.css". ++html_static_path = ['_static'] ++ ++# Add any extra paths that contain custom files (such as robots.txt or ++# .htaccess) here, relative to this directory. These files are copied ++# directly to the root of the documentation. ++#html_extra_path = [] ++ ++# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, ++# using the given strftime format. ++#html_last_updated_fmt = '%b %d, %Y' ++ ++# If true, SmartyPants will be used to convert quotes and dashes to ++# typographically correct entities. ++#html_use_smartypants = True ++ ++# Custom sidebar templates, maps document names to template names. ++#html_sidebars = {} ++ ++# Additional templates that should be rendered to pages, maps page names to ++# template names. ++#html_additional_pages = {} ++ ++# If false, no module index is generated. ++#html_domain_indices = True ++ ++# If false, no index is generated. ++#html_use_index = True ++ ++# If true, the index is split into individual pages for each letter. ++#html_split_index = False ++ ++# If true, links to the reST sources are added to the pages. ++#html_show_sourcelink = True ++ ++# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. ++#html_show_sphinx = True ++ ++# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. ++#html_show_copyright = True ++ ++# If true, an OpenSearch description file will be output, and all pages will ++# contain a <link> tag referring to it. The value of this option must be the ++# base URL from which the finished HTML is served. ++#html_use_opensearch = '' ++ ++# This is the file name suffix for HTML files (e.g. ".xhtml"). ++#html_file_suffix = None ++ ++# Language to be used for generating the HTML full-text search index. ++# Sphinx supports the following languages: ++# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' ++# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' ++#html_search_language = 'en' ++ ++# A dictionary with options for the search language support, empty by default. ++# Now only 'ja' uses this config value ++#html_search_options = {'type': 'default'} ++ ++# The name of a javascript file (relative to the configuration directory) that ++# implements a search results scorer. If empty, the default will be used. ++#html_search_scorer = 'scorer.js' ++ ++# Output file base name for HTML help builder. ++htmlhelp_basename = 'SugarToolkitGTK3doc' ++ ++# -- Options for LaTeX output --------------------------------------------- ++ ++latex_elements = { ++ # The paper size ('letterpaper' or 'a4paper'). ++ #'papersize': 'letterpaper', ++ ++ # The font size ('10pt', '11pt' or '12pt'). ++ #'pointsize': '10pt', ++ ++ # Additional stuff for the LaTeX preamble. ++ #'preamble': '', ++ ++ # Latex figure (float) alignment ++ #'figure_align': 'htbp', ++} ++ ++# Grouping the document tree into LaTeX files. List of tuples ++# (source start file, target name, title, ++# author, documentclass [howto, manual, or own class]). ++latex_documents = [ ++ (master_doc, 'SugarToolkitGTK3.tex', u'Sugar Toolkit GTK3 Documentation', ++ u'Sugar Labs', 'manual'), ++] ++ ++# The name of an image file (relative to this directory) to place at the top of ++# the title page. ++#latex_logo = None ++ ++# For "manual" documents, if this is true, then toplevel headings are parts, ++# not chapters. ++#latex_use_parts = False ++ ++# If true, show page references after internal links. ++#latex_show_pagerefs = False ++ ++# If true, show URL addresses after external links. ++#latex_show_urls = False ++ ++# Documents to append as an appendix to all manuals. ++#latex_appendices = [] ++ ++# If false, no module index is generated. ++#latex_domain_indices = True ++ ++ ++# -- Options for manual page output --------------------------------------- ++ ++# One entry per manual page. List of tuples ++# (source start file, name, description, authors, manual section). ++man_pages = [ ++ (master_doc, 'sugartoolkitgtk3', u'Sugar Toolkit GTK3 Documentation', ++ [author], 1) ++] ++ ++# If true, show URL addresses after external links. ++#man_show_urls = False ++ ++ ++# -- Options for Texinfo output ------------------------------------------- ++ ++# Grouping the document tree into Texinfo files. List of tuples ++# (source start file, target name, title, author, ++# dir menu entry, description, category) ++texinfo_documents = [ ++ (master_doc, 'SugarToolkitGTK3', u'Sugar Toolkit GTK3 Documentation', ++ author, 'SugarToolkitGTK3', 'One line description of project.', ++ 'Miscellaneous'), ++] ++ ++# Documents to append as an appendix to all manuals. ++#texinfo_appendices = [] ++ ++# If false, no module index is generated. ++#texinfo_domain_indices = True ++ ++# How to display URL addresses: 'footnote', 'no', or 'inline'. ++#texinfo_show_urls = 'footnote' ++ ++# If true, do not generate a @detailmenu in the "Top" node's menu. ++#texinfo_no_detailmenu = False +diff --git b/doc/index.rst a/doc/index.rst +new file mode 100644 +index 0000000..ba28b9f +--- /dev/null ++++ a/doc/index.rst +@@ -0,0 +1,33 @@ ++Sugar Toolkit GTK3 ++================== ++ ++Sugar Toolkit GTK3, or `sugar3`, is a toolkit for writing Sugar ++activities in Python: ++ ++* write a `setup.py` which calls :class:`~sugar3.activity.bundlebuilder`, ++* write an `activity/activity.info` file with metadata, see :class:`~sugar3.bundle`, ++* write a class derived from :class:`~sugar3.activity.activity.Activity`, ++* use the :class:`~sugar3.graphics` module classes to build a user interface. ++ ++Optional modules include: ++ ++* use the :class:`~sugar3.profile` module to fetch user profile information, ++* use the :class:`~sugar3.presence` module classes to implement sharing, ++* use the :class:`~sugar3.logger` module for debug logging, ++* use the :class:`~sugar3.network` module for downloading data, ++* use the :class:`~sugar3.speech` module for speech synthesis. ++ ++Indices and tables ++================== ++ ++* :ref:`Functions and classes <genindex>` ++* :ref:`Modules <modindex>` ++* :ref:`search` ++ ++Table of Contents ++================= ++ ++.. toctree:: ++ :maxdepth: 5 ++ ++ sugar3 +diff --git b/doc/modules.rst a/doc/modules.rst +new file mode 100644 +index 0000000..126de53 +--- /dev/null ++++ a/doc/modules.rst +@@ -0,0 +1,7 @@ ++src ++=== ++ ++.. toctree:: ++ :maxdepth: 4 ++ ++ sugar3 +diff --git b/examples/alert.py a/examples/alert.py +new file mode 100644 +index 0000000..f0425cb +--- /dev/null ++++ a/examples/alert.py +@@ -0,0 +1,33 @@ ++from gi.repository import Gtk ++from sugar3.graphics.alert import TimeoutAlert ++from common import set_theme ++ ++ ++set_theme() ++w = Gtk.Window() ++w.connect("delete-event", Gtk.main_quit) ++box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) ++w.add(box) ++ ++# Create a TimeoutAlert Object ++alert = TimeoutAlert(5) ++alert.props.title = '<Alert Title>' ++alert.props.msg = '<Alert Message>' ++ ++# Add Timeout Object to the box ++box.pack_start(alert, False, False, 0) ++ ++ ++# Called when an alert object throws a response event. ++def __alert_response_cb(alert, response_id): ++ if response_id is Gtk.ResponseType.OK: ++ print('Continue Button was clicked.') ++ elif response_id is Gtk.ResponseType.CANCEL: ++ print('Cancel Button was clicked.') ++ elif response_id == -1: ++ print('Timeout occurred') ++ ++ ++alert.connect('response', __alert_response_cb) ++w.show_all() ++Gtk.main() +diff --git b/examples/animator.py a/examples/animator.py +new file mode 100644 +index 0000000..c6ede6f +--- /dev/null ++++ a/examples/animator.py +@@ -0,0 +1,46 @@ ++from gi.repository import Gtk ++ ++from sugar3.graphics import animator ++from sugar3.graphics.icon import Icon ++from sugar3.graphics import style ++ ++from common import set_theme ++set_theme() ++ ++ ++class _Animation(animator.Animation): ++ ++ def __init__(self, icon, start_size, end_size): ++ animator.Animation.__init__(self, 0.0, 1.0) ++ ++ self._icon = icon ++ self.start_size = start_size ++ self.end_size = end_size ++ ++ def next_frame(self, current): ++ d = (self.end_size - self.start_size) * current ++ self._icon.props.pixel_size = int(self.start_size + d) ++ ++ ++def __animation_completed_cb(anim): ++ print('Animation completed') ++ ++ ++w = Gtk.Window() ++w.connect('delete-event', Gtk.main_quit) ++ ++box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) ++w.add(box) ++ ++anim = animator.Animator(5) ++anim.connect('completed', __animation_completed_cb) ++ ++my_icon = Icon(icon_name='go-next') ++box.pack_start(my_icon, False, False, 0) ++ ++anim.add(_Animation(my_icon, style.STANDARD_ICON_SIZE, style.XLARGE_ICON_SIZE)) ++anim.start() ++ ++w.show_all() ++ ++Gtk.main() +diff --git b/examples/buttons.py a/examples/buttons.py +new file mode 100644 +index 0000000..5c679c2 +--- /dev/null ++++ a/examples/buttons.py +@@ -0,0 +1,64 @@ ++from gi.repository import Gtk ++ ++import common ++ ++ ++test = common.Test() ++test.show() ++ ++box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) ++test.pack_start(box, True, True, 0) ++box.show() ++ ++# test Gtk.SpinButton: ++ ++adj = Gtk.Adjustment(0, 0, 10, 1, 32, 0) ++spin = Gtk.SpinButton() ++spin.set_adjustment(adj) ++box.pack_start(spin, False, False, 1) ++spin.show() ++ ++# test Gtk.RadioButton: ++ ++radio_1 = Gtk.RadioButton.new_with_label_from_widget(None, 'Radio 1') ++box.pack_start(radio_1, False, False, 1) ++radio_1.show() ++radio_2 = Gtk.RadioButton.new_with_label_from_widget(radio_1, 'Radio 2') ++box.pack_start(radio_2, False, False, 1) ++radio_2.show() ++radio_3 = Gtk.RadioButton.new_with_label_from_widget(radio_1, 'Radio 3') ++box.pack_start(radio_3, False, False, 1) ++radio_3.show() ++ ++# test Gtk.CheckButton: ++ ++check_1 = Gtk.CheckButton('Check 1') ++box.pack_start(check_1, False, False, 1) ++check_1.show() ++ ++check_2 = Gtk.CheckButton('Check 2') ++box.pack_start(check_2, False, False, 1) ++check_2.show() ++ ++# test Gtk.Button: ++ ++button = Gtk.Button('Button') ++box.pack_start(button, False, False, 1) ++button.show() ++ ++# test Gtk.Button insensitive: ++ ++insensitive_button = Gtk.Button('Insensitive Button') ++box.pack_start(insensitive_button, False, False, 1) ++insensitive_button.props.sensitive = False ++insensitive_button.show() ++ ++# test Gtk.ToggleButton: ++ ++toggle_button = Gtk.ToggleButton('ToggleButton') ++box.pack_start(toggle_button, False, False, 1) ++toggle_button.show() ++ ++ ++if __name__ == '__main__': ++ common.main(test) +diff --git b/examples/cellrenderericon.py a/examples/cellrenderericon.py +new file mode 100644 +index 0000000..e280204 +--- /dev/null ++++ a/examples/cellrenderericon.py +@@ -0,0 +1,37 @@ ++from gi.repository import Gtk ++ ++from sugar3.graphics import style ++from sugar3.graphics.icon import CellRendererIcon ++ ++import common ++ ++ ++test = common.Test() ++test.show() ++ ++model = Gtk.ListStore(str) ++for icon in ['one', 'two', 'three']: ++ model.append([icon]) ++ ++treeview = Gtk.TreeView() ++treeview.set_model(model) ++test.pack_start(treeview, True, True, 0) ++treeview.show() ++ ++col = Gtk.TreeViewColumn() ++treeview.append_column(col) ++ ++cell_icon = CellRendererIcon() ++cell_icon.props.width = style.GRID_CELL_SIZE ++cell_icon.props.height = style.GRID_CELL_SIZE ++cell_icon.props.size = style.SMALL_ICON_SIZE ++cell_icon.props.icon_name = 'emblem-favorite' ++col.pack_start(cell_icon, expand=False) ++ ++cell_text = Gtk.CellRendererText() ++col.pack_start(cell_text, expand=True) ++col.add_attribute(cell_text, 'text', 0) ++ ++ ++if __name__ == '__main__': ++ common.main(test) +diff --git b/examples/colorbutton.py a/examples/colorbutton.py +new file mode 100644 +index 0000000..09db068 +--- /dev/null ++++ a/examples/colorbutton.py +@@ -0,0 +1,37 @@ ++from gi.repository import Gtk ++ ++from sugar3.graphics.toolbarbox import ToolbarBox ++from sugar3.graphics.colorbutton import ColorToolButton ++ ++ ++import common ++ ++ ++test = common.Test() ++test.show() ++ ++box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) ++test.pack_start(box, True, True, 0) ++box.show() ++ ++toolbar_box = ToolbarBox() ++box.pack_start(toolbar_box, False, False, 0) ++toolbar_box.show() ++ ++separator = Gtk.SeparatorToolItem() ++toolbar_box.toolbar.insert(separator, -1) ++separator.show() ++ ++ ++def color_changed_cb(button, pspec): ++ print(button.get_color()) ++ ++ ++color_button = ColorToolButton() ++color_button.connect("notify::color", color_changed_cb) ++toolbar_box.toolbar.insert(color_button, -1) ++color_button.show() ++ ++ ++if __name__ == '__main__': ++ common.main(test) +diff --git b/examples/combobox.py a/examples/combobox.py +new file mode 100644 +index 0000000..6d1c1a0 +--- /dev/null ++++ a/examples/combobox.py +@@ -0,0 +1,25 @@ ++from gi.repository import Gtk ++ ++from sugar3.graphics.combobox import ComboBox ++from common import set_theme ++set_theme() ++ ++ ++def __combo_changed_cb(combo): ++ print('Combo changed to %r' % combo.get_value()) ++ ++ ++w = Gtk.Window() ++w.connect("delete-event", Gtk.main_quit) ++ ++combo = ComboBox() ++combo.append_item(True, 'one') ++combo.append_item(2, 'two', 'go-next') ++combo.append_item('3', 'three') ++# This will make 'two' active (zero indexed) ++combo.set_active(1) ++combo.connect('changed', __combo_changed_cb) ++w.add(combo) ++ ++w.show_all() ++Gtk.main() +diff --git b/examples/common.py a/examples/common.py +new file mode 100644 +index 0000000..906eb50 +--- /dev/null ++++ a/examples/common.py +@@ -0,0 +1,77 @@ ++# Copyright (C) 2007, Red Hat, Inc. ++# ++# This library is free software; you can redistribute it and/or ++# modify it under the terms of the GNU Lesser General Public ++# License as published by the Free Software Foundation; either ++# version 2 of the License, or (at your option) any later version. ++# ++# This library is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++# Lesser General Public License for more details. ++# ++# You should have received a copy of the GNU Lesser General Public ++# License along with this library; if not, write to the ++# Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++# Boston, MA 02111-1307, USA. ++ ++from gi.repository import Gtk ++from gi.repository import GObject ++ ++from sugar3.graphics.toolbutton import ToolButton ++ ++import os ++ ++ ++def set_theme(): ++ settings = Gtk.Settings.get_default() ++ sugar_theme = 'sugar-72' ++ if 'SUGAR_SCALING' in os.environ: ++ if os.environ['SUGAR_SCALING'] == '100': ++ sugar_theme = 'sugar-100' ++ settings.set_property('gtk-theme-name', sugar_theme) ++ settings.set_property('gtk-icon-theme-name', 'sugar') ++ ++ ++class Test(Gtk.Box): ++ ++ def __init__(self): ++ GObject.GObject.__init__(self, orientation=Gtk.Orientation.VERTICAL) ++ ++ set_theme() ++ ++ ++class TestPalette(Test): ++ ++ def __init__(self): ++ Test.__init__(self) ++ ++ toolbar = Gtk.Toolbar() ++ ++ self._invoker = ToolButton('go-previous') ++ toolbar.insert(self._invoker, -1) ++ self._invoker.show() ++ ++ self.pack_start(toolbar, False, False, 0) ++ toolbar.show() ++ ++ def set_palette(self, palette): ++ self._invoker.set_palette(palette) ++ ++ ++class TestRunner(object): ++ ++ def run(self, test): ++ window = Gtk.Window() ++ window.connect('delete-event', Gtk.main_quit) ++ window.add(test) ++ test.show() ++ ++ window.show() ++ ++ ++def main(test): ++ runner = TestRunner() ++ runner.run(test) ++ ++ Gtk.main() +diff --git b/examples/customdestroy.py a/examples/customdestroy.py +new file mode 100644 +index 0000000..fc33eb9 +--- /dev/null ++++ a/examples/customdestroy.py +@@ -0,0 +1,47 @@ ++from gi.repository import Gtk ++ ++""" ++Since GTK+3 Gtk.CellRenderer doesn't have a destroy signal anymore. ++We can do the cleanup in the python destructor method instead. ++ ++""" ++ ++ ++class MyCellRenderer(Gtk.CellRenderer): ++ ++ def __init__(self): ++ Gtk.CellRenderer.__init__(self) ++ ++ def __del__(self): ++ print("cellrenderer destroy") ++ ++ def do_render(self, cairo_t, widget, background_area, cell_area, flags): ++ pass ++ ++ ++def window_destroy_cb(*kwargs): ++ print("window destroy") ++ Gtk.main_quit() ++ ++ ++window = Gtk.Window(Gtk.WindowType.TOPLEVEL) ++window.connect("destroy", window_destroy_cb) ++window.show() ++ ++ ++def treeview_destroy_cb(*kwargs): ++ print("treeview destroy") ++ ++ ++treeview = Gtk.TreeView() ++treeview.connect("destroy", treeview_destroy_cb) ++window.add(treeview) ++treeview.show() ++ ++col = Gtk.TreeViewColumn() ++treeview.append_column(col) ++ ++cel = MyCellRenderer() ++col.pack_start(cel, expand=True) ++ ++Gtk.main() +diff --git b/examples/gtktreesensitive.py a/examples/gtktreesensitive.py +new file mode 100644 +index 0000000..58fea99 +--- /dev/null ++++ a/examples/gtktreesensitive.py +@@ -0,0 +1,48 @@ ++#!/usr/bin/python3 ++from gi.repository import Gtk ++ ++import common ++test = common.Test() ++test.show() ++ ++ ++class MyBox(Gtk.Box): ++ ++ def __init__(self): ++ Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL) ++ ++ scrolled = Gtk.ScrolledWindow() ++ scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, ++ Gtk.PolicyType.AUTOMATIC) ++ ++ store = Gtk.ListStore(str, str) ++ for i in range(5): ++ store.append([str(i), 'Item %s' % i]) ++ ++ treeview = Gtk.TreeView(store) ++ renderer_no_sens = Gtk.CellRendererText() ++ # set 'sensitive' property ++ renderer_no_sens.set_property('sensitive', False) ++ ++ renderer = Gtk.CellRendererText() ++ ++ column = Gtk.TreeViewColumn('\'sensitive\' False', ++ renderer_no_sens, text=0) ++ treeview.append_column(column) ++ ++ column = Gtk.TreeViewColumn('\'sensitive\' True', ++ renderer, text=1) ++ treeview.append_column(column) ++ ++ scrolled.add(treeview) ++ self.pack_start(scrolled, True, True, 0) ++ ++ self.show_all() ++ ++ ++box = MyBox() ++test.pack_start(box, True, True, 0) ++box.show() ++ ++if __name__ == '__main__': ++ common.main(test) +diff --git b/examples/iconbadges.py a/examples/iconbadges.py +new file mode 100644 +index 0000000..545f0d0 +--- /dev/null ++++ a/examples/iconbadges.py +@@ -0,0 +1,42 @@ ++from gi.repository import Gtk ++ ++from sugar3.graphics.icon import EventIcon ++from sugar3.graphics.icon import Icon ++from sugar3.graphics import style ++from sugar3.graphics.xocolor import XoColor ++from sugar3.graphics.palette import Palette ++ ++import common ++ ++ ++test = common.Test() ++test.show() ++ ++box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) ++test.pack_start(box, True, True, 0) ++box.show() ++ ++# An XO Icon, normal size, setting the color via the XoColor object ++icon = Icon(icon_name='computer-xo', ++ pixel_size=style.STANDARD_ICON_SIZE, ++ xo_color=XoColor('#00BEFF,#FF7800')) ++box.pack_start(icon, False, False, 0) ++icon.show() ++ ++# You can mix constructor keyword argument and setting ++# properties after creation ++icon = EventIcon(icon_name='network-wireless-080', ++ pixel_size=style.STANDARD_ICON_SIZE) ++# Badges are little icons displayed ++icon.props.badge_name = 'emblem-favorite' ++# Instead of using the XoColor, you can use any SVG color specifier: ++icon.props.fill_color = 'rgb(230, 0, 10)' ++icon.props.stroke_color = '#78E600' ++# Unlike normal icons, EventIcons support palettes: ++icon.props.palette = Palette('Hello World') ++box.pack_start(icon, False, False, 0) ++icon.show() ++ ++ ++if __name__ == '__main__': ++ common.main(test) +diff --git b/examples/iconcache.py a/examples/iconcache.py +new file mode 100644 +index 0000000..a766a37 +--- /dev/null ++++ a/examples/iconcache.py +@@ -0,0 +1,72 @@ ++# Copyright (C) 2007, Red Hat, Inc. ++# ++# This library is free software; you can redistribute it and/or ++# modify it under the terms of the GNU Lesser General Public ++# License as published by the Free Software Foundation; either ++# version 2 of the License, or (at your option) any later version. ++# ++# This library is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++# Lesser General Public License for more details. ++# ++# You should have received a copy of the GNU Lesser General Public ++# License along with this library; if not, write to the ++# Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++# Boston, MA 02111-1307, USA. ++ ++""" ++Test the sugar3.graphics.icon.* cache. ++""" ++ ++from gi.repository import Gtk ++ ++from sugar3.graphics.icon import Icon ++from sugar3.graphics.xocolor import XoColor ++from sugar3.graphics import style ++ ++import common ++ ++test = common.Test() ++ ++data = [ ++ ['battery-000', '#FF8F00,#FF2B34'], ++ ['battery-010', '#D1A3FF,#00A0FF'], ++ ['battery-020', '#FF8F00,#FF2B34'], ++ ['battery-030', '#00A0FF,#D1A3FF'], ++ ['battery-040', '#AC32FF,#FF2B34'], ++ ['battery-050', '#D1A3FF,#00A0FF'], ++ ['battery-060', '#AC32FF,#FF2B34'], ++ ['battery-070', '#00A0FF,#D1A3FF'], ++ ['battery-080', '#FF8F00,#FF2B34'], ++ ['battery-090', '#D1A3FF,#00A0FF'], ++ ['battery-100', '#AC32FF,#FF2B34']] ++ ++ ++def _button_activated_cb(button): ++ import random ++ ++ global data ++ random.shuffle(data) ++ ++ for i in range(0, len(test.get_children()) - 1): ++ test.get_children()[i].props.icon_name = data[i][0] ++ test.get_children()[i].props.xo_color = XoColor(data[i][1]) ++ ++ ++for d in data: ++ icon = Icon(icon_name=d[0], ++ pixel_size=style.STANDARD_ICON_SIZE, ++ xo_color=XoColor(d[1])) ++ test.pack_start(icon, True, True, 0) ++ icon.show() ++ ++button = Gtk.Button('mec mac') ++test.pack_start(button, True, True, 0) ++button.connect('activate', _button_activated_cb) ++button.show() ++ ++test.show() ++ ++if __name__ == '__main__': ++ common.main(test) +diff --git b/examples/iconentry.py a/examples/iconentry.py +new file mode 100644 +index 0000000..e35c601 +--- /dev/null ++++ a/examples/iconentry.py +@@ -0,0 +1,32 @@ ++from gi.repository import Gtk ++ ++from sugar3.graphics import iconentry ++from common import set_theme ++set_theme() ++ ++ ++def __go_next_cb(entry, icon_pos, data=None): ++ print('Go next') ++ ++ ++def __entry_activate_cb(widget, data=None): ++ print('Entry activate') ++ ++ ++w = Gtk.Window() ++w.connect("delete-event", Gtk.main_quit) ++ ++box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) ++w.add(box) ++ ++entry = iconentry.IconEntry() ++entry.set_icon_from_name(iconentry.ICON_ENTRY_SECONDARY, ++ 'go-next') ++entry.connect('icon-press', __go_next_cb) ++entry.connect('activate', __entry_activate_cb) ++entry.set_progress_fraction(0.3) ++box.pack_start(entry, False, False, 0) ++ ++w.show_all() ++ ++Gtk.main() +diff --git b/examples/iconwidget.py a/examples/iconwidget.py +new file mode 100644 +index 0000000..2854b4c +--- /dev/null ++++ a/examples/iconwidget.py +@@ -0,0 +1,88 @@ ++# Copyright (C) 2007, Red Hat, Inc. ++# ++# This library is free software; you can redistribute it and/or ++# modify it under the terms of the GNU Lesser General Public ++# License as published by the Free Software Foundation; either ++# version 2 of the License, or (at your option) any later version. ++# ++# This library is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++# Lesser General Public License for more details. ++# ++# You should have received a copy of the GNU Lesser General Public ++# License along with this library; if not, write to the ++# Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++# Boston, MA 02111-1307, USA. ++ ++""" ++Test the sugar3.graphics.icon.Icon widget. ++""" ++ ++from gi.repository import Gtk ++ ++from sugar3.graphics.icon import Icon ++from sugar3.graphics.xocolor import XoColor ++from sugar3.graphics import style ++ ++import common ++ ++test = common.Test() ++ ++box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) ++test.pack_start(box, True, True, 0) ++sensitive_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) ++insensitive_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) ++ ++box.pack_start(sensitive_box, True, True, 0) ++box.pack_start(insensitive_box, True, True, 0) ++box.show_all() ++ ++ ++def create_icon_widgets(box, sensitive=True): ++ icon = Icon(icon_name='go-previous') ++ icon.props.pixel_size = style.STANDARD_ICON_SIZE ++ box.pack_start(icon, True, True, 0) ++ icon.set_sensitive(sensitive) ++ icon.show() ++ ++ icon = Icon(icon_name='computer-xo', ++ pixel_size=style.STANDARD_ICON_SIZE, ++ xo_color=XoColor()) ++ box.pack_start(icon, True, True, 0) ++ icon.set_sensitive(sensitive) ++ icon.show() ++ ++ icon = Icon(icon_name='battery-000', ++ pixel_size=style.STANDARD_ICON_SIZE, ++ badge_name='emblem-busy') ++ box.pack_start(icon, True, True, 0) ++ icon.set_sensitive(sensitive) ++ icon.show() ++ ++ icon = Icon(icon_name='gtk-new', ++ pixel_size=style.STANDARD_ICON_SIZE, ++ badge_name='gtk-cancel') ++ box.pack_start(icon, True, True, 0) ++ icon.set_sensitive(sensitive) ++ icon.show() ++ ++ ++create_icon_widgets(sensitive_box, True) ++create_icon_widgets(insensitive_box, False) ++ ++test.show() ++ ++# This can be used to test for leaks by setting the LRU cache size ++# in icon.py to 1. ++# def idle_cb(): ++# import gc ++# gc.collect() ++# test.queue_draw() ++# return True ++# ++# from gi.repository import GLib ++# GLib.idle_add(idle_cb) ++ ++if __name__ == '__main__': ++ common.main(test) +diff --git b/examples/notebook.py a/examples/notebook.py +new file mode 100644 +index 0000000..7462e0d +--- /dev/null ++++ a/examples/notebook.py +@@ -0,0 +1,32 @@ ++from gi.repository import Gtk ++ ++from sugar3.graphics.notebook import Notebook ++from common import set_theme ++set_theme() ++ ++ ++w = Gtk.Window() ++w.connect("delete-event", Gtk.main_quit) ++ ++box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) ++w.add(box) ++ ++nb = Notebook(can_close_tabs=True) ++box.pack_start(nb, False, False, 0) ++ ++for i in range(5): ++ bufferf = "Prepend Frame %d" % (i + 1) ++ bufferl = "PPage %d" % (i + 1) ++ ++ frame = Gtk.Frame() ++ frame.set_border_width(10) ++ frame.set_size_request(100, 75) ++ label = Gtk.Label(bufferf) ++ frame.add(label) ++ label.show() ++ nb.add_page(bufferl, frame) ++ frame.show() ++ ++w.show_all() ++ ++Gtk.main() +diff --git b/examples/progress.py a/examples/progress.py +new file mode 100644 +index 0000000..62a9313 +--- /dev/null ++++ a/examples/progress.py +@@ -0,0 +1,20 @@ ++from gi.repository import Gtk ++ ++import common ++ ++ ++test = common.Test() ++test.show() ++ ++box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) ++test.pack_start(box, True, False, 10) ++box.show() ++ ++bar = Gtk.ProgressBar() ++bar.set_fraction(0.5) ++box.pack_start(bar, True, True, 10) ++bar.show() ++ ++ ++if __name__ == '__main__': ++ common.main(test) +diff --git b/examples/progressicon.py a/examples/progressicon.py +new file mode 100644 +index 0000000..4bf3d99 +--- /dev/null ++++ a/examples/progressicon.py +@@ -0,0 +1,58 @@ ++from gi.repository import Gtk ++from gi.repository import GLib ++ ++from sugar3.graphics.toolbarbox import ToolbarBox ++from sugar3.graphics.progressicon import ProgressIcon ++from sugar3.graphics import style ++ ++import common ++ ++ ++test = common.Test() ++ ++box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) ++test.pack_start(box, True, True, 0) ++ ++toolbar_box = ToolbarBox() ++box.pack_start(toolbar_box, False, False, 0) ++ ++separator = Gtk.SeparatorToolItem() ++toolbar_box.toolbar.insert(separator, -1) ++ ++icon = ProgressIcon( ++ pixel_size=style.LARGE_ICON_SIZE, ++ icon_name='computer-xo', ++ stroke_color=style.COLOR_BUTTON_GREY.get_svg(), ++ fill_color=style.COLOR_WHITE.get_svg()) ++test.pack_start(icon, True, True, 0) ++icon.show() ++ ++icon2 = ProgressIcon( ++ pixel_size=style.LARGE_ICON_SIZE, ++ icon_name='computer-xo', ++ stroke_color=style.COLOR_BUTTON_GREY.get_svg(), ++ fill_color=style.COLOR_WHITE.get_svg(), ++ direction='horizontal') ++test.pack_start(icon2, True, True, 0) ++icon2.show() ++ ++test.show_all() ++ ++progress = 0 ++ ++ ++def timeout_cb(): ++ global progress ++ progress += 0.05 ++ icon.update(progress) ++ icon2.update(progress) ++ if progress >= 1: ++ return False ++ return True ++ ++ ++GLib.timeout_add(50, timeout_cb) ++ ++ ++if __name__ == '__main__': ++ common.main(test) +diff --git b/examples/radiopalette.py a/examples/radiopalette.py +new file mode 100644 +index 0000000..8537144 +--- /dev/null ++++ a/examples/radiopalette.py +@@ -0,0 +1,78 @@ ++from gi.repository import Gtk ++ ++from sugar3.graphics.radiopalette import RadioPalette, RadioMenuButton, \ ++ RadioToolsButton ++from sugar3.graphics.radiotoolbutton import RadioToolButton ++from common import set_theme ++set_theme() ++ ++ ++window = Gtk.Window() ++ ++box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) ++window.add(box) ++ ++toolbar = Gtk.Toolbar() ++box.pack_start(toolbar, False, False, 0) ++ ++text_view = Gtk.TextView() ++box.pack_start(text_view, True, True, 0) ++ ++ ++def echo(button, label): ++ if not button.props.active: ++ return ++ text_view.props.buffer.props.text += '\n' + label ++ ++ ++# RadioMenuButton ++ ++palette = RadioPalette() ++ ++group = RadioToolButton( ++ icon_name='document-open') ++group.connect('clicked', lambda button: echo(button, 'document-open')) ++palette.append(group, 'menu.document-open') ++ ++button = RadioToolButton( ++ icon_name='document-save', ++ group=group) ++button.connect('clicked', lambda button: echo(button, 'document-save')) ++palette.append(button, 'menu.document-save') ++ ++button = RadioToolButton( ++ icon_name='document-send', ++ group=group) ++button.connect('clicked', lambda button: echo(button, 'document-send')) ++palette.append(button, 'menu.document-send') ++ ++button = RadioMenuButton(palette=palette) ++toolbar.insert(button, -1) ++ ++# RadioToolsButton ++ ++palette = RadioPalette() ++ ++group = RadioToolButton( ++ icon_name='document-open') ++group.connect('clicked', lambda button: echo(button, 'document-open')) ++palette.append(group, 'menu.document-open') ++ ++button = RadioToolButton( ++ icon_name='document-save', ++ group=group) ++button.connect('clicked', lambda button: echo(button, 'document-save')) ++palette.append(button, 'menu.document-save') ++ ++button = RadioToolButton( ++ icon_name='document-send', ++ group=group) ++button.connect('clicked', lambda button: echo(button, 'document-send')) ++palette.append(button, 'menu.document-send') ++ ++button = RadioToolsButton(palette=palette) ++toolbar.insert(button, -1) ++ ++window.connect('delete-event', Gtk.main_quit) ++window.show_all() ++Gtk.main() +diff --git b/examples/radiotoolbutton.py a/examples/radiotoolbutton.py +new file mode 100644 +index 0000000..5d0b547 +--- /dev/null ++++ a/examples/radiotoolbutton.py +@@ -0,0 +1,48 @@ ++from gi.repository import Gtk ++from sugar3.graphics.radiotoolbutton import RadioToolButton ++from sugar3.graphics.radiopalette import RadioPalette, RadioMenuButton ++from sugar3.graphics.xocolor import XoColor ++ ++ ++from common import set_theme ++set_theme() ++ ++window = Gtk.Window() ++window.show() ++window.connect("delete-event", Gtk.main_quit) ++ ++box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) ++window.add(box) ++box.show() ++ ++ ++def echo(button, label): ++ if not button.props.active: ++ return ++ print(label) ++ ++ ++palette = RadioPalette() ++# Adding 3 RadioToolButtons to a palette ++ ++button1 = RadioToolButton(icon_name='document-save', accelerator="<ctrl>S", ++ xo_color=XoColor("white")) ++button1.connect('toggled', lambda button: echo(button, 'document-save')) ++palette.append(button1, 'menu.document-save') ++ ++button2 = RadioToolButton(icon_name='document-open', accelerator="<ctrl>O", ++ xo_color=XoColor("white"), group=button1) ++button2.connect('toggled', lambda button: echo(button, 'document-open')) ++palette.append(button2, 'menu.document-open') ++ ++button3 = RadioToolButton(icon_name='document-send', accelerator="<ctrl>F", ++ xo_color=XoColor("white"), group=button1) ++button3.connect('toggled', lambda button: echo(button, 'document-send')) ++palette.append(button3, 'menu.document-send') ++ ++button = RadioMenuButton(palette=palette) ++box.pack_start(button, False, False, 1) ++button.show() ++ ++if __name__ == '__main__': ++ Gtk.main() +diff --git b/examples/scrollingdetector.py a/examples/scrollingdetector.py +new file mode 100644 +index 0000000..df0c70a +--- /dev/null ++++ a/examples/scrollingdetector.py +@@ -0,0 +1,73 @@ ++import os ++import time ++ ++from gi.repository import Gtk ++ ++from sugar3.graphics import style ++from sugar3.graphics.icon import CellRendererIcon ++from sugar3.graphics.xocolor import XoColor ++from sugar3.graphics.scrollingdetector import ScrollingDetector ++from sugar3.graphics.palettewindow import TreeViewInvoker ++import common ++ ++ ++def _scroll_start_cb(event, treeview, invoker): ++ print("Scroll starts") ++ invoker.detach() ++ ++ ++def _scroll_end_cb(event, treeview, invoker): ++ print("Scroll ends") ++ invoker.attach_treeview(treeview) ++ ++ ++test = common.Test() ++test.show() ++ ++model = Gtk.ListStore(str) ++ ++data_dir = os.getenv('GTK_DATA_PREFIX', '/usr/') ++ ++iconlist = os.listdir(os.path.join(data_dir, ++ 'share/icons/sugar/scalable/actions/')) ++print("Displaying %s icons" % len(iconlist)) ++for icon in iconlist: ++ icon = os.path.basename(icon) ++ icon = icon[:icon.find('.')] ++ model.append([icon]) ++ ++scrolled = Gtk.ScrolledWindow() ++scrolled.set_size_request(800, 800) ++treeview = Gtk.TreeView() ++ ++treeview.set_model(model) ++scrolled.add(treeview) ++test.pack_start(scrolled, True, True, 0) ++test.show_all() ++ ++col = Gtk.TreeViewColumn() ++treeview.append_column(col) ++ ++xo_color = XoColor('#FF0000,#00FF00') ++cell_icon = CellRendererIcon() ++cell_icon.props.width = style.GRID_CELL_SIZE ++cell_icon.props.height = style.GRID_CELL_SIZE ++cell_icon.props.size = style.STANDARD_ICON_SIZE ++cell_icon.props.xo_color = xo_color ++ ++col.pack_start(cell_icon, expand=False) ++col.add_attribute(cell_icon, 'icon-name', 0) ++cell_text = Gtk.CellRendererText() ++col.pack_start(cell_text, expand=True) ++col.add_attribute(cell_text, 'text', 0) ++ ++invoker = TreeViewInvoker() ++invoker.attach_treeview(treeview) ++ ++detector = ScrollingDetector(scrolled) ++detector.connect('scroll-start', _scroll_start_cb, treeview, invoker) ++detector.connect('scroll-end', _scroll_end_cb, treeview, invoker) ++ ++if __name__ == '__main__': ++ time_ini = time.time() ++ common.main(test) +diff --git b/examples/tabs.py a/examples/tabs.py +new file mode 100644 +index 0000000..7a8b52f +--- /dev/null ++++ a/examples/tabs.py +@@ -0,0 +1,46 @@ ++#!/usr/bin/python3 ++from gi.repository import Gtk ++ ++from sugar3.graphics.icon import Icon ++ ++import common ++test = common.Test() ++test.show() ++ ++box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) ++test.pack_start(box, True, True, 0) ++box.show() ++ ++# notebook without button ++ ++notebook = Gtk.Notebook() ++box.pack_start(notebook, True, True, 0) ++notebook.show() ++ ++for i in range(3): ++ hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) ++ notebook.append_page(hbox, Gtk.Label('Page %d' % (i + 1))) ++ hbox.show() ++ ++# notebook with buttons ++ ++notebook = Gtk.Notebook() ++box.pack_start(notebook, True, True, 0) ++notebook.show() ++ ++add_icon = Icon(icon_name='add') ++button = Gtk.Button() ++button.props.focus_on_click = False ++button.add(add_icon) ++add_icon.show() ++ ++notebook.set_action_widget(button, Gtk.PackType.END) ++button.show() ++ ++for i in range(3): ++ hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) ++ notebook.append_page(hbox, Gtk.Label('Page %d' % (i + 1))) ++ hbox.show() ++ ++if __name__ == '__main__': ++ common.main(test) +diff --git b/examples/ticket2855.py a/examples/ticket2855.py +new file mode 100644 +index 0000000..59a2917 +--- /dev/null ++++ a/examples/ticket2855.py +@@ -0,0 +1,60 @@ ++# Copyright (C) 2007, Red Hat, Inc. ++# ++# This library is free software; you can redistribute it and/or ++# modify it under the terms of the GNU Lesser General Public ++# License as published by the Free Software Foundation; either ++# version 2 of the License, or (at your option) any later version. ++# ++# This library is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++# Lesser General Public License for more details. ++# ++# You should have received a copy of the GNU Lesser General Public ++# License along with this library; if not, write to the ++# Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++# Boston, MA 02111-1307, USA. ++ ++""" ++Test the style of toggle and radio buttons inside a palette. The buttons ++contains only an icon and should be rendered similarly to the toolbar ++controls. Ticket #2855. ++""" ++ ++from gi.repository import Gtk ++ ++from sugar3.graphics.palette import Palette ++from sugar3.graphics.icon import Icon ++from sugar3.graphics import style ++ ++import common ++ ++test = common.TestPalette() ++ ++palette = Palette('Test radio and toggle') ++test.set_palette(palette) ++ ++box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) ++ ++toggle = Gtk.ToggleButton() ++ ++icon = Icon(icon_name='go-previous', pixel_size=style.STANDARD_ICON_SIZE) ++toggle.set_image(icon) ++ ++box.pack_start(toggle, False, False, 0) ++toggle.show() ++ ++radio = Gtk.RadioButton() ++ ++icon = Icon(icon_name='go-next', pixel_size=style.STANDARD_ICON_SIZE) ++radio.set_image(icon) ++ ++radio.set_mode(False) ++box.pack_start(radio, False, False, 0) ++radio.show() ++ ++palette.set_content(box) ++box.show() ++ ++if __name__ == '__main__': ++ common.main(test) +diff --git b/bin/sugar-activity-web a/examples/ticket2999.py +similarity index 66% +copy from bin/sugar-activity-web +copy to examples/ticket2999.py +index 8fd7a59..0d42297 100644 +--- b/bin/sugar-activity-web ++++ a/examples/ticket2999.py +@@ -1,6 +1,4 @@ +-#!/bin/sh +- +-# Copyright (C) 2013 Daniel Narvaez ++# Copyright (C) 2007, One Laptop Per Child + # + # This library is free software; you can redistribute it and/or + # modify it under the terms of the GNU Lesser General Public +@@ -17,8 +15,21 @@ + # Free Software Foundation, Inc., 59 Temple Place - Suite 330, + # Boston, MA 02111-1307, USA. + +-if [ "$SUGAR_USE_WEBKIT1" = "yes" ]; then +- exec sugar-activity3 sugar3.activity.webkit1.WebActivity $@ +-else +- exec sugar-activity3 sugar3.activity.webactivity.WebActivity $@ +-fi ++""" ++Spec in ticket #2999. ++""" ++ ++from gi.repository import Gtk ++ ++import common ++ ++test = common.Test() ++test.set_border_width(60) ++ ++text_view = Gtk.TextView() ++text_view.props.buffer.props.text = 'Blah blah blah, blah blah blah.' ++test.pack_start(text_view, True, True, 0) ++text_view.show() ++ ++if __name__ == '__main__': ++ common.main(test) +diff --git b/bin/sugar-activity-web a/examples/ticket3000.py +similarity index 56% +copy from bin/sugar-activity-web +copy to examples/ticket3000.py +index 8fd7a59..488985e 100644 +--- b/bin/sugar-activity-web ++++ a/examples/ticket3000.py +@@ -1,6 +1,4 @@ +-#!/bin/sh +- +-# Copyright (C) 2013 Daniel Narvaez ++# Copyright (C) 2007, One Laptop Per Child + # + # This library is free software; you can redistribute it and/or + # modify it under the terms of the GNU Lesser General Public +@@ -17,8 +15,34 @@ + # Free Software Foundation, Inc., 59 Temple Place - Suite 330, + # Boston, MA 02111-1307, USA. + +-if [ "$SUGAR_USE_WEBKIT1" = "yes" ]; then +- exec sugar-activity3 sugar3.activity.webkit1.WebActivity $@ +-else +- exec sugar-activity3 sugar3.activity.webactivity.WebActivity $@ +-fi ++""" ++Spec in ticket #3000. ++""" ++ ++from gi.repository import Gtk ++ ++from sugar3.graphics.toolbutton import ToolButton ++ ++import common ++ ++test = common.Test() ++ ++toolbar = Gtk.Toolbar() ++test.pack_start(toolbar, False, False, 0) ++toolbar.show() ++ ++button = ToolButton('go-previous') ++toolbar.insert(button, -1) ++button.show() ++ ++separator = Gtk.SeparatorToolItem() ++toolbar.add(separator) ++separator.show() ++ ++button = ToolButton('go-next') ++toolbar.insert(button, -1) ++button.show() ++ ++ ++if __name__ == '__main__': ++ common.main(test) +diff --git b/examples/toggletoolbutton.py a/examples/toggletoolbutton.py +new file mode 100644 +index 0000000..bc37c17 +--- /dev/null ++++ a/examples/toggletoolbutton.py +@@ -0,0 +1,33 @@ ++from gi.repository import Gtk ++ ++from sugar3.graphics.toolbarbox import ToolbarBox ++from sugar3.graphics.toggletoolbutton import ToggleToolButton ++ ++import common ++ ++ ++test = common.Test() ++test.show() ++ ++box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) ++test.pack_start(box, True, True, 0) ++box.show() ++ ++toolbar_box = ToolbarBox() ++box.pack_start(toolbar_box, False, False, 0) ++toolbar_box.show() ++ ++favorite_button = ToggleToolButton('emblem-favorite') ++favorite_button.set_tooltip('Favorite') ++toolbar_box.toolbar.insert(favorite_button, -1) ++favorite_button.show() ++ ++favorite_button2 = ToggleToolButton('emblem-favorite') ++favorite_button2.set_tooltip('Favorite') ++toolbar_box.toolbar.insert(favorite_button2, -1) ++favorite_button2.set_active(True) ++favorite_button2.show() ++ ++ ++if __name__ == '__main__': ++ common.main(test) +diff --git b/examples/toolbar.py a/examples/toolbar.py +new file mode 100644 +index 0000000..dc3cb41 +--- /dev/null ++++ a/examples/toolbar.py +@@ -0,0 +1,56 @@ ++from gi.repository import Gtk ++ ++from sugar3.graphics.toolbutton import ToolButton ++from sugar3.graphics.toolbarbox import ToolbarBox, ToolbarButton ++from common import set_theme ++set_theme() ++ ++ ++window = Gtk.Window() ++ ++box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) ++window.add(box) ++ ++toolbar = ToolbarBox() ++box.pack_start(toolbar, False, False, 0) ++ ++tollbarbutton_1 = ToolbarButton( ++ page=Gtk.Button('sub-widget #1'), ++ icon_name='computer-xo') ++toolbar.toolbar.insert(tollbarbutton_1, -1) ++ ++tollbarbutton_2 = ToolbarButton( ++ page=Gtk.Button('sub-widget #2'), ++ icon_name='button_cancel', ++ tooltip='with custom palette instead of sub-widget') ++toolbar.toolbar.insert(tollbarbutton_2, -1) ++ ++toolbar.toolbar.insert(Gtk.SeparatorToolItem(), -1) ++ ++ ++def del_cb(widget): ++ toolbar.toolbar.remove(tollbarbutton_3) ++ ++ ++del_b = Gtk.Button('delete sub-widget #3') ++del_b.connect('clicked', del_cb) ++tollbarbutton_3 = ToolbarButton( ++ page=del_b, ++ icon_name='activity-journal') ++toolbar.toolbar.insert(tollbarbutton_3, -1) ++ ++subbar = Gtk.Toolbar() ++subbutton = ToolButton( ++ icon_name='document-send', ++ tooltip='document-send') ++subbar.insert(subbutton, -1) ++subbar.show_all() ++ ++tollbarbutton_4 = ToolbarButton( ++ page=subbar, ++ icon_name='document-save') ++toolbar.toolbar.insert(tollbarbutton_4, -1) ++ ++window.connect('delete-event', Gtk.main_quit) ++window.show_all() ++Gtk.main() +diff --git b/examples/toolbarpalettes.py a/examples/toolbarpalettes.py +new file mode 100644 +index 0000000..5d9ee9a +--- /dev/null ++++ a/examples/toolbarpalettes.py +@@ -0,0 +1,65 @@ ++# Copyright (C) 2007, Red Hat, Inc. ++# ++# This library is free software; you can redistribute it and/or ++# modify it under the terms of the GNU Lesser General Public ++# License as published by the Free Software Foundation; either ++# version 2 of the License, or (at your option) any later version. ++# ++# This library is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++# Lesser General Public License for more details. ++# ++# You should have received a copy of the GNU Lesser General Public ++# License along with this library; if not, write to the ++# Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++# Boston, MA 02111-1307, USA. ++ ++""" ++Test palette positioning for toolbar and tray. ++""" ++ ++from gi.repository import Gtk ++ ++from sugar3.graphics.tray import HTray, TrayButton ++from sugar3.graphics.toolbutton import ToolButton ++ ++import common ++ ++test = common.Test() ++ ++box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) ++ ++theme_icons = Gtk.IconTheme.get_default().list_icons() ++ ++toolbar = Gtk.Toolbar() ++box.pack_start(toolbar, False, False, 0) ++toolbar.show() ++ ++for i in range(0, 5): ++ button = ToolButton(icon_name=theme_icons[i]) ++ button.set_tooltip('Icon %d' % i) ++ toolbar.insert(button, -1) ++ button.show() ++ ++content = Gtk.Label() ++box.pack_start(content, True, True, 0) ++content.show() ++ ++tray = HTray() ++box.pack_start(tray, False, False, 0) ++tray.show() ++ ++for i in range(0, 30): ++ button = TrayButton(icon_name=theme_icons[i]) ++ button.set_tooltip('Icon %d' % i) ++ tray.add_item(button) ++ button.show() ++ ++test.pack_start(box, True, True, 0) ++box.show() ++ ++test.show() ++ ++if __name__ == '__main__': ++ common.main(test) +diff --git b/examples/toolbutton.py a/examples/toolbutton.py +new file mode 100644 +index 0000000..c4a2649 +--- /dev/null ++++ a/examples/toolbutton.py +@@ -0,0 +1,36 @@ ++from gi.repository import Gtk ++ ++from sugar3.graphics.toolbarbox import ToolbarBox ++from sugar3.graphics.toolbutton import ToolButton ++ ++import common ++ ++ ++test = common.Test() ++ ++box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) ++test.pack_start(box, True, True, 0) ++ ++toolbar_box = ToolbarBox() ++box.pack_start(toolbar_box, False, False, 0) ++ ++separator = Gtk.SeparatorToolItem() ++toolbar_box.toolbar.insert(separator, -1) ++ ++ ++def __clicked_cb(button): ++ n = int(button.get_tooltip()) ++ button.set_tooltip(str(n + 1)) ++ print("tool button click count %d" % n) ++ ++ ++tool_button = ToolButton(icon_name='view-radial', tooltip='0') ++tool_button.connect('clicked', __clicked_cb) ++tool_button.set_hide_tooltip_on_click(False) ++tool_button.set_accelerator('<Space>') ++toolbar_box.toolbar.insert(tool_button, -1) ++ ++test.show_all() ++ ++if __name__ == '__main__': ++ common.main(test) +diff --git b/examples/toolbuttons.py a/examples/toolbuttons.py +new file mode 100644 +index 0000000..75e9e49 +--- /dev/null ++++ a/examples/toolbuttons.py +@@ -0,0 +1,46 @@ ++from gi.repository import Gtk ++ ++from sugar3.graphics.toolbarbox import ToolbarBox ++from sugar3.graphics.colorbutton import ColorToolButton ++from sugar3.graphics.radiotoolbutton import RadioToolButton ++from sugar3.graphics.toggletoolbutton import ToggleToolButton ++ ++import common ++ ++ ++test = common.Test() ++test.show() ++ ++box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) ++test.pack_start(box, True, True, 0) ++box.show() ++ ++toolbar_box = ToolbarBox() ++box.pack_start(toolbar_box, False, False, 0) ++toolbar_box.show() ++ ++radial_button = RadioToolButton(icon_name='view-radial') ++toolbar_box.toolbar.insert(radial_button, -1) ++radial_button.show() ++ ++list_button = RadioToolButton(icon_name='view-list') ++list_button.props.group = radial_button ++toolbar_box.toolbar.insert(list_button, -1) ++list_button.show() ++ ++separator = Gtk.SeparatorToolItem() ++toolbar_box.toolbar.insert(separator, -1) ++separator.show() ++ ++color_button = ColorToolButton() ++toolbar_box.toolbar.insert(color_button, -1) ++color_button.show() ++ ++favorite_button = ToggleToolButton('emblem-favorite') ++favorite_button.set_tooltip('Favorite') ++toolbar_box.toolbar.insert(favorite_button, -1) ++favorite_button.show() ++ ++ ++if __name__ == '__main__': ++ common.main(test) +diff --git b/examples/tray.py a/examples/tray.py +new file mode 100644 +index 0000000..b336a92 +--- /dev/null ++++ a/examples/tray.py +@@ -0,0 +1,82 @@ ++# Copyright (C) 2007, Red Hat, Inc. ++# ++# This library is free software; you can redistribute it and/or ++# modify it under the terms of the GNU Lesser General Public ++# License as published by the Free Software Foundation; either ++# version 2 of the License, or (at your option) any later version. ++# ++# This library is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++# Lesser General Public License for more details. ++# ++# You should have received a copy of the GNU Lesser General Public ++# License along with this library; if not, write to the ++# Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++# Boston, MA 02111-1307, USA. ++ ++""" ++Test the sugar3.graphics.icon.Icon widget. ++""" ++ ++from gi.repository import Gtk ++ ++from sugar3.graphics.tray import HTray, VTray ++from sugar3.graphics.tray import TrayButton, TrayIcon ++ ++import common ++ ++test = common.Test() ++ ++vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) ++ ++tray = HTray() ++vbox.pack_start(tray, False, False, 0) ++tray.show() ++ ++theme_icons = Gtk.IconTheme.get_default().list_icons(context=None) ++ ++for i in range(0, 100): ++ button = TrayButton(icon_name=theme_icons[i]) ++ tray.add_item(button) ++ button.show() ++ ++tray = HTray() ++vbox.pack_start(tray, False, False, 0) ++tray.show() ++ ++for i in range(0, 10): ++ icon = TrayIcon(icon_name=theme_icons[i]) ++ tray.add_item(icon) ++ icon.show() ++ ++hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) ++ ++tray = VTray() ++hbox.pack_start(tray, False, False, 0) ++tray.show() ++ ++for i in range(0, 100): ++ button = TrayButton(icon_name=theme_icons[i]) ++ tray.add_item(button) ++ button.show() ++ ++tray = VTray() ++hbox.pack_start(tray, False, False, 0) ++tray.show() ++ ++for i in range(0, 4): ++ button = TrayButton(icon_name=theme_icons[i]) ++ tray.add_item(button) ++ button.show() ++ ++vbox.pack_start(hbox, True, True, 0) ++hbox.show() ++ ++test.pack_start(vbox, True, True, 0) ++vbox.show() ++ ++test.show() ++ ++if __name__ == '__main__': ++ common.main(test) +diff --git b/m4/.gitignore a/m4/.gitignore +new file mode 100644 +index 0000000..e08c7c8 +--- /dev/null ++++ a/m4/.gitignore +@@ -0,0 +1,3 @@ ++intltool.m4 ++libtool.m4 ++lt*.m4 +diff --git b/m4/python.m4 a/m4/python.m4 +new file mode 100644 +index 0000000..e1c5266 +--- /dev/null ++++ a/m4/python.m4 +@@ -0,0 +1,62 @@ ++## this one is commonly used with AM_PATH_PYTHONDIR ... ++dnl AM_CHECK_PYMOD(MODNAME [,SYMBOL [,ACTION-IF-FOUND [,ACTION-IF-NOT-FOUND]]]) ++dnl Check if a module containing a given symbol is visible to python. ++AC_DEFUN([AM_CHECK_PYMOD], ++[AC_REQUIRE([AM_PATH_PYTHON]) ++py_mod_var=`echo $1['_']$2 | sed 'y%./+-%__p_%'` ++AC_MSG_CHECKING(for ifelse([$2],[],,[$2 in ])python module $1) ++AC_CACHE_VAL(py_cv_mod_$py_mod_var, [ ++ifelse([$2],[], [prog=" ++import sys ++try: ++ import $1 ++except ImportError: ++ sys.exit(1) ++except: ++ sys.exit(0) ++sys.exit(0)"], [prog=" ++import $1 ++$1.$2"]) ++if $PYTHON -c "$prog" 1>&AC_FD_CC 2>&AC_FD_CC ++ then ++ eval "py_cv_mod_$py_mod_var=yes" ++ else ++ eval "py_cv_mod_$py_mod_var=no" ++ fi ++]) ++py_val=`eval "echo \`echo '$py_cv_mod_'$py_mod_var\`"` ++if test "x$py_val" != xno; then ++ AC_MSG_RESULT(yes) ++ ifelse([$3], [],, [$3 ++])dnl ++else ++ AC_MSG_RESULT(no) ++ ifelse([$4], [],, [$4 ++])dnl ++fi ++]) ++ ++dnl a macro to check for ability to create python extensions ++dnl AM_CHECK_PYTHON_HEADERS([ACTION-IF-POSSIBLE], [ACTION-IF-NOT-POSSIBLE]) ++dnl function also defines PYTHON_INCLUDES ++AC_DEFUN([AM_CHECK_PYTHON_HEADERS], ++[AC_REQUIRE([AM_PATH_PYTHON]) ++AC_MSG_CHECKING(for headers required to compile python extensions) ++dnl deduce PYTHON_INCLUDES ++py_prefix=`$PYTHON -c "import sys; print sys.prefix"` ++py_exec_prefix=`$PYTHON -c "import sys; print sys.exec_prefix"` ++PYTHON_INCLUDES="-I${py_prefix}/include/python${PYTHON_VERSION}" ++if test "$py_prefix" != "$py_exec_prefix"; then ++ PYTHON_INCLUDES="$PYTHON_INCLUDES -I${py_exec_prefix}/include/python${PYTHON_VERSION}" ++fi ++AC_SUBST(PYTHON_INCLUDES) ++dnl check if the headers exist: ++save_CPPFLAGS="$CPPFLAGS" ++CPPFLAGS="$CPPFLAGS $PYTHON_INCLUDES" ++AC_TRY_CPP([#include <Python.h>],dnl ++[AC_MSG_RESULT(found) ++$1],dnl ++[AC_MSG_RESULT(not found) ++$2]) ++CPPFLAGS="$save_CPPFLAGS" ++]) +diff --git b/make-doc.sh a/make-doc.sh +new file mode 100755 +index 0000000..d8721d9 +--- /dev/null ++++ a/make-doc.sh +@@ -0,0 +1,4 @@ ++#!/bin/sh ++ ++sphinx-apidoc --force --separate --output-dir=doc src ++make -C doc html +diff --git b/po/.gitignore a/po/.gitignore +new file mode 100644 +index 0000000..da9bbde +--- /dev/null ++++ a/po/.gitignore +@@ -0,0 +1,4 @@ ++*.gmo ++Makefile.in.in ++POTFILES ++stamp-it +diff --git b/po/ast.po a/po/ast.po +new file mode 100644 +index 0000000..983872f +--- /dev/null ++++ a/po/ast.po +@@ -0,0 +1,559 @@ ++# SOME DESCRIPTIVE TITLE. ++# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER ++# This file is distributed under the same license as the PACKAGE package. ++# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. ++msgid "" ++msgstr "" ++"Project-Id-Version: PACKAGE VERSION\n" ++"Report-Msgid-Bugs-To: \n" ++"POT-Creation-Date: 2017-10-16 18:58+1100\n" ++"PO-Revision-Date: 2016-10-05 03:47+0000\n" ++"Last-Translator: Chris <cjl@sugarlabs.org>\n" ++"Language-Team: LANGUAGE <LL@li.org>\n" ++"Language: ast\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Pootle 2.5.1.1\n" ++"X-POOTLE-MTIME: 1475639246.000000\n" ++ ++#: ../src/sugar3/activity/activity.py:416 src/sugar3/activity/activity.py:467 ++#, python-format ++msgid "%s Activity" ++msgstr "" ++ ++#: ../src/sugar3/activity/activity.py:967 src/sugar3/activity/activity.py:1127 ++msgid "Keep error" ++msgstr "" ++ ++#: ../src/sugar3/activity/activity.py:968 src/sugar3/activity/activity.py:1128 ++msgid "Keep error: all changes will be lost" ++msgstr "" ++ ++#: ../src/sugar3/activity/activity.py:971 src/sugar3/activity/activity.py:1131 ++msgid "Don't stop" ++msgstr "" ++ ++#: ../src/sugar3/activity/activity.py:975 src/sugar3/activity/activity.py:1135 ++msgid "Stop anyway" ++msgstr "" ++ ++#: ../src/sugar3/activity/widgets.py:86 src/sugar3/activity/activity.py:1169 ++#: src/sugar3/activity/widgets.py:86 ++msgid "Stop" ++msgstr "" ++ ++#: ../src/sugar3/activity/widgets.py:98 src/sugar3/activity/widgets.py:99 ++msgid "Undo" ++msgstr "" ++ ++#: ../src/sugar3/activity/widgets.py:106 src/sugar3/activity/widgets.py:107 ++msgid "Redo" ++msgstr "" ++ ++#: ../src/sugar3/activity/widgets.py:113 src/sugar3/activity/widgets.py:114 ++msgid "Copy" ++msgstr "" ++ ++#: ../src/sugar3/activity/widgets.py:121 src/sugar3/activity/widgets.py:122 ++msgid "Paste" ++msgstr "" ++ ++#: ../src/sugar3/activity/widgets.py:132 src/sugar3/activity/widgets.py:133 ++msgid "Private" ++msgstr "" ++ ++#: ../src/sugar3/activity/widgets.py:139 src/sugar3/activity/widgets.py:140 ++msgid "My Neighborhood" ++msgstr "" ++ ++#: ../src/sugar3/activity/widgets.py:233 src/sugar3/activity/widgets.py:234 ++msgid "Description" ++msgstr "" ++ ++#: ../src/sugar3/graphics/alert.py:287 ../src/sugar3/graphics/alert.py:429 ++#: src/sugar3/activity/activity.py:1189 src/sugar3/graphics/alert.py:301 ++#: src/sugar3/graphics/alert.py:467 ++msgid "Cancel" ++msgstr "" ++ ++#: ../src/sugar3/graphics/alert.py:291 ../src/sugar3/graphics/alert.py:337 ++#: ../src/sugar3/graphics/alert.py:479 src/sugar3/graphics/alert.py:305 ++#: src/sugar3/graphics/alert.py:346 src/sugar3/graphics/alert.py:393 ++#: src/sugar3/graphics/alert.py:512 ++msgid "Ok" ++msgstr "" ++ ++#: ../src/sugar3/graphics/alert.py:434 src/sugar3/graphics/alert.py:464 ++msgid "Continue" ++msgstr "" ++ ++#: ../src/sugar3/graphics/colorbutton.py:54 ++#: src/sugar3/graphics/colorbutton.py:55 ++msgid "Choose a color" ++msgstr "" ++ ++#: ../src/sugar3/graphics/colorbutton.py:279 ++#: src/sugar3/graphics/colorbutton.py:300 ++msgid "Red" ++msgstr "" ++ ++#: ../src/sugar3/graphics/colorbutton.py:281 ++#: src/sugar3/graphics/colorbutton.py:302 ++#, fuzzy ++msgid "Green" ++msgstr "griegu" ++ ++#: ../src/sugar3/graphics/colorbutton.py:283 ++#: src/sugar3/graphics/colorbutton.py:304 ++msgid "Blue" ++msgstr "" ++ ++#: ../src/sugar3/util.py:217 src/sugar3/util.py:217 ++msgid " and " ++msgstr "" ++ ++#: ../src/sugar3/util.py:218 src/sugar3/util.py:218 ++msgid ", " ++msgstr "" ++ ++#. TRANS: Indicating something that just happened, eg. "just now", "moments ago" ++#: ../src/sugar3/util.py:221 src/sugar3/util.py:221 ++msgid "Seconds ago" ++msgstr "" ++ ++#. TRANS: Indicating time passed, eg. "[10 day, 5 hours] ago", ++#. "[2 minutes] in the past", or "[3 years, 1 month] earlier" ++#: ../src/sugar3/util.py:225 src/sugar3/util.py:225 ++#, python-format ++msgid "%s ago" ++msgstr "" ++ ++#. TRANS: Relative dates (eg. 1 month and 5 days). ++#: ../src/sugar3/util.py:240 src/sugar3/util.py:240 ++#, python-format ++msgid "%d year" ++msgid_plural "%d years" ++msgstr[0] "" ++msgstr[1] "" ++ ++#: ../src/sugar3/util.py:241 src/sugar3/util.py:241 ++#, python-format ++msgid "%d month" ++msgid_plural "%d months" ++msgstr[0] "" ++msgstr[1] "" ++ ++#: ../src/sugar3/util.py:242 src/sugar3/util.py:242 ++#, python-format ++msgid "%d week" ++msgid_plural "%d weeks" ++msgstr[0] "" ++msgstr[1] "" ++ ++#: ../src/sugar3/util.py:243 src/sugar3/util.py:243 ++#, python-format ++msgid "%d day" ++msgid_plural "%d days" ++msgstr[0] "" ++msgstr[1] "" ++ ++#: ../src/sugar3/util.py:244 src/sugar3/util.py:244 ++#, python-format ++msgid "%d hour" ++msgid_plural "%d hours" ++msgstr[0] "" ++msgstr[1] "" ++ ++#: ../src/sugar3/util.py:245 src/sugar3/util.py:245 ++#, python-format ++msgid "%d minute" ++msgid_plural "%d minutes" ++msgstr[0] "" ++msgstr[1] "" ++ ++#: ../src/sugar3/util.py:346 src/sugar3/util.py:346 ++msgid "Empty" ++msgstr "" ++ ++#: ../src/sugar3/util.py:348 src/sugar3/util.py:348 ++#, python-format ++msgid "%d B" ++msgstr "" ++ ++#: ../src/sugar3/util.py:350 src/sugar3/util.py:350 ++#, python-format ++msgid "%d KB" ++msgstr "" ++ ++#: ../src/sugar3/util.py:352 src/sugar3/util.py:352 ++#, python-format ++msgid "%d MB" ++msgstr "" ++ ++#: ../src/sugar3/util.py:354 src/sugar3/util.py:354 ++#, python-format ++msgid "%d GB" ++msgstr "" ++ ++#: ../src/sugar3/mime.py:56 src/sugar3/mime.py:59 ++msgid "Text" ++msgstr "Testu" ++ ++#: ../src/sugar3/mime.py:63 src/sugar3/mime.py:66 ++msgid "Image" ++msgstr "" ++ ++#: ../src/sugar3/mime.py:68 src/sugar3/mime.py:71 ++msgid "Audio" ++msgstr "" ++ ++#: ../src/sugar3/mime.py:75 src/sugar3/mime.py:78 ++msgid "Video" ++msgstr "" ++ ++#: ../src/sugar3/mime.py:86 src/sugar3/mime.py:89 ++msgid "Link" ++msgstr "" ++ ++#: ../src/sugar3/mime.py:91 src/sugar3/mime.py:94 ++msgid "Bundle" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:48 src/sugar3/speech.py:56 ++msgid "Afrikaans" ++msgstr "afrikaans" ++ ++#: ../src/sugar3/speech.py:49 src/sugar3/speech.py:58 ++msgid "Aragonese" ++msgstr "aragonés" ++ ++#: ../src/sugar3/speech.py:50 src/sugar3/speech.py:60 ++msgid "Bulgarian" ++msgstr "búlgaru" ++ ++#: ../src/sugar3/speech.py:51 src/sugar3/speech.py:62 ++msgid "Bosnian" ++msgstr "bosniu" ++ ++#: ../src/sugar3/speech.py:52 src/sugar3/speech.py:64 ++msgid "Catalan" ++msgstr "catalán" ++ ++#: ../src/sugar3/speech.py:53 src/sugar3/speech.py:66 ++msgid "Czech" ++msgstr "checu" ++ ++#: ../src/sugar3/speech.py:54 src/sugar3/speech.py:68 ++msgid "Welsh" ++msgstr "galés" ++ ++#: ../src/sugar3/speech.py:55 src/sugar3/speech.py:70 ++msgid "Danish" ++msgstr "danés" ++ ++#: ../src/sugar3/speech.py:56 src/sugar3/speech.py:72 ++msgid "German" ++msgstr "alemán" ++ ++#: ../src/sugar3/speech.py:57 src/sugar3/speech.py:74 ++msgid "Greek" ++msgstr "griegu" ++ ++#: ../src/sugar3/speech.py:58 ++msgid "Default" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:59 src/sugar3/speech.py:77 ++msgid "English Britain" ++msgstr "inglés de Gran Bretaña" ++ ++#: ../src/sugar3/speech.py:60 src/sugar3/speech.py:79 ++#, fuzzy ++msgid "English scottish" ++msgstr "inglés" ++ ++#: ../src/sugar3/speech.py:61 src/sugar3/speech.py:80 ++#, fuzzy ++msgid "English-north" ++msgstr "inglés" ++ ++#: ../src/sugar3/speech.py:62 src/sugar3/speech.py:82 ++msgid "English_rp" ++msgstr "inglés" ++ ++#: ../src/sugar3/speech.py:63 src/sugar3/speech.py:84 ++#, fuzzy ++msgid "English_wmids" ++msgstr "inglés" ++ ++#: ../src/sugar3/speech.py:64 src/sugar3/speech.py:86 ++msgid "English USA" ++msgstr "Inglés (EE.XX.)" ++ ++#: ../src/sugar3/speech.py:65 ++#, fuzzy ++msgid "English west indies" ++msgstr "inglés" ++ ++#: ../src/sugar3/speech.py:66 src/sugar3/speech.py:90 ++msgid "Esperanto" ++msgstr "esperanto" ++ ++#: ../src/sugar3/speech.py:67 src/sugar3/speech.py:92 ++msgid "Spanish" ++msgstr "español" ++ ++#: ../src/sugar3/speech.py:68 src/sugar3/speech.py:93 ++#, fuzzy ++msgid "Spanish latin american" ++msgstr "español" ++ ++#: ../src/sugar3/speech.py:69 src/sugar3/speech.py:95 ++msgid "Estonian" ++msgstr "estoniu" ++ ++#: ../src/sugar3/speech.py:70 src/sugar3/speech.py:97 ++msgid "Farsi" ++msgstr "persa" ++ ++#: ../src/sugar3/speech.py:71 src/sugar3/speech.py:99 ++msgid "Farsi-pinglish" ++msgstr "persa-inglés" ++ ++#: ../src/sugar3/speech.py:72 src/sugar3/speech.py:101 ++msgid "Finnish" ++msgstr "finlandés" ++ ++#: ../src/sugar3/speech.py:73 src/sugar3/speech.py:103 ++msgid "French belgium" ++msgstr "Francés (Bélxica)" ++ ++#: ../src/sugar3/speech.py:74 src/sugar3/speech.py:105 ++msgid "French" ++msgstr "francés" ++ ++#: ../src/sugar3/speech.py:75 src/sugar3/speech.py:107 ++msgid "Irish-gaeilge" ++msgstr "irlandés" ++ ++#: ../src/sugar3/speech.py:76 src/sugar3/speech.py:109 ++msgid "Greek-ancient" ++msgstr "Griegu, Antiguu" ++ ++#: ../src/sugar3/speech.py:77 src/sugar3/speech.py:111 ++msgid "Hindi" ++msgstr "hindi" ++ ++#: ../src/sugar3/speech.py:78 src/sugar3/speech.py:113 ++msgid "Croatian" ++msgstr "croata" ++ ++#: ../src/sugar3/speech.py:79 src/sugar3/speech.py:115 ++msgid "Hungarian" ++msgstr "húngaru" ++ ++#: ../src/sugar3/speech.py:80 src/sugar3/speech.py:117 ++msgid "Armenian" ++msgstr "armeniu" ++ ++#: ../src/sugar3/speech.py:81 src/sugar3/speech.py:119 ++#, fuzzy ++msgid "Armenian (west)" ++msgstr "armeniu" ++ ++#: ../src/sugar3/speech.py:82 src/sugar3/speech.py:121 ++msgid "Indonesian" ++msgstr "indonesiu" ++ ++#: ../src/sugar3/speech.py:83 src/sugar3/speech.py:123 ++msgid "Icelandic" ++msgstr "islandés" ++ ++#: ../src/sugar3/speech.py:84 src/sugar3/speech.py:125 ++msgid "Italian" ++msgstr "italianu" ++ ++#: ../src/sugar3/speech.py:85 src/sugar3/speech.py:127 ++msgid "Lojban" ++msgstr "lojban" ++ ++#: ../src/sugar3/speech.py:86 src/sugar3/speech.py:129 ++msgid "Georgian" ++msgstr "xeorxanu" ++ ++#: ../src/sugar3/speech.py:87 src/sugar3/speech.py:131 ++msgid "Kannada" ++msgstr "canarés" ++ ++#: ../src/sugar3/speech.py:88 src/sugar3/speech.py:133 ++msgid "Kurdish" ++msgstr "curdu" ++ ++#: ../src/sugar3/speech.py:89 src/sugar3/speech.py:135 ++msgid "Latin" ++msgstr "llatÃn" ++ ++#: ../src/sugar3/speech.py:90 src/sugar3/speech.py:137 ++msgid "Lithuanian" ++msgstr "lituanu" ++ ++#: ../src/sugar3/speech.py:91 src/sugar3/speech.py:139 ++msgid "Latvian" ++msgstr "letón" ++ ++#: ../src/sugar3/speech.py:92 src/sugar3/speech.py:141 ++msgid "Macedonian" ++msgstr "macedoniu" ++ ++#: ../src/sugar3/speech.py:93 src/sugar3/speech.py:143 ++msgid "Malayalam" ++msgstr "malayalam" ++ ++#: ../src/sugar3/speech.py:94 src/sugar3/speech.py:145 ++msgid "Malay" ++msgstr "malayu" ++ ++#: ../src/sugar3/speech.py:95 src/sugar3/speech.py:147 ++msgid "Nepali" ++msgstr "nepalés" ++ ++#: ../src/sugar3/speech.py:96 src/sugar3/speech.py:149 ++msgid "Dutch" ++msgstr "neerlandés" ++ ++#: ../src/sugar3/speech.py:97 src/sugar3/speech.py:151 ++msgid "Norwegian" ++msgstr "noruegu" ++ ++#: ../src/sugar3/speech.py:98 src/sugar3/speech.py:153 ++msgid "Punjabi" ++msgstr "punyabÃ" ++ ++#: ../src/sugar3/speech.py:99 src/sugar3/speech.py:155 ++msgid "Polish" ++msgstr "polacu" ++ ++#: ../src/sugar3/speech.py:100 src/sugar3/speech.py:157 ++msgid "Portuguese (Brazil)" ++msgstr "Portugués (Brasil)" ++ ++#: ../src/sugar3/speech.py:101 src/sugar3/speech.py:159 ++msgid "Portuguese (Portugal)" ++msgstr "Portugués (Portugal)" ++ ++#: ../src/sugar3/speech.py:102 src/sugar3/speech.py:161 ++msgid "Romanian" ++msgstr "rumanu" ++ ++#: ../src/sugar3/speech.py:103 src/sugar3/speech.py:163 ++msgid "Russian" ++msgstr "rusu" ++ ++#: ../src/sugar3/speech.py:104 src/sugar3/speech.py:165 ++msgid "Slovak" ++msgstr "eslovacu" ++ ++#: ../src/sugar3/speech.py:105 src/sugar3/speech.py:167 ++msgid "Albanian" ++msgstr "albanu" ++ ++#: ../src/sugar3/speech.py:106 src/sugar3/speech.py:169 ++msgid "Serbian" ++msgstr "serbiu" ++ ++#: ../src/sugar3/speech.py:107 src/sugar3/speech.py:171 ++msgid "Swedish" ++msgstr "suecu" ++ ++#: ../src/sugar3/speech.py:108 ++msgid "Swahili-test" ++msgstr "suaḥili" ++ ++#: ../src/sugar3/speech.py:109 src/sugar3/speech.py:175 ++msgid "Tamil" ++msgstr "tamil" ++ ++#: ../src/sugar3/speech.py:110 src/sugar3/speech.py:177 ++msgid "Turkish" ++msgstr "turcu" ++ ++#: ../src/sugar3/speech.py:111 src/sugar3/speech.py:179 ++msgid "Vietnam" ++msgstr "vietnamÃn" ++ ++#: ../src/sugar3/speech.py:112 src/sugar3/speech.py:180 ++msgid "Vietnam_hue" ++msgstr "vietnamÃn_hue" ++ ++#: ../src/sugar3/speech.py:113 src/sugar3/speech.py:181 ++msgid "Vietnam_sgn" ++msgstr "vietnamÃn_sgn" ++ ++#: ../src/sugar3/speech.py:114 src/sugar3/speech.py:183 ++#, fuzzy ++msgid "Mandarin" ++msgstr "chinu" ++ ++#: ../src/sugar3/speech.py:115 src/sugar3/speech.py:185 ++#, fuzzy ++msgid "Cantonese" ++msgstr "chinu" ++ ++#: src/sugar3/activity/activity.py:1170 ++msgid "Stop: name your journal entry" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1193 ++msgid "Cancel stop and continue the activity" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1230 ++msgid "Save new" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1231 ++msgid "Save a new journal entry" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1234 ++msgid "Save" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1235 ++msgid "Save into the old journal entry" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1241 ++msgid "Erase changes" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1242 ++msgid "Erase what you have done, and leave your old journal entry unchanged" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1245 ++msgid "Erase" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1246 ++msgid "Erase what you have done, and avoid making a journal entry" ++msgstr "" ++ ++#: src/sugar3/graphics/popwindow.py:179 ++msgid "Close" ++msgstr "" ++ ++#: src/sugar3/speech.py:75 ++msgid "English" ++msgstr "" ++ ++#: src/sugar3/speech.py:88 ++#, fuzzy ++msgid "English West Indies" ++msgstr "inglés" ++ ++#: src/sugar3/speech.py:173 ++msgid "Swahili" ++msgstr "" +diff --git b/po/nah.po a/po/nah.po +new file mode 100644 +index 0000000..17e8938 +--- /dev/null ++++ a/po/nah.po +@@ -0,0 +1,552 @@ ++# SOME DESCRIPTIVE TITLE. ++# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER ++# This file is distributed under the same license as the PACKAGE package. ++# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. ++msgid "" ++msgstr "" ++"Project-Id-Version: PACKAGE VERSION\n" ++"Report-Msgid-Bugs-To: \n" ++"POT-Creation-Date: 2017-10-16 18:58+1100\n" ++"PO-Revision-Date: 2013-08-30 17:49+0200\n" ++"Last-Translator: Chris <cjl@laptop.org>\n" ++"Language-Team: LANGUAGE <LL@li.org>\n" ++"Language: nah\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Pootle 2.0.5\n" ++ ++#: ../src/sugar3/activity/activity.py:416 src/sugar3/activity/activity.py:467 ++#, python-format ++#, python-format, fuzzy ++msgid "%s Activity" ++msgstr "tlen ti chiuas %s" ++ ++#: ../src/sugar3/activity/activity.py:967 src/sugar3/activity/activity.py:1127 ++#, fuzzy ++msgid "Keep error" ++msgstr "kuapolo" ++ ++#: ../src/sugar3/activity/activity.py:968 src/sugar3/activity/activity.py:1128 ++msgid "Keep error: all changes will be lost" ++msgstr "kuapolo kema ti ajukui katli ti chijki pulus" ++ ++#: ../src/sugar3/activity/activity.py:971 src/sugar3/activity/activity.py:1131 ++msgid "Don't stop" ++msgstr "inka moketsas" ++ ++#: ../src/sugar3/activity/activity.py:975 src/sugar3/activity/activity.py:1135 ++msgid "Stop anyway" ++msgstr "moketsas" ++ ++#: ../src/sugar3/activity/widgets.py:86 src/sugar3/activity/activity.py:1169 ++#: src/sugar3/activity/widgets.py:86 ++#, fuzzy ++msgid "Stop" ++msgstr "Moketsas" ++ ++#: ../src/sugar3/activity/widgets.py:98 src/sugar3/activity/widgets.py:99 ++msgid "Undo" ++msgstr "patik" ++ ++#: ../src/sugar3/activity/widgets.py:106 src/sugar3/activity/widgets.py:107 ++msgid "Redo" ++msgstr "ompawi" ++ ++#: ../src/sugar3/activity/widgets.py:113 src/sugar3/activity/widgets.py:114 ++msgid "Copy" ++msgstr "ixcopina" ++ ++#: ../src/sugar3/activity/widgets.py:121 src/sugar3/activity/widgets.py:122 ++msgid "Paste" ++msgstr "tlatskis" ++ ++#: ../src/sugar3/activity/widgets.py:132 src/sugar3/activity/widgets.py:133 ++msgid "Private" ++msgstr "san iyaya" ++ ++#: ../src/sugar3/activity/widgets.py:139 src/sugar3/activity/widgets.py:140 ++msgid "My Neighborhood" ++msgstr "nechicokalime" ++ ++#: ../src/sugar3/activity/widgets.py:233 src/sugar3/activity/widgets.py:234 ++msgid "Description" ++msgstr "tlaixkuilolli" ++ ++#: ../src/sugar3/graphics/alert.py:287 ../src/sugar3/graphics/alert.py:429 ++#: src/sugar3/activity/activity.py:1189 src/sugar3/graphics/alert.py:301 ++#: src/sugar3/graphics/alert.py:467 ++#, fuzzy ++msgid "Cancel" ++msgstr "Tlamilti" ++ ++#: ../src/sugar3/graphics/alert.py:291 ../src/sugar3/graphics/alert.py:337 ++#: ../src/sugar3/graphics/alert.py:479 src/sugar3/graphics/alert.py:305 ++#: src/sugar3/graphics/alert.py:346 src/sugar3/graphics/alert.py:393 ++#: src/sugar3/graphics/alert.py:512 ++msgid "Ok" ++msgstr "selis" ++ ++#: ../src/sugar3/graphics/alert.py:434 src/sugar3/graphics/alert.py:464 ++msgid "Continue" ++msgstr "mosentokilis" ++ ++#: ../src/sugar3/graphics/colorbutton.py:54 ++#: src/sugar3/graphics/colorbutton.py:55 ++msgid "Choose a color" ++msgstr "xitlapejoeni se tlapalli" ++ ++#: ../src/sugar3/graphics/colorbutton.py:279 ++#: src/sugar3/graphics/colorbutton.py:300 ++msgid "Red" ++msgstr "chichiltik" ++ ++#: ../src/sugar3/graphics/colorbutton.py:281 ++#: src/sugar3/graphics/colorbutton.py:302 ++msgid "Green" ++msgstr "xoxowik" ++ ++#: ../src/sugar3/graphics/colorbutton.py:283 ++#: src/sugar3/graphics/colorbutton.py:304 ++msgid "Blue" ++msgstr "axoxoltik" ++ ++#: ../src/sugar3/util.py:217 src/sugar3/util.py:217 ++msgid " and " ++msgstr " wan " ++ ++#: ../src/sugar3/util.py:218 src/sugar3/util.py:218 ++msgid ", " ++msgstr ", " ++ ++#. TRANS: Indicating something that just happened, eg. "just now", "moments ago" ++#: ../src/sugar3/util.py:221 src/sugar3/util.py:221 ++msgid "Seconds ago" ++msgstr "omekawiltsitsi ikatlaika" ++ ++#. TRANS: Indicating time passed, eg. "[10 day, 5 hours] ago", ++#. "[2 minutes] in the past", or "[3 years, 1 month] earlier" ++#: ../src/sugar3/util.py:225 src/sugar3/util.py:225 ++#, python-format ++msgid "%s ago" ++msgstr "%s katlaika" ++ ++#. TRANS: Relative dates (eg. 1 month and 5 days). ++#: ../src/sugar3/util.py:240 src/sugar3/util.py:240 ++#, python-format ++msgid "%d year" ++msgid_plural "%d years" ++msgstr[0] "%d xiwitl" ++msgstr[1] "%d xiwimej" ++ ++#: ../src/sugar3/util.py:241 src/sugar3/util.py:241 ++#, python-format ++msgid "%d month" ++msgid_plural "%d months" ++msgstr[0] "%d meestli" ++msgstr[1] "%d meestlimej" ++ ++#: ../src/sugar3/util.py:242 src/sugar3/util.py:242 ++#, python-format ++msgid "%d week" ++msgid_plural "%d weeks" ++msgstr[0] "%d chikontonal" ++msgstr[1] "%d chikontonalmej" ++ ++#: ../src/sugar3/util.py:243 src/sugar3/util.py:243 ++#, python-format ++msgid "%d day" ++msgid_plural "%d days" ++msgstr[0] "%d tonal" ++msgstr[1] "%d tonalmej" ++ ++#: ../src/sugar3/util.py:244 src/sugar3/util.py:244 ++#, python-format ++msgid "%d hour" ++msgid_plural "%d hours" ++msgstr[0] "%d kawitl" ++msgstr[1] "%d kawitlmej" ++ ++#: ../src/sugar3/util.py:245 src/sugar3/util.py:245 ++#, python-format ++msgid "%d minute" ++msgid_plural "%d minutes" ++msgstr[0] "%d kawiltsi" ++msgstr[1] "%d kawilmej" ++ ++#: ../src/sugar3/util.py:346 src/sugar3/util.py:346 ++msgid "Empty" ++msgstr "kaktok" ++ ++#: ../src/sugar3/util.py:348 src/sugar3/util.py:348 ++#, python-format ++msgid "%d B" ++msgstr "%d B" ++ ++#: ../src/sugar3/util.py:350 src/sugar3/util.py:350 ++#, python-format ++msgid "%d KB" ++msgstr "%de KB" ++ ++#: ../src/sugar3/util.py:352 src/sugar3/util.py:352 ++#, python-format ++msgid "%d MB" ++msgstr "%d MB" ++ ++#: ../src/sugar3/util.py:354 src/sugar3/util.py:354 ++#, python-format ++msgid "%d GB" ++msgstr "%d GB" ++ ++#: ../src/sugar3/mime.py:56 src/sugar3/mime.py:59 ++msgid "Text" ++msgstr "tlakuilolpa" ++ ++#: ../src/sugar3/mime.py:63 src/sugar3/mime.py:66 ++msgid "Image" ++msgstr "ixnextli" ++ ++#: ../src/sugar3/mime.py:68 src/sugar3/mime.py:71 ++msgid "Audio" ++msgstr "kakiilistli" ++ ++#: ../src/sugar3/mime.py:75 src/sugar3/mime.py:78 ++msgid "Video" ++msgstr "ixnextilli" ++ ++#: ../src/sugar3/mime.py:86 src/sugar3/mime.py:89 ++msgid "Link" ++msgstr "saloli" ++ ++#: ../src/sugar3/mime.py:91 src/sugar3/mime.py:94 ++msgid "Bundle" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:48 src/sugar3/speech.py:56 ++msgid "Afrikaans" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:49 src/sugar3/speech.py:58 ++msgid "Aragonese" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:50 src/sugar3/speech.py:60 ++msgid "Bulgarian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:51 src/sugar3/speech.py:62 ++msgid "Bosnian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:52 src/sugar3/speech.py:64 ++msgid "Catalan" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:53 src/sugar3/speech.py:66 ++msgid "Czech" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:54 src/sugar3/speech.py:68 ++msgid "Welsh" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:55 src/sugar3/speech.py:70 ++msgid "Danish" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:56 src/sugar3/speech.py:72 ++msgid "German" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:57 src/sugar3/speech.py:74 ++msgid "Greek" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:58 ++msgid "Default" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:59 src/sugar3/speech.py:77 ++msgid "English Britain" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:60 src/sugar3/speech.py:79 ++msgid "English scottish" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:61 src/sugar3/speech.py:80 ++msgid "English-north" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:62 src/sugar3/speech.py:82 ++msgid "English_rp" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:63 src/sugar3/speech.py:84 ++msgid "English_wmids" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:64 src/sugar3/speech.py:86 ++msgid "English USA" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:65 ++msgid "English west indies" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:66 src/sugar3/speech.py:90 ++msgid "Esperanto" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:67 src/sugar3/speech.py:92 ++msgid "Spanish" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:68 src/sugar3/speech.py:93 ++msgid "Spanish latin american" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:69 src/sugar3/speech.py:95 ++msgid "Estonian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:70 src/sugar3/speech.py:97 ++msgid "Farsi" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:71 src/sugar3/speech.py:99 ++msgid "Farsi-pinglish" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:72 src/sugar3/speech.py:101 ++msgid "Finnish" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:73 src/sugar3/speech.py:103 ++msgid "French belgium" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:74 src/sugar3/speech.py:105 ++msgid "French" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:75 src/sugar3/speech.py:107 ++msgid "Irish-gaeilge" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:76 src/sugar3/speech.py:109 ++msgid "Greek-ancient" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:77 src/sugar3/speech.py:111 ++msgid "Hindi" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:78 src/sugar3/speech.py:113 ++msgid "Croatian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:79 src/sugar3/speech.py:115 ++msgid "Hungarian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:80 src/sugar3/speech.py:117 ++msgid "Armenian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:81 src/sugar3/speech.py:119 ++msgid "Armenian (west)" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:82 src/sugar3/speech.py:121 ++msgid "Indonesian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:83 src/sugar3/speech.py:123 ++msgid "Icelandic" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:84 src/sugar3/speech.py:125 ++msgid "Italian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:85 src/sugar3/speech.py:127 ++msgid "Lojban" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:86 src/sugar3/speech.py:129 ++msgid "Georgian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:87 src/sugar3/speech.py:131 ++msgid "Kannada" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:88 src/sugar3/speech.py:133 ++msgid "Kurdish" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:89 src/sugar3/speech.py:135 ++msgid "Latin" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:90 src/sugar3/speech.py:137 ++msgid "Lithuanian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:91 src/sugar3/speech.py:139 ++msgid "Latvian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:92 src/sugar3/speech.py:141 ++msgid "Macedonian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:93 src/sugar3/speech.py:143 ++msgid "Malayalam" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:94 src/sugar3/speech.py:145 ++msgid "Malay" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:95 src/sugar3/speech.py:147 ++msgid "Nepali" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:96 src/sugar3/speech.py:149 ++msgid "Dutch" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:97 src/sugar3/speech.py:151 ++msgid "Norwegian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:98 src/sugar3/speech.py:153 ++msgid "Punjabi" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:99 src/sugar3/speech.py:155 ++msgid "Polish" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:100 src/sugar3/speech.py:157 ++msgid "Portuguese (Brazil)" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:101 src/sugar3/speech.py:159 ++msgid "Portuguese (Portugal)" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:102 src/sugar3/speech.py:161 ++msgid "Romanian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:103 src/sugar3/speech.py:163 ++msgid "Russian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:104 src/sugar3/speech.py:165 ++msgid "Slovak" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:105 src/sugar3/speech.py:167 ++msgid "Albanian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:106 src/sugar3/speech.py:169 ++msgid "Serbian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:107 src/sugar3/speech.py:171 ++msgid "Swedish" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:108 ++msgid "Swahili-test" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:109 src/sugar3/speech.py:175 ++msgid "Tamil" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:110 src/sugar3/speech.py:177 ++msgid "Turkish" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:111 src/sugar3/speech.py:179 ++msgid "Vietnam" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:112 src/sugar3/speech.py:180 ++msgid "Vietnam_hue" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:113 src/sugar3/speech.py:181 ++msgid "Vietnam_sgn" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:114 src/sugar3/speech.py:183 ++msgid "Mandarin" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:115 src/sugar3/speech.py:185 ++msgid "Cantonese" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1170 ++msgid "Stop: name your journal entry" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1193 ++msgid "Cancel stop and continue the activity" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1230 ++msgid "Save new" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1231 ++msgid "Save a new journal entry" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1234 ++msgid "Save" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1235 ++msgid "Save into the old journal entry" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1241 ++msgid "Erase changes" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1242 ++msgid "Erase what you have done, and leave your old journal entry unchanged" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1245 ++msgid "Erase" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1246 ++msgid "Erase what you have done, and avoid making a journal entry" ++msgstr "" ++ ++#: src/sugar3/graphics/popwindow.py:179 ++msgid "Close" ++msgstr "" ++ ++#: src/sugar3/speech.py:75 ++msgid "English" ++msgstr "" ++ ++#: src/sugar3/speech.py:88 ++msgid "English West Indies" ++msgstr "" ++ ++#: src/sugar3/speech.py:173 ++msgid "Swahili" ++msgstr "" +diff --git b/po/sugar-toolkit-gtk3.pot a/po/sugar-toolkit-gtk3.pot +new file mode 100644 +index 0000000..adfc7a5 +--- /dev/null ++++ a/po/sugar-toolkit-gtk3.pot +@@ -0,0 +1,569 @@ ++# SOME DESCRIPTIVE TITLE. ++# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER ++# This file is distributed under the same license as the PACKAGE package. ++# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. ++# ++#, fuzzy ++msgid "" ++msgstr "" ++"Project-Id-Version: PACKAGE VERSION\n" ++"Report-Msgid-Bugs-To: \n" ++"POT-Creation-Date: 2019-03-13 14:50+1100\n" ++"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" ++"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" ++"Language-Team: LANGUAGE <LL@li.org>\n" ++"Language: \n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=CHARSET\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" ++ ++#: ../src/sugar3/activity/activity.py:416 src/sugar3/activity/activity.py:467 ++#: src/sugar3/activity/activity.py:475 ++#, python-format ++msgid "%s Activity" ++msgstr "" ++ ++#: ../src/sugar3/activity/activity.py:967 src/sugar3/activity/activity.py:1127 ++#: src/sugar3/activity/activity.py:1122 ++msgid "Keep error" ++msgstr "" ++ ++#: ../src/sugar3/activity/activity.py:968 src/sugar3/activity/activity.py:1128 ++#: src/sugar3/activity/activity.py:1123 ++msgid "Keep error: all changes will be lost" ++msgstr "" ++ ++#: ../src/sugar3/activity/activity.py:971 src/sugar3/activity/activity.py:1131 ++#: src/sugar3/activity/activity.py:1126 ++msgid "Don't stop" ++msgstr "" ++ ++#: ../src/sugar3/activity/activity.py:975 src/sugar3/activity/activity.py:1135 ++#: src/sugar3/activity/activity.py:1130 ++msgid "Stop anyway" ++msgstr "" ++ ++#: ../src/sugar3/activity/widgets.py:86 src/sugar3/activity/activity.py:1169 ++#: src/sugar3/activity/widgets.py:86 src/sugar3/activity/activity.py:1164 ++#: src/sugar3/activity/widgets.py:88 ++msgid "Stop" ++msgstr "" ++ ++#: ../src/sugar3/activity/widgets.py:98 src/sugar3/activity/widgets.py:99 ++#: src/sugar3/activity/widgets.py:101 ++msgid "Undo" ++msgstr "" ++ ++#: ../src/sugar3/activity/widgets.py:106 src/sugar3/activity/widgets.py:107 ++#: src/sugar3/activity/widgets.py:109 ++msgid "Redo" ++msgstr "" ++ ++#: ../src/sugar3/activity/widgets.py:113 src/sugar3/activity/widgets.py:114 ++#: src/sugar3/activity/widgets.py:116 ++msgid "Copy" ++msgstr "" ++ ++#: ../src/sugar3/activity/widgets.py:121 src/sugar3/activity/widgets.py:122 ++#: src/sugar3/activity/widgets.py:124 ++msgid "Paste" ++msgstr "" ++ ++#: ../src/sugar3/activity/widgets.py:132 src/sugar3/activity/widgets.py:133 ++#: src/sugar3/activity/widgets.py:135 ++msgid "Private" ++msgstr "" ++ ++#: ../src/sugar3/activity/widgets.py:139 src/sugar3/activity/widgets.py:140 ++#: src/sugar3/activity/widgets.py:142 ++msgid "My Neighborhood" ++msgstr "" ++ ++#: ../src/sugar3/activity/widgets.py:233 src/sugar3/activity/widgets.py:234 ++#: src/sugar3/activity/widgets.py:249 ++msgid "Description" ++msgstr "" ++ ++#: ../src/sugar3/graphics/alert.py:287 ../src/sugar3/graphics/alert.py:429 ++#: src/sugar3/activity/activity.py:1189 src/sugar3/graphics/alert.py:301 ++#: src/sugar3/graphics/alert.py:467 src/sugar3/activity/activity.py:1184 ++#: src/sugar3/graphics/alert.py:308 src/sugar3/graphics/alert.py:476 ++msgid "Cancel" ++msgstr "" ++ ++#: ../src/sugar3/graphics/alert.py:291 ../src/sugar3/graphics/alert.py:337 ++#: ../src/sugar3/graphics/alert.py:479 src/sugar3/graphics/alert.py:305 ++#: src/sugar3/graphics/alert.py:346 src/sugar3/graphics/alert.py:393 ++#: src/sugar3/graphics/alert.py:512 src/sugar3/graphics/alert.py:312 ++#: src/sugar3/graphics/alert.py:353 src/sugar3/graphics/alert.py:402 ++#: src/sugar3/graphics/alert.py:521 ++msgid "Ok" ++msgstr "" ++ ++#: ../src/sugar3/graphics/alert.py:434 src/sugar3/graphics/alert.py:464 ++#: src/sugar3/graphics/alert.py:473 ++msgid "Continue" ++msgstr "" ++ ++#: ../src/sugar3/graphics/colorbutton.py:54 ++#: src/sugar3/graphics/colorbutton.py:55 src/sugar3/graphics/colorbutton.py:60 ++msgid "Choose a color" ++msgstr "" ++ ++#: ../src/sugar3/graphics/colorbutton.py:279 ++#: src/sugar3/graphics/colorbutton.py:300 ++#: src/sugar3/graphics/colorbutton.py:305 ++msgid "Red" ++msgstr "" ++ ++#: ../src/sugar3/graphics/colorbutton.py:281 ++#: src/sugar3/graphics/colorbutton.py:302 ++#: src/sugar3/graphics/colorbutton.py:307 ++msgid "Green" ++msgstr "" ++ ++#: ../src/sugar3/graphics/colorbutton.py:283 ++#: src/sugar3/graphics/colorbutton.py:304 ++#: src/sugar3/graphics/colorbutton.py:309 ++msgid "Blue" ++msgstr "" ++ ++#: ../src/sugar3/util.py:217 src/sugar3/util.py:217 src/sugar3/util.py:224 ++msgid " and " ++msgstr "" ++ ++#: ../src/sugar3/util.py:218 src/sugar3/util.py:218 src/sugar3/util.py:225 ++msgid ", " ++msgstr "" ++ ++#. TRANS: Indicating something that just happened, eg. "just now", "moments ago" ++#: ../src/sugar3/util.py:221 src/sugar3/util.py:221 src/sugar3/util.py:228 ++msgid "Seconds ago" ++msgstr "" ++ ++#. TRANS: Indicating time passed, eg. "[10 day, 5 hours] ago", ++#. "[2 minutes] in the past", or "[3 years, 1 month] earlier" ++#: ../src/sugar3/util.py:225 src/sugar3/util.py:225 src/sugar3/util.py:232 ++#, python-format ++msgid "%s ago" ++msgstr "" ++ ++#. TRANS: Relative dates (eg. 1 month and 5 days). ++#: ../src/sugar3/util.py:240 src/sugar3/util.py:240 src/sugar3/util.py:247 ++#, python-format ++msgid "%d year" ++msgid_plural "%d years" ++msgstr[0] "" ++msgstr[1] "" ++ ++#: ../src/sugar3/util.py:241 src/sugar3/util.py:241 src/sugar3/util.py:248 ++#, python-format ++msgid "%d month" ++msgid_plural "%d months" ++msgstr[0] "" ++msgstr[1] "" ++ ++#: ../src/sugar3/util.py:242 src/sugar3/util.py:242 src/sugar3/util.py:249 ++#, python-format ++msgid "%d week" ++msgid_plural "%d weeks" ++msgstr[0] "" ++msgstr[1] "" ++ ++#: ../src/sugar3/util.py:243 src/sugar3/util.py:243 src/sugar3/util.py:250 ++#, python-format ++msgid "%d day" ++msgid_plural "%d days" ++msgstr[0] "" ++msgstr[1] "" ++ ++#: ../src/sugar3/util.py:244 src/sugar3/util.py:244 src/sugar3/util.py:251 ++#, python-format ++msgid "%d hour" ++msgid_plural "%d hours" ++msgstr[0] "" ++msgstr[1] "" ++ ++#: ../src/sugar3/util.py:245 src/sugar3/util.py:245 src/sugar3/util.py:252 ++#, python-format ++msgid "%d minute" ++msgid_plural "%d minutes" ++msgstr[0] "" ++msgstr[1] "" ++ ++#: ../src/sugar3/util.py:346 src/sugar3/util.py:346 src/sugar3/util.py:354 ++msgid "Empty" ++msgstr "" ++ ++#: ../src/sugar3/util.py:348 src/sugar3/util.py:348 src/sugar3/util.py:356 ++#, python-format ++msgid "%d B" ++msgstr "" ++ ++#: ../src/sugar3/util.py:350 src/sugar3/util.py:350 src/sugar3/util.py:358 ++#, python-format ++msgid "%d KB" ++msgstr "" ++ ++#: ../src/sugar3/util.py:352 src/sugar3/util.py:352 src/sugar3/util.py:360 ++#, python-format ++msgid "%d MB" ++msgstr "" ++ ++#: ../src/sugar3/util.py:354 src/sugar3/util.py:354 src/sugar3/util.py:362 ++#, python-format ++msgid "%d GB" ++msgstr "" ++ ++#: ../src/sugar3/mime.py:56 src/sugar3/mime.py:59 src/sugar3/mime.py:61 ++msgid "Text" ++msgstr "" ++ ++#: ../src/sugar3/mime.py:63 src/sugar3/mime.py:66 src/sugar3/mime.py:68 ++msgid "Image" ++msgstr "" ++ ++#: ../src/sugar3/mime.py:68 src/sugar3/mime.py:71 src/sugar3/mime.py:73 ++msgid "Audio" ++msgstr "" ++ ++#: ../src/sugar3/mime.py:75 src/sugar3/mime.py:78 src/sugar3/mime.py:80 ++msgid "Video" ++msgstr "" ++ ++#: ../src/sugar3/mime.py:86 src/sugar3/mime.py:89 src/sugar3/mime.py:91 ++msgid "Link" ++msgstr "" ++ ++#: ../src/sugar3/mime.py:91 src/sugar3/mime.py:94 src/sugar3/mime.py:96 ++msgid "Bundle" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:48 src/sugar3/speech.py:56 ++msgid "Afrikaans" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:49 src/sugar3/speech.py:58 ++msgid "Aragonese" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:50 src/sugar3/speech.py:60 ++msgid "Bulgarian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:51 src/sugar3/speech.py:62 ++msgid "Bosnian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:52 src/sugar3/speech.py:64 ++msgid "Catalan" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:53 src/sugar3/speech.py:66 ++msgid "Czech" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:54 src/sugar3/speech.py:68 ++msgid "Welsh" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:55 src/sugar3/speech.py:70 ++msgid "Danish" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:56 src/sugar3/speech.py:72 ++msgid "German" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:57 src/sugar3/speech.py:74 ++msgid "Greek" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:58 ++msgid "Default" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:59 src/sugar3/speech.py:77 ++msgid "English Britain" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:60 src/sugar3/speech.py:79 ++msgid "English scottish" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:61 src/sugar3/speech.py:80 ++msgid "English-north" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:62 src/sugar3/speech.py:82 ++msgid "English_rp" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:63 src/sugar3/speech.py:84 ++msgid "English_wmids" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:64 src/sugar3/speech.py:86 ++msgid "English USA" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:65 ++msgid "English west indies" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:66 src/sugar3/speech.py:90 ++msgid "Esperanto" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:67 src/sugar3/speech.py:92 ++msgid "Spanish" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:68 src/sugar3/speech.py:93 ++msgid "Spanish latin american" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:69 src/sugar3/speech.py:95 ++msgid "Estonian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:70 src/sugar3/speech.py:97 ++msgid "Farsi" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:71 src/sugar3/speech.py:99 ++msgid "Farsi-pinglish" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:72 src/sugar3/speech.py:101 ++msgid "Finnish" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:73 src/sugar3/speech.py:103 ++msgid "French belgium" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:74 src/sugar3/speech.py:105 ++msgid "French" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:75 src/sugar3/speech.py:107 ++msgid "Irish-gaeilge" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:76 src/sugar3/speech.py:109 ++msgid "Greek-ancient" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:77 src/sugar3/speech.py:111 ++msgid "Hindi" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:78 src/sugar3/speech.py:113 ++msgid "Croatian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:79 src/sugar3/speech.py:115 ++msgid "Hungarian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:80 src/sugar3/speech.py:117 ++msgid "Armenian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:81 src/sugar3/speech.py:119 ++msgid "Armenian (west)" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:82 src/sugar3/speech.py:121 ++msgid "Indonesian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:83 src/sugar3/speech.py:123 ++msgid "Icelandic" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:84 src/sugar3/speech.py:125 ++msgid "Italian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:85 src/sugar3/speech.py:127 ++msgid "Lojban" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:86 src/sugar3/speech.py:129 ++msgid "Georgian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:87 src/sugar3/speech.py:131 ++msgid "Kannada" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:88 src/sugar3/speech.py:133 ++msgid "Kurdish" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:89 src/sugar3/speech.py:135 ++msgid "Latin" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:90 src/sugar3/speech.py:137 ++msgid "Lithuanian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:91 src/sugar3/speech.py:139 ++msgid "Latvian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:92 src/sugar3/speech.py:141 ++msgid "Macedonian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:93 src/sugar3/speech.py:143 ++msgid "Malayalam" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:94 src/sugar3/speech.py:145 ++msgid "Malay" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:95 src/sugar3/speech.py:147 ++msgid "Nepali" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:96 src/sugar3/speech.py:149 ++msgid "Dutch" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:97 src/sugar3/speech.py:151 ++msgid "Norwegian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:98 src/sugar3/speech.py:153 ++msgid "Punjabi" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:99 src/sugar3/speech.py:155 ++msgid "Polish" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:100 src/sugar3/speech.py:157 ++msgid "Portuguese (Brazil)" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:101 src/sugar3/speech.py:159 ++msgid "Portuguese (Portugal)" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:102 src/sugar3/speech.py:161 ++msgid "Romanian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:103 src/sugar3/speech.py:163 ++msgid "Russian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:104 src/sugar3/speech.py:165 ++msgid "Slovak" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:105 src/sugar3/speech.py:167 ++msgid "Albanian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:106 src/sugar3/speech.py:169 ++msgid "Serbian" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:107 src/sugar3/speech.py:171 ++msgid "Swedish" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:108 ++msgid "Swahili-test" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:109 src/sugar3/speech.py:175 ++msgid "Tamil" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:110 src/sugar3/speech.py:177 ++msgid "Turkish" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:111 src/sugar3/speech.py:179 ++msgid "Vietnam" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:112 src/sugar3/speech.py:180 ++msgid "Vietnam_hue" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:113 src/sugar3/speech.py:181 ++msgid "Vietnam_sgn" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:114 src/sugar3/speech.py:183 ++msgid "Mandarin" ++msgstr "" ++ ++#: ../src/sugar3/speech.py:115 src/sugar3/speech.py:185 ++msgid "Cantonese" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1170 src/sugar3/activity/activity.py:1165 ++msgid "Stop: name your journal entry" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1193 src/sugar3/activity/activity.py:1188 ++msgid "Cancel stop and continue the activity" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1230 src/sugar3/activity/activity.py:1225 ++msgid "Save new" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1231 src/sugar3/activity/activity.py:1226 ++msgid "Save a new journal entry" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1234 src/sugar3/activity/activity.py:1229 ++msgid "Save" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1235 src/sugar3/activity/activity.py:1230 ++msgid "Save into the old journal entry" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1241 src/sugar3/activity/activity.py:1236 ++msgid "Erase changes" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1242 src/sugar3/activity/activity.py:1237 ++msgid "Erase what you have done, and leave your old journal entry unchanged" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1245 src/sugar3/activity/activity.py:1240 ++msgid "Erase" ++msgstr "" ++ ++#: src/sugar3/activity/activity.py:1246 src/sugar3/activity/activity.py:1241 ++msgid "Erase what you have done, and avoid making a journal entry" ++msgstr "" ++ ++#: src/sugar3/graphics/popwindow.py:179 ++msgid "Close" ++msgstr "" ++ ++#: src/sugar3/speech.py:75 ++msgid "English" ++msgstr "" ++ ++#: src/sugar3/speech.py:88 ++msgid "English West Indies" ++msgstr "" ++ ++#: src/sugar3/speech.py:173 ++msgid "Swahili" ++msgstr "" +diff --git b/src/sugar3/.gitignore a/src/sugar3/.gitignore +new file mode 100644 +index 0000000..de24e35 +--- /dev/null ++++ a/src/sugar3/.gitignore +@@ -0,0 +1,4 @@ ++sugar-marshal.c ++sugar-marshal.h ++_sugarext.c ++_sugarext.c +diff --git b/src/sugar3/.license a/src/sugar3/.license +new file mode 100644 +index 0000000..6989ebe +--- /dev/null ++++ a/src/sugar3/.license +@@ -0,0 +1 @@ ++LGPL +diff --git b/src/sugar3/activity/Makefile.am a/src/sugar3/activity/Makefile.am +index e3cf05b..1f7a433 100644 +--- b/src/sugar3/activity/Makefile.am ++++ a/src/sugar3/activity/Makefile.am +@@ -7,7 +7,6 @@ sugar_PYTHON = \ + activityhandle.py \ + activityservice.py \ + bundlebuilder.py \ +- webkit1.py \ + webactivity.py \ + i18n.py \ + widgets.py +diff --git b/src/sugar3/activity/activity.py a/src/sugar3/activity/activity.py +index a459d64..4f7c9a2 100644 +--- b/src/sugar3/activity/activity.py ++++ a/src/sugar3/activity/activity.py +@@ -854,7 +854,7 @@ class Activity(Window, Gtk.Container): + is seeing at the time. + + Returns: +- str: image data in PNG format ++ bytes: image data in PNG format + + Activities may override this method, and return a string with + image data in PNG format with a width and height of +diff --git b/src/sugar3/activity/bundlebuilder.py a/src/sugar3/activity/bundlebuilder.py +index 9fd3839..cc32d60 100644 +--- b/src/sugar3/activity/bundlebuilder.py ++++ a/src/sugar3/activity/bundlebuilder.py +@@ -42,7 +42,7 @@ import logging + from glob import glob + from fnmatch import fnmatch + from six.moves.configparser import ConfigParser +-import xml.etree.cElementTree as ET ++import xml.etree.ElementTree as ET + from six.moves.html_parser import HTMLParser + + from sugar3 import env +@@ -629,9 +629,9 @@ def start(): + source_dir = os.path.abspath(os.path.dirname(sys.argv[0])) + config = Config(source_dir) + +- try: +- globals()['cmd_' + options.command](config, options) +- except (KeyError, IndexError): ++ if 'cmd_' + (options.command or '') in globals(): ++ globals()['cmd_' + (options.command or '')](config, options) ++ else: + parser.print_help() + + +diff --git b/src/sugar3/graphics/style.py a/src/sugar3/graphics/style.py +index 8dafd5b..4b34351 100644 +--- b/src/sugar3/graphics/style.py ++++ a/src/sugar3/graphics/style.py +@@ -155,7 +155,7 @@ def zoom(units): + Returns size of units pixels at current zoom level + + Args: +- units (int): size of item at full size ++ units (int or float): size of item at full size + ''' + return int(ZOOM_FACTOR * units) + +diff --git b/src/sugar3/presence/test_presence.txt a/src/sugar3/presence/test_presence.txt +new file mode 100644 +index 0000000..d0736a9 +--- /dev/null ++++ a/src/sugar3/presence/test_presence.txt +@@ -0,0 +1,26 @@ ++This is a test of presence. ++ ++To test this service we will start up a mock dbus library: ++ ++ >>> from sugar.testing import mockdbus ++ >>> import dbus ++ >>> pres_service = mockdbus.MockService( ++ ... 'org.laptop.Presence', '/org/laptop/Presence', name='pres') ++ >>> pres_service.install() ++ >>> pres_interface = dbus.Interface(pres_service, 'org.laptop.Presence') ++ ++Then we import the library (second, to make sure it connects to our ++mocked system, though the lazy instantiation in get_instance() should ++handle it): ++ ++ >>> from sugar.presence import PresenceService ++ >>> ps = PresenceService.get_instance() ++ >>> pres_interface.make_response('getServices', []) ++ >>> ps.get_services() ++ Called pres.org.laptop.Presence:getServices() ++ [] ++ >>> pres_interface.make_response('getBuddies', []) ++ >>> ps.get_buddies() ++ Called pres.org.laptop.Presence:getBuddies() ++ [] ++ +diff --git b/tests/data/mime.svg a/tests/data/mime.svg +new file mode 100644 +index 0000000..d4e6db3 +--- /dev/null ++++ a/tests/data/mime.svg +@@ -0,0 +1,3 @@ ++<?xml version="1.0" encoding="UTF-8" standalone="no"?> ++<svg xmlns="http://www.w3.org/2000/svg" version="2.0"> ++</svg> +diff --git b/tests/data/sample.activity/activity.py a/tests/data/sample.activity/activity.py +new file mode 100644 +index 0000000..ea4e983 +--- /dev/null ++++ a/tests/data/sample.activity/activity.py +@@ -0,0 +1,9 @@ ++from gettext import gettext as _ ++ ++from sugar3.activity import activity ++ ++ ++class SampleActivity(activity.Activity): ++ def __init__(self, handle): ++ activity.Activity.__init__(self, handle) ++ self._text = _("Text string") +diff --git b/tests/data/sample.activity/activity/activity-sample.svg a/tests/data/sample.activity/activity/activity-sample.svg +new file mode 100644 +index 0000000..8da7c63 +--- /dev/null ++++ a/tests/data/sample.activity/activity/activity-sample.svg +@@ -0,0 +1,26 @@ ++<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [ ++ <!ENTITY stroke_color "#010101"> ++ <!ENTITY fill_color "#FFFFFF"> ++]> ++<svg enable-background="new 0 0 55 55" height="55px" version="1.1" viewBox="0 0 55 55" width="55px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"> ++ <g display="block" id="activity-helloworld"> ++ <path d="M9.263,48.396c0.682,1.152,6.027,0.059,8.246-1.463 c2.102-1.432,3.207-2.596,4.336-2.596c1.133,0,12.54,0.92,20.935-5.715c7.225-5.707,9.773-13.788,4.52-21.437 c-5.252-7.644-13.832-9.08-20.878-8.56C16.806,9.342,4.224,16.91,4.677,28.313c0.264,6.711,3.357,9.143,4.922,10.703 c1.562,1.566,4.545,1.566,2.992,5.588C11.981,46.183,8.753,47.522,9.263,48.396z" display="inline" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5"/> ++ </g> ++ <circle cx="27.375" cy="27.5" r="19.903" ++ transform="matrix(0.6,0,0,0.6,10.95,11)" ++ id="circle4" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" display="inline" /> ++ <g transform="matrix(0.6,0,0,0.6,10.95,11)" id="g6" style="display:inline"> ++ <path d="m 27.376,7.598 c 0,0 -11.205,8.394 -11.205,19.976 0,11.583 11.205,19.829 11.205,19.829" ++ id="path8" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" /> ++ <path d="m 27.376,7.598 c 0,0 11.066,9.141 11.066,19.976 0,10.839 -11.066,19.829 -11.066,19.829" ++ id="path10" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" /> ++ <line x1="27.375999" x2="27.375999" y1="7.598" y2="47.402" ++ id="line12" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" /> ++ <line x1="27.375999" x2="27.375999" y1="7.598" y2="47.402" ++ id="line14" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" /> ++ <line x1="27.375999" x2="27.375999" y1="7.598" y2="47.402" ++ id="line16" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" /> ++ <line x1="7.4720001" x2="47.278" y1="27.5" y2="27.5" ++ id="line18" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" /> ++ </g> ++</svg> +diff --git b/tests/data/sample.activity/activity/activity.info a/tests/data/sample.activity/activity/activity.info +new file mode 100644 +index 0000000..820c07a +--- /dev/null ++++ a/tests/data/sample.activity/activity/activity.info +@@ -0,0 +1,7 @@ ++[Activity] ++name = Sample ++activity_version = 1 ++bundle_id = org.sugarlabs.Sample ++exec = sugar-activity3 activity.SampleActivity ++icon = activity-sample ++license = GPLv2+ +diff --git b/tests/data/sample.activity/po/Sample.pot a/tests/data/sample.activity/po/Sample.pot +new file mode 100644 +index 0000000..0cee357 +--- /dev/null ++++ a/tests/data/sample.activity/po/Sample.pot +@@ -0,0 +1,26 @@ ++# SOME DESCRIPTIVE TITLE. ++# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER ++# This file is distributed under the same license as the PACKAGE package. ++# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. ++# ++#, fuzzy ++msgid "" ++msgstr "" ++"Project-Id-Version: PACKAGE VERSION\n" ++"Report-Msgid-Bugs-To: \n" ++"POT-Creation-Date: 2012-12-06 20:10+0100\n" ++"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" ++"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" ++"Language-Team: LANGUAGE <LL@li.org>\n" ++"Language: \n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=CHARSET\n" ++"Content-Transfer-Encoding: 8bit\n" ++ ++#: activity/activity.info:2 ++msgid "Sample" ++msgstr "" ++ ++#: activity.py:8 ++msgid "Text string" ++msgstr "" +diff --git b/tests/data/sample.activity/po/es.po a/tests/data/sample.activity/po/es.po +new file mode 100644 +index 0000000..a1a6adb +--- /dev/null ++++ a/tests/data/sample.activity/po/es.po +@@ -0,0 +1,26 @@ ++# SOME DESCRIPTIVE TITLE. ++# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER ++# This file is distributed under the same license as the PACKAGE package. ++# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. ++# ++#, fuzzy ++msgid "" ++msgstr "" ++"Project-Id-Version: PACKAGE VERSION\n" ++"Report-Msgid-Bugs-To: \n" ++"POT-Creation-Date: 2012-12-06 20:10+0100\n" ++"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" ++"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" ++"Language-Team: LANGUAGE <LL@li.org>\n" ++"Language: \n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++ ++#: activity/activity.info:2 ++msgid "Sample" ++msgstr "" ++ ++#: activity.py:8 ++msgid "Text string" ++msgstr "" +diff --git b/tests/data/sample.activity/setup.py a/tests/data/sample.activity/setup.py +new file mode 100755 +index 0000000..191204b +--- /dev/null ++++ a/tests/data/sample.activity/setup.py +@@ -0,0 +1,5 @@ ++#!/usr/bin/env python3 ++ ++from sugar3.activity import bundlebuilder ++ ++bundlebuilder.start() +diff --git b/tests/data/sample.content/index.html a/tests/data/sample.content/index.html +new file mode 100644 +index 0000000..e69de29 +diff --git b/tests/data/sample.content/library/library.info a/tests/data/sample.content/library/library.info +new file mode 100644 +index 0000000..fb372df +--- /dev/null ++++ a/tests/data/sample.content/library/library.info +@@ -0,0 +1,10 @@ ++[Library] ++name = sample ++long_name = sample ++global_name = org.sugarlabs.samplecontent ++library_version = 1 ++host_version = 1 ++l10n = false ++locale = en ++license = CC-BY 2.0 ++category = media +diff --git b/tests/graphics/cellrendererprogress.py a/tests/graphics/cellrendererprogress.py +new file mode 100644 +index 0000000..94c1b9a +--- /dev/null ++++ a/tests/graphics/cellrendererprogress.py +@@ -0,0 +1,46 @@ ++""" ++ ++http://developer.gnome.org/gtk3/stable/GtkCellRendererProgress.html ++ ++""" ++ ++from gi.repository import Gtk ++ ++from sugar3.graphics import style ++ ++import common ++ ++ ++test = common.Test() ++test.show() ++ ++model = Gtk.ListStore(str, int, int) ++for item in [('one', 72, -1), ++ ('two', 50, -1), ++ ('three', 35, -1), ++ ('four', 0, 5)]: ++ model.append(item) ++ ++treeview = Gtk.TreeView() ++treeview.set_model(model) ++treeview.set_headers_visible(False) ++test.pack_start(treeview, True, True, 0) ++treeview.show() ++ ++col = Gtk.TreeViewColumn() ++treeview.append_column(col) ++ ++cell_text = Gtk.CellRendererText() ++cell_text.props.height = style.GRID_CELL_SIZE ++col.pack_start(cell_text, expand=False) ++col.add_attribute(cell_text, 'text', 0) ++ ++cell_progress = Gtk.CellRendererProgress() ++cell_progress.props.ypad = style.GRID_CELL_SIZE / 4 ++col.pack_start(cell_progress, expand=True) ++col.add_attribute(cell_progress, 'value', 1) ++col.add_attribute(cell_progress, 'pulse', 2) ++ ++ ++if __name__ == '__main__': ++ common.main(test) +diff --git b/tests/graphics/combobox.py a/tests/graphics/combobox.py +new file mode 100644 +index 0000000..0c329a0 +--- /dev/null ++++ a/tests/graphics/combobox.py +@@ -0,0 +1,24 @@ ++from gi.repository import Gtk ++ ++import common ++ ++ ++test = common.Test() ++test.show() ++ ++# test Gtk.ComboBox: ++ ++store = Gtk.ListStore(int, str) ++for i in range(100): ++ description = "combo test entry %d" % i ++ store.append([i, description]) ++ ++combobox = Gtk.ComboBox(model=store) ++cell = Gtk.CellRendererText() ++combobox.pack_start(cell, True) ++combobox.add_attribute(cell, 'text', 1) ++test.pack_start(combobox, True, True, 0) ++combobox.show() ++ ++if __name__ == '__main__': ++ common.main(test) +diff --git b/tests/graphics/progressicon.py a/tests/graphics/progressicon.py +new file mode 100644 +index 0000000..b756d2f +--- /dev/null ++++ a/tests/graphics/progressicon.py +@@ -0,0 +1,66 @@ ++# Copyright (C) 2013, One Laptop Per Child ++# ++# This library is free software; you can redistribute it and/or ++# modify it under the terms of the GNU Lesser General Public ++# License as published by the Free Software Foundation; either ++# version 2 of the License, or (at your option) any later version. ++# ++# This library is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++# Lesser General Public License for more details. ++# ++# You should have received a copy of the GNU Lesser General Public ++# License along with this library; if not, write to the ++# Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++# Boston, MA 02111-1307, USA. ++ ++""" ++Test the sugar3.graphics.progressicon.ProgressIcon widget. ++""" ++ ++ ++from gi.repository import GLib ++ ++from sugar3.graphics.progressicon import ProgressIcon ++from sugar3.graphics import style ++ ++import common ++ ++test = common.Test() ++test.show() ++ ++icon = ProgressIcon( ++ pixel_size=style.LARGE_ICON_SIZE, ++ icon_name='computer-xo', ++ stroke_color=style.COLOR_BUTTON_GREY.get_svg(), ++ fill_color=style.COLOR_WHITE.get_svg()) ++test.pack_start(icon, True, True, 0) ++icon.show() ++ ++icon2 = ProgressIcon( ++ pixel_size=style.LARGE_ICON_SIZE, ++ icon_name='computer-xo', ++ stroke_color=style.COLOR_BUTTON_GREY.get_svg(), ++ fill_color=style.COLOR_WHITE.get_svg(), ++ direction='horizontal') ++test.pack_start(icon2, True, True, 0) ++icon2.show() ++ ++progress = 0 ++ ++ ++def timeout_cb(): ++ global progress ++ progress += 0.05 ++ icon.update(progress) ++ icon2.update(progress) ++ if progress >= 1: ++ return False ++ return True ++ ++ ++GLib.timeout_add(50, timeout_cb) ++ ++if __name__ == '__main__': ++ common.main(test) +diff --git b/tests/test_bundle.py a/tests/test_bundle.py +new file mode 100644 +index 0000000..9d343d2 +--- /dev/null ++++ a/tests/test_bundle.py +@@ -0,0 +1,49 @@ ++# Copyright (C) 2013, One Laptop per Child ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ ++import os ++import unittest ++import subprocess ++ ++from sugar3.bundle.helpers import bundle_from_dir, bundle_from_archive ++from sugar3.bundle.activitybundle import ActivityBundle ++from sugar3.bundle.contentbundle import ContentBundle ++ ++tests_dir = os.path.dirname(__file__) ++data_dir = os.path.join(tests_dir, "data") ++SAMPLE_ACTIVITY_PATH = os.path.join(data_dir, 'sample.activity') ++SAMPLE_CONTENT_PATH = os.path.join(data_dir, 'sample.content') ++ ++ ++class TestBundle(unittest.TestCase): ++ def test_bundle_from_dir(self): ++ bundle = bundle_from_dir(SAMPLE_ACTIVITY_PATH) ++ self.assertIsInstance(bundle, ActivityBundle) ++ bundle = bundle_from_dir(SAMPLE_CONTENT_PATH) ++ self.assertIsInstance(bundle, ContentBundle) ++ ++ def test_activity_bundle_from_archive(self): ++ os.chdir(SAMPLE_ACTIVITY_PATH) ++ subprocess.check_call(["./setup.py", "dist_xo"]) ++ xo_path = os.path.join(".", "dist", "Sample-1.xo") ++ bundle = bundle_from_archive(xo_path) ++ self.assertIsInstance(bundle, ActivityBundle) ++ ++ def test_content_bundle_from_archive(self): ++ os.chdir(data_dir) ++ subprocess.check_call(["zip", "-r", "sample-1.xol", "sample.content"]) ++ bundle = bundle_from_archive("./sample-1.xol") ++ self.assertIsInstance(bundle, ContentBundle) +diff --git b/tests/test_bundlebuilder.py a/tests/test_bundlebuilder.py +new file mode 100644 +index 0000000..bda1af6 +--- /dev/null ++++ a/tests/test_bundlebuilder.py +@@ -0,0 +1,245 @@ ++# Copyright (C) 2012, Daniel Narvaez ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ ++import os ++import unittest ++import shutil ++import subprocess ++import tempfile ++import tarfile ++import zipfile ++ ++tests_dir = os.path.dirname(__file__) ++data_dir = os.path.join(tests_dir, "data") ++ ++ ++class TestGit(unittest.TestCase): ++ _source_files = ["activity.py", ++ "setup.py", ++ "po/Sample.pot", ++ "po/es.po", ++ "activity/activity.info", ++ "activity/activity-sample.svg"] ++ ++ _activity_locale_files = ["locale/es/activity.linfo"] ++ ++ _share_locale_files = ["locale/es/LC_MESSAGES/org.sugarlabs.Sample.mo"] ++ ++ def _get_all_locale_files(self): ++ expected = self._share_locale_files[:] ++ expected.extend(self._activity_locale_files) ++ return expected ++ ++ def _create_repo(self): ++ cwd = os.getcwd() ++ path = tempfile.mkdtemp() ++ os.chdir(path) ++ ++ subprocess.check_call(["git", "init"]) ++ subprocess.check_call(["git", "config", "user.name", "Test Test"]) ++ subprocess.check_call(["git", "config", "user.email", "test@test.org"]) ++ ++ for source in self._source_files: ++ source_path = os.path.join(data_dir, "sample.activity", source) ++ dest_path = os.path.join(path, source) ++ ++ try: ++ os.makedirs(os.path.dirname(dest_path)) ++ except OSError: ++ pass ++ ++ shutil.copyfile(source_path, dest_path) ++ shutil.copymode(source_path, dest_path) ++ ++ subprocess.check_call(["git", "add", source]) ++ ++ subprocess.check_call(["git", "commit", "-m", "Initial commit", "-a"]) ++ ++ os.chdir(cwd) ++ ++ return path ++ ++ def _strip_root_dir(self, paths): ++ return [path[path.find("/") + 1:] for path in paths] ++ ++ def _test_dist_xo(self, source_path, build_path): ++ cwd = os.getcwd() ++ os.chdir(build_path) ++ ++ setup_path = os.path.join(source_path, "setup.py") ++ subprocess.call([setup_path, "dist_xo"]) ++ ++ xo_path = os.path.join(build_path, "dist", "Sample-1.xo") ++ filenames = zipfile.ZipFile(xo_path).namelist() ++ ++ stripped_filenames = self._strip_root_dir(filenames) ++ expected = self._source_files[:] ++ expected.extend(self._get_all_locale_files()) ++ self.assertItemsEqual(stripped_filenames, expected) ++ ++ os.chdir(cwd) ++ ++ def _test_dist_source(self, source_path, build_path): ++ cwd = os.getcwd() ++ os.chdir(build_path) ++ ++ setup_path = os.path.join(source_path, "setup.py") ++ subprocess.call([setup_path, "dist_source"]) ++ ++ xo_path = os.path.join(build_path, "dist", "Sample-1.tar.bz2") ++ filenames = tarfile.open(name=xo_path, mode="r:bz2").getnames() ++ ++ stripped_filenames = self._strip_root_dir(filenames) ++ self.assertItemsEqual(stripped_filenames, self._source_files) ++ ++ os.chdir(cwd) ++ ++ def _test_build(self, source_path, build_path): ++ cwd = os.getcwd() ++ os.chdir(build_path) ++ ++ setup_path = os.path.join(source_path, "setup.py") ++ subprocess.call([setup_path, "build"]) ++ ++ locale_path = os.path.join(build_path, "locale") ++ ++ filenames = [] ++ for root, dirs, files in os.walk(locale_path): ++ rel_root = root[len(build_path) + 1:] ++ filenames.extend([os.path.join(rel_root, name) for name in files]) ++ ++ self.assertItemsEqual(filenames, self._get_all_locale_files()) ++ ++ os.chdir(cwd) ++ ++ def _test_dev(self, source_path, build_path): ++ activities_path = tempfile.mkdtemp() ++ ++ cwd = os.getcwd() ++ os.chdir(build_path) ++ ++ os.environ["SUGAR_ACTIVITIES_PATH"] = activities_path ++ ++ setup_path = os.path.join(source_path, "setup.py") ++ subprocess.call([setup_path, "dev"]) ++ ++ activity_py_path = os.path.join(activities_path, "Sample.activity", ++ "activity.py") ++ self.assertTrue(os.path.exists(activity_py_path)) ++ ++ os.chdir(cwd) ++ ++ def _test_genpot(self, source_path, build_path): ++ cwd = os.getcwd() ++ os.chdir(build_path) ++ ++ pot_path = os.path.join(source_path, "po", "Sample.pot") ++ os.unlink(pot_path) ++ ++ setup_path = os.path.join(source_path, "setup.py") ++ subprocess.call([setup_path, "genpot"]) ++ ++ self.assertTrue(os.path.exists(pot_path)) ++ ++ os.chdir(cwd) ++ ++ def _test_install(self, source_path, build_path): ++ install_path = tempfile.mkdtemp() ++ ++ cwd = os.getcwd() ++ os.chdir(build_path) ++ ++ setup_path = os.path.join(source_path, "setup.py") ++ subprocess.call([setup_path, "install", "--prefix", install_path]) ++ ++ filenames = [] ++ activity_dir = os.path.join(install_path, "share", ++ "sugar", "activities", "Sample.activity") ++ for root, dirs, files in os.walk(activity_dir): ++ rel_root = root[len(activity_dir) + 1:] ++ filenames.extend([os.path.join(rel_root, name) for name in files]) ++ ++ expected = self._source_files[:] ++ expected.extend(self._activity_locale_files) ++ ++ self.assertItemsEqual(filenames, expected) ++ ++ filenames = [] ++ share_dir = os.path.join(install_path, "share") ++ locale_dir = os.path.join(share_dir, "locale") ++ for root, dirs, files in os.walk(locale_dir): ++ rel_root = root[len(share_dir) + 1:] ++ for name in files: ++ if "org.sugarlabs.Sample" in name: ++ filenames.append(os.path.join(rel_root, name)) ++ ++ self.assertItemsEqual(filenames, self._share_locale_files) ++ ++ os.chdir(cwd) ++ ++ def test_dist_xo_in_source(self): ++ repo_path = self._create_repo() ++ self._test_dist_xo(repo_path, repo_path) ++ ++ def test_dist_xo_out_of_source(self): ++ repo_path = self._create_repo() ++ build_path = tempfile.mkdtemp() ++ self._test_dist_xo(repo_path, build_path) ++ ++ def test_dist_source_in_source(self): ++ repo_path = self._create_repo() ++ self._test_dist_source(repo_path, repo_path) ++ ++ def test_dist_source_out_of_source(self): ++ repo_path = self._create_repo() ++ build_path = tempfile.mkdtemp() ++ self._test_dist_source(repo_path, build_path) ++ ++ def test_install_in_source(self): ++ repo_path = self._create_repo() ++ self._test_install(repo_path, repo_path) ++ ++ def test_install_out_of_source(self): ++ repo_path = self._create_repo() ++ build_path = tempfile.mkdtemp() ++ self._test_install(repo_path, build_path) ++ ++ def test_build_in_source(self): ++ repo_path = self._create_repo() ++ self._test_build(repo_path, repo_path) ++ ++ def test_build_out_of_source(self): ++ repo_path = self._create_repo() ++ build_path = tempfile.mkdtemp() ++ self._test_build(repo_path, build_path) ++ ++ def test_dev_in_source(self): ++ repo_path = self._create_repo() ++ self._test_dev(repo_path, repo_path) ++ ++ def test_dev_out_of_source(self): ++ repo_path = self._create_repo() ++ build_path = tempfile.mkdtemp() ++ self._test_dev(repo_path, build_path) ++ ++ def test_genpot_in_source(self): ++ repo_path = self._create_repo() ++ self._test_genpot(repo_path, repo_path) ++ ++ def test_genpot_out_of_source(self): ++ repo_path = self._create_repo() ++ build_path = tempfile.mkdtemp() ++ self._test_genpot(repo_path, build_path) +diff --git b/tests/test_mime.py a/tests/test_mime.py +new file mode 100644 +index 0000000..9e478de +--- /dev/null ++++ a/tests/test_mime.py +@@ -0,0 +1,109 @@ ++#!/usr/bin/env python3 ++ ++# Copyright (C) 2006, Red Hat, Inc. ++# Copyright (C) 2007, One Laptop Per Child ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ ++import os ++import unittest ++ ++from sugar3 import mime ++ ++tests_dir = os.path.dirname(__file__) ++data_dir = os.path.join(tests_dir, "data") ++ ++ ++class TestMime(unittest.TestCase): ++ def test_split_uri_list(self): ++ self.assertSequenceEqual(mime.split_uri_list("http://one\nhttp://two"), ++ ("http://one", "http://two")) ++ ++ def test_get_mime_parents(self): ++ self.assertListEqual(mime.get_mime_parents("image/svg+xml"), ++ ["application/xml"]) ++ ++ # If the mime type don't have parents, should return a empty array ++ self.assertListEqual(mime.get_mime_parents("application/octet-stream"), ++ []) ++ ++ def test_get_for_file(self): ++ self.assertEqual(mime.get_for_file(os.path.join(data_dir, "mime.svg")), ++ 'image/svg+xml') ++ ++ def test_from_file_name(self): ++ self.assertEqual(mime.get_from_file_name('test.pdf'), ++ 'application/pdf') ++ ++ def test_choose_most_significant(self): ++ # Mozilla's text in dnd ++ mime_type = mime.choose_most_significant( ++ ['text/plain', 'text/_moz_htmlcontext', 'text/unicode', ++ 'text/html', 'text/_moz_htmlinfo']) ++ self.assertEqual(mime_type, 'text/html') ++ ++ # Mozilla's text in c&v ++ mime_type = mime.choose_most_significant( ++ ['text/_moz_htmlcontext', ++ 'STRING', ++ 'text/html', ++ 'text/_moz_htmlinfo', ++ 'text/x-moz-url-priv', ++ 'UTF8_STRING', ++ 'COMPOUND_TEXT']) ++ self.assertEqual(mime_type, 'text/html') ++ ++ # Mozilla gif in dnd ++ mime_type = mime.choose_most_significant( ++ ['application/x-moz-file-promise-url', ++ 'application/x-moz-file-promise-dest-filename', ++ 'text/_moz_htmlinfo', 'text/x-moz-url-desc', ++ 'text/_moz_htmlcontext', 'text/x-moz-url-data', ++ 'text/uri-list']) ++ self.assertEqual(mime_type, 'text/uri-list') ++ ++ # Mozilla url in dnd ++ mime_type = mime.choose_most_significant( ++ ['text/_moz_htmlcontext', ++ 'text/html', ++ 'text/_moz_htmlinfo', ++ '_NETSCAPE_URL', ++ 'text/x-moz-url', ++ 'text/x-moz-url-desc', ++ 'text/x-moz-url-data', ++ 'text/plain', ++ 'text/unicode']) ++ self.assertEqual(mime_type, 'text/x-moz-url') ++ ++ # Abiword text in dnd ++ mime_type = mime.choose_most_significant( ++ ['text/rtf', 'text/uri-list']) ++ self.assertEqual(mime_type, 'text/uri-list') ++ ++ # Abiword text in c&v ++ mime_type = mime.choose_most_significant( ++ ['UTF8_STRING', 'STRING', 'text/html', 'TEXT', 'text/rtf', ++ 'COMPOUND_TEXT', 'application/rtf', 'text/plain', ++ 'application/xhtml+xml']) ++ self.assertEqual(mime_type, 'application/rtf') ++ ++ # Abiword text in c&v ++ mime_type = mime.choose_most_significant( ++ ['GTK_TEXT_BUFFER_CONTENTS', ++ 'application/x-gtk-text-buffer-rich-text', ++ 'UTF8_STRING', 'COMPOUND_TEXT', 'TEXT', 'STRING', ++ 'text/plain;charset=utf-8', 'text/plain;charset=UTF-8', ++ 'text/plain']) ++ self.assertEqual(mime_type, 'text/plain') +diff --git b/tests/test_uitree.py a/tests/test_uitree.py +new file mode 100644 +index 0000000..b7c7da4 +--- /dev/null ++++ a/tests/test_uitree.py +@@ -0,0 +1,54 @@ ++# Copyright (C) 2012, Daniel Narvaez ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ ++import sys ++import subprocess ++import unittest ++ ++from sugar3.test import uitree ++ ++ ++class TestUITree(unittest.TestCase): ++ def test_tree(self): ++ process = subprocess.Popen(["python3", __file__, "show_window1"]) ++ ++ try: ++ root = uitree.get_root() ++ window = root.find_child(name="window1", role_name="frame") ++ button = window.find_child(name="button1", role_name="push button") ++ finally: ++ process.terminate() ++ ++ self.assertIsNotNone(button) ++ ++ ++def show_window1(): ++ from gi.repository import Gtk ++ ++ window = Gtk.Window() ++ window.set_title("window1") ++ ++ button = Gtk.Button(label="button1") ++ window.add(button) ++ button.show() ++ ++ window.show() ++ ++ Gtk.main() ++ ++ ++if __name__ == '__main__': ++ globals()[sys.argv[1]]() diff --git a/helpers/DATA/sugar/git-20201017.patch b/helpers/DATA/sugar/git-20201017.patch new file mode 100644 index 0000000000000000000000000000000000000000..8eda104ab3c82034dc9b0822186dd10888ca0df4 --- /dev/null +++ b/helpers/DATA/sugar/git-20201017.patch @@ -0,0 +1,10097 @@ +diff --git b/.flake8 a/.flake8 +new file mode 100644 +index 0000000..0146a5f +--- /dev/null ++++ a/.flake8 +@@ -0,0 +1,6 @@ ++[flake8] ++ ++# E402 module level import not at top of file ++# gi.require_version() is required before later imports ++ ++ignore = E402 +diff --git b/MAINTAINERS a/MAINTAINERS +new file mode 100644 +index 0000000..0f3a245 +--- /dev/null ++++ a/MAINTAINERS +@@ -0,0 +1,14 @@ ++Current maintainers ++------------------- ++ ++Aleksey Lim <alsroot@member.fsf.org> http://github.com/alsroot (Journal) ++Tomeu Vizoso <tomeu@sugarlabs.org> http://github.com/tomeuv ++Gonzalo Odiard http://github.com/godiard ++Martin Abente Lahaye <tch@sugarlabs.org>http://github.com/tchx84 ++Sam <sam@sam.today> http://github.com/samdroid-apps ++ ++ ++Past maintainers ++---------------- ++ ++Marco Pesenti Gritti <marcopg@sugarlabs.org> +diff --git b/autogen.sh a/autogen.sh +new file mode 100755 +index 0000000..739e7f8 +--- /dev/null ++++ a/autogen.sh +@@ -0,0 +1,15 @@ ++#!/bin/sh ++ ++test -n "${srcdir}" || srcdir=`dirname "$0"` ++test -n "${srcdir}" || srcdir="$(pwd)" ++ ++olddir="$(pwd)" ++cd "$srcdir" ++ ++mkdir -p m4 ++ ++intltoolize --force ++autoreconf -i ++ ++cd "$olddir" ++"$srcdir/configure" --enable-maintainer-mode "$@" +diff --git b/data/.gitignore a/data/.gitignore +new file mode 100644 +index 0000000..09d75cd +--- /dev/null ++++ a/data/.gitignore +@@ -0,0 +1,3 @@ ++*.gtkrc ++sugar.schemas ++org.sugarlabs.gschema.valid +diff --git b/docs/debian.md a/docs/debian.md +index 725b6a1..9183bb7 100644 +--- b/docs/debian.md ++++ a/docs/debian.md +@@ -18,7 +18,7 @@ sudo apt install sucrose lightdm + exec sudo reboot + ``` + +-- in the graphical login screen, change from the default X session to Sugar, ++- in the graphical login screen, [change from the default X session to Sugar](https://github.com/sugarlabs/sugar-docs/blob/master/src/sugar-logging-in.md), + - log in as the non-root user, which you will have created during install. + + Known bugs include; +@@ -41,7 +41,7 @@ sudo apt install sucrose lightdm + exec sudo reboot + ``` + +-- in the graphical login screen, change from the default X session to Sugar, ++- in the graphical login screen, [change from the default X session to Sugar](https://github.com/sugarlabs/sugar-docs/blob/master/src/sugar-logging-in.md), + - log in as your non-root user, created during install. + + Known bugs include; +@@ -61,10 +61,9 @@ Packaging + + Packaging of Sugar on Debian is done by a team: + +-- [pkg-sugar project](https://alioth.debian.org/projects/pkg-sugar/), ++- [pkg-sugar-team project](https://salsa.debian.org/pkg-sugar-team), + - [pkg-sugar-devel mailing list](https://lists.alioth.debian.org/mailman/listinfo/pkg-sugar-devel), +-- [pkg-sugar-commit mailing list](https://lists.alioth.debian.org/mailman/listinfo/pkg-sugar-commit), +-- [pkg-sugar git repositories](https://anonscm.debian.org/cgit/pkg-sugar/), ++- [pkg-sugar git repositories](https://salsa.debian.org/pkg-sugar-team/sugar) + - [package archive of Jonas Smedegaard](http://debian.jones.dk/pkg/sugar_/), + + Sucrose packages are usually updated in the unstable release. These packages migrate to the testing release after a while. You can see the current package versions [here](http://packages.debian.org/search?keywords=sugar&searchon=names&suite=all§ion=all). +diff --git b/docs/development-environment.md a/docs/development-environment.md +index eb1914d..7bd61a4 100644 +--- b/docs/development-environment.md ++++ a/docs/development-environment.md +@@ -26,7 +26,7 @@ See [downloads](http://people.sugarlabs.org/~quozl/sugar-live-build/) for the IS + + Once installed, Sugar Live Build can be used to make changes to Sugar, the toolkits, the demonstration activities, or to write new activities. + +-- changes to Sugar or the toolkits can be done by editing files in the module source trees in `/usr/src`, followed by `sudo make install` for each changed module. ++- changes to Sugar or the toolkits can be done by editing files in the module source trees in `/usr/src`, followed by per-module [install steps](https://github.com/sugarlabs/sugar-live-build/blob/master/src/config/hooks/normal/0900-sugar.hook.chroot#L42) for each changed module. See [issue 442](https://github.com/sugarlabs/sugar-toolkit-gtk3/issues/442) for details. + + - changes to demonstration activities can be done in the activity source trees in `/usr/src/sugar-activities`, and are immediately effective; just start a new instance of the activity in Sugar. + +@@ -49,7 +49,7 @@ Install the `sucrose` package; + + sudo apt install sucrose + +-Log out, then log in with the Sugar desktop selected. ++Log out, then [log in with the Sugar desktop selected](https://github.com/sugarlabs/sugar-docs/blob/master/src/sugar-logging-in.md). + + Once Sugar is installed, development of activities can begin. + +@@ -144,7 +144,7 @@ Clone the Browse and Terminal activities; + git clone https://github.com/sugarlabs/browse-activity.git Browse.activity + git clone https://github.com/sugarlabs/terminal-activity.git Terminal.activity + +-Log out and log in again with the Sugar desktop selected, or use the remote desktop feature described earlier on this page. ++Log out and [log in again with the Sugar desktop selected](https://github.com/sugarlabs/sugar-docs/blob/master/src/sugar-logging-in.md), or use the remote desktop feature described earlier on this page. + + After making changes in a Sugar module, repeat the `sudo make install` step, and log in again. + +diff --git b/docs/fedora.md a/docs/fedora.md +index 4b50b8b..af3c3e9 100644 +--- b/docs/fedora.md ++++ a/docs/fedora.md +@@ -12,7 +12,7 @@ Install Fedora. Then, in a Terminal, type: + + sudo dnf groupinstall sugar-desktop + +-Then restart your computer. At the *Sign in* select the *Sugar* desktop. ++Then restart your computer. At the *Sign in* select the *Sugar* desktop (Fedora uses GDM by default, tutorial to login to Sugar using GDM can be viewed in [the Sugar Docs](https://github.com/sugarlabs/sugar-docs/blob/master/src/sugar-logging-in.md)). + + Using Sugar with another Desktop Environment + -------------------------------------------- +diff --git b/docs/ubuntu.md a/docs/ubuntu.md +index 34c5644..26661cd 100644 +--- b/docs/ubuntu.md ++++ a/docs/ubuntu.md +@@ -14,7 +14,7 @@ Sugar 0.112 can be installed with the following commands: + sudo apt install sucrose + + - log out, +-- log in with the Sugar desktop selected, ++- [log in with the Sugar desktop selected](https://github.com/sugarlabs/sugar-docs/blob/master/src/sugar-logging-in.md), + + Known Problems: + +@@ -31,7 +31,7 @@ Sugar 0.112 is in the universe repository, and can be installed with the followi + sudo apt install sucrose + + - log out, +-- log in with the Sugar desktop selected, ++- [log in with the Sugar desktop selected](https://github.com/sugarlabs/sugar-docs/blob/master/src/sugar-logging-in.md), + + Ubuntu 18.04 (Bionic Beaver) and 18.10 (Cosmic Cuttlefish) + ------------------- +@@ -44,7 +44,7 @@ Sugar 0.112 is in the universe repository, and can be installed with the followi + sudo apt install sucrose + + - log out, +-- log in with the Sugar desktop selected, ++- [log in with the Sugar desktop selected](https://github.com/sugarlabs/sugar-docs/blob/master/src/sugar-logging-in.md), + - press the F3 key to switch to the home view, see below. + + Known problems +diff --git b/extensions/cpsection/language/view.py a/extensions/cpsection/language/view.py +index 39beda7..b2bb51e 100644 +--- b/extensions/cpsection/language/view.py ++++ a/extensions/cpsection/language/view.py +@@ -486,6 +486,7 @@ class BlackLabel(PaletteMenuItem): + self.set_label(text_label) + + def set_label(self, text_label): ++ text_label = GLib.markup_escape_text(text_label) + text = '<span foreground="%s">' % style.COLOR_BLACK.get_html() + \ + text_label + '</span>' + self.label.set_markup(text) +diff --git b/extensions/cpsection/modemconfiguration/model.py a/extensions/cpsection/modemconfiguration/model.py +index e2ba304..dfe0e20 100755 +--- b/extensions/cpsection/modemconfiguration/model.py ++++ a/extensions/cpsection/modemconfiguration/model.py +@@ -318,8 +318,6 @@ class ServiceProviders(object): + provider_name = self._settings.get_string(CONF_SP_PROVIDER) + if not provider_name: + provider_name = '' +- else: +- provider_name = provider_name.decode('utf-8') + + plan_idx = self._settings.get_int(CONF_SP_PLAN) or 0 + +diff --git b/po/en_US.po a/po/en_US.po +new file mode 100644 +index 0000000..06414dd +--- /dev/null ++++ a/po/en_US.po +@@ -0,0 +1,2016 @@ ++# SOME DESCRIPTIVE TITLE. ++# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER ++# This file is distributed under the same license as the PACKAGE package. ++# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. ++msgid "" ++msgstr "" ++"Project-Id-Version: PACKAGE VERSION\n" ++"Report-Msgid-Bugs-To: \n" ++"POT-Creation-Date: 2013-07-31 00:33-0400\n" ++"PO-Revision-Date: 2013-08-01 05:05+0200\n" ++"Last-Translator: Chris <cjl@laptop.org>\n" ++"Language-Team: LANGUAGE <LL@li.org>\n" ++"Language: en_US\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Pootle 2.0.5\n" ++ ++#: ../extensions/cpsection/aboutme/__init__.py:24 ++msgid "About Me" ++msgstr "About Me" ++ ++#: ../extensions/cpsection/aboutme/model.py:48 ++msgid "You must enter a name." ++msgstr "You must enter a name." ++ ++#: ../extensions/cpsection/aboutme/model.py:75 ++#, python-format ++msgid "stroke: color=%s hue=%s" ++msgstr "stroke: color=%s hue=%s" ++ ++#: ../extensions/cpsection/aboutme/model.py:78 ++#, python-format ++msgid "stroke: %s" ++msgstr "stroke: %s" ++ ++#: ../extensions/cpsection/aboutme/model.py:80 ++#, python-format ++msgid "fill: color=%s hue=%s" ++msgstr "fill: color=%s hue=%s" ++ ++#: ../extensions/cpsection/aboutme/model.py:82 ++#, python-format ++msgid "fill: %s" ++msgstr "fill: %s" ++ ++#: ../extensions/cpsection/aboutme/model.py:94 ++msgid "Error in specified color modifiers." ++msgstr "Error in specified color modifiers." ++ ++#: ../extensions/cpsection/aboutme/model.py:97 ++msgid "Error in specified colors." ++msgstr "Error in specified colors." ++ ++#: ../extensions/cpsection/aboutme/view.py:212 ++msgid "Click to change your color:" ++msgstr "Click to change your color:" ++ ++#: ../extensions/cpsection/aboutcomputer/__init__.py:21 ++msgid "About my Computer" ++msgstr "About my Computer" ++ ++#: ../extensions/cpsection/aboutcomputer/model.py:42 ++msgid "Not available" ++msgstr "Not available" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:60 ++msgid "Identity" ++msgstr "Identity" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:69 ++msgid "Serial Number:" ++msgstr "Serial Number:" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:91 ++msgid "Software" ++msgstr "Software" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:100 ++msgid "Build:" ++msgstr "Build:" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:115 ++msgid "Sugar:" ++msgstr "Sugar:" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:130 ++msgid "Firmware:" ++msgstr "Firmware:" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:145 ++msgid "Wireless Firmware:" ++msgstr "Wireless Firmware:" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:168 ++msgid "Copyright and License" ++msgstr "Copyright and License" ++ ++#. TRANS: The word "Sugar" should not be translated. ++#: ../extensions/cpsection/aboutcomputer/view.py:187 ++msgid "" ++"Sugar is the graphical user interface that you are looking at. Sugar is free " ++"software, covered by the GNU General Public License, and you are welcome to " ++"change it and/or distribute copies of it under certain conditions described " ++"therein." ++msgstr "" ++"Sugar is the graphical user interface that you are looking at. Sugar is free " ++"software, covered by the GNU General Public License, and you are welcome to " ++"change it and/or distribute copies of it under certain conditions described " ++"therein." ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:199 ++msgid "Full license:" ++msgstr "Full license:" ++ ++#: ../extensions/cpsection/background/__init__.py:21 ++msgid "Background" ++msgstr "Background" ++ ++#: ../extensions/cpsection/background/view.py:39 ++msgid "Select a background:" ++msgstr "Select a background:" ++ ++#: ../extensions/cpsection/background/view.py:46 ++msgid "Clear background" ++msgstr "Clear background" ++ ++#: ../extensions/cpsection/datetime/__init__.py:21 ++msgid "Date & Time" ++msgstr "Date & Time" ++ ++#: ../extensions/cpsection/datetime/model.py:92 ++msgid "Error timezone does not exist." ++msgstr "Error timezone does not exist." ++ ++#: ../extensions/cpsection/datetime/view.py:66 ../data/sugar.schemas.in.h:61 ++msgid "Timezone" ++msgstr "Timezone" ++ ++#: ../extensions/cpsection/frame/__init__.py:21 ++msgid "Frame" ++msgstr "Frame" ++ ++#: ../extensions/cpsection/frame/model.py:41 ++#: ../extensions/cpsection/frame/model.py:66 ++msgid "Value must be an integer." ++msgstr "Value must be an integer." ++ ++#: ../extensions/cpsection/frame/view.py:27 ++msgid "never" ++msgstr "never" ++ ++#: ../extensions/cpsection/frame/view.py:28 ++msgid "instantaneous" ++msgstr "instantaneous" ++ ++#: ../extensions/cpsection/frame/view.py:29 ++#, python-format ++msgid "%s seconds" ++msgstr "%s seconds" ++ ++#: ../extensions/cpsection/frame/view.py:54 ++msgid "Activation Delay" ++msgstr "Activation Delay" ++ ++#: ../extensions/cpsection/frame/view.py:78 ++msgid "Corner" ++msgstr "Corner" ++ ++#: ../extensions/cpsection/frame/view.py:114 ++msgid "Edge" ++msgstr "Edge" ++ ++#: ../extensions/cpsection/keyboard/__init__.py:21 ++#: ../extensions/cpsection/keyboard/view.py:38 ++msgid "Keyboard" ++msgstr "Keyboard" ++ ++#: ../extensions/cpsection/keyboard/view.py:240 ++msgid "Keyboard Model" ++msgstr "Keyboard Model" ++ ++#: ../extensions/cpsection/keyboard/view.py:301 ++msgid "Key(s) to change layout" ++msgstr "Key(s) to change layout" ++ ++#: ../extensions/cpsection/keyboard/view.py:369 ++msgid "Keyboard Layout(s)" ++msgstr "Keyboard Layout(s)" ++ ++#: ../extensions/cpsection/language/__init__.py:21 ++#: ../extensions/cpsection/language/view.py:33 ++msgid "Language" ++msgstr "Language" ++ ++#: ../extensions/cpsection/language/model.py:30 ++msgid "Could not access ~/.i18n. Create standard settings." ++msgstr "Could not access ~/.i18n. Create standard settings." ++ ++#: ../extensions/cpsection/language/model.py:129 ++#, python-format ++msgid "Language for code=%s could not be determined." ++msgstr "Language for code=%s could not be determined." ++ ++#: ../extensions/cpsection/language/model.py:152 ++#, python-format ++msgid "Sorry I do not speak '%s'." ++msgstr "Sorry I do not speak '%s'." ++ ++#: ../extensions/cpsection/language/view.py:57 ++msgid "" ++"Add languages in the order you prefer. If a translation is not available, " ++"the next in the list will be used." ++msgstr "" ++"Add languages in the order you prefer. If a translation is not available, " ++"the next in the list will be used." ++ ++#: ../extensions/cpsection/modemconfiguration/__init__.py:21 ++msgid "Modem Configuration" ++msgstr "Modem Configuration" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:94 ++msgid "" ++"You will need to provide the following information to set up a mobile " ++"broadband connection to a cellular (3G) network." ++msgstr "" ++"You will need to provide the following information to set up a mobile " ++"broadband connection to a cellular (3G) network." ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:117 ++msgid "Country:" ++msgstr "Country:" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:118 ++msgid "Provider:" ++msgstr "Provider:" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:119 ++msgid "Plan:" ++msgstr "Plan:" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:160 ++msgid "Username:" ++msgstr "Username:" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:167 ++msgid "Password:" ++msgstr "Password:" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:174 ++msgid "Number:" ++msgstr "Number:" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:181 ++msgid "Access Point Name (APN):" ++msgstr "Access Point Name (APN):" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:188 ++msgid "Personal Identity Number (PIN):" ++msgstr "Personal Identity Number (PIN):" ++ ++#: ../extensions/cpsection/modemconfiguration/model.py:161 ++#, python-format ++msgid "Plan #%s" ++msgstr "Plan #%s" ++ ++#: ../extensions/cpsection/modemconfiguration/model.py:291 ++#, python-format ++msgid "Provider %s" ++msgstr "Provider %s" ++ ++#: ../extensions/cpsection/network/__init__.py:21 ++#: ../extensions/cpsection/network/view.py:30 ++msgid "Network" ++msgstr "Network" ++ ++#: ../extensions/cpsection/network/model.py:73 ++msgid "State is unknown." ++msgstr "State is unknown." ++ ++#: ../extensions/cpsection/network/model.py:101 ++msgid "Error in specified radio argument use on/off." ++msgstr "Error in specified radio argument use on/off." ++ ++#: ../extensions/cpsection/network/model.py:152 ++msgid "Error in specified argument use 0/1." ++msgstr "Error in specified argument use 0/1." ++ ++#: ../extensions/cpsection/network/view.py:68 ++msgid "Wireless" ++msgstr "Wireless" ++ ++#: ../extensions/cpsection/network/view.py:77 ++msgid "Turn off the wireless radio to save battery life" ++msgstr "Turn off the wireless radio to save battery life" ++ ++#: ../extensions/cpsection/network/view.py:90 ++msgid "Radio" ++msgstr "Radio" ++ ++#: ../extensions/cpsection/network/view.py:106 ++msgid "Discard network history if you have trouble connecting to the network" ++msgstr "Discard network history if you have trouble connecting to the network" ++ ++#: ../extensions/cpsection/network/view.py:115 ++msgid "Discard network history" ++msgstr "Discard network history" ++ ++#: ../extensions/cpsection/network/view.py:131 ++msgid "Collaboration" ++msgstr "Collaboration" ++ ++#: ../extensions/cpsection/network/view.py:139 ++msgid "" ++"The server is the equivalent of what room you are in; people on the same " ++"server will be able to see each other, even when they aren't on the same " ++"network." ++msgstr "" ++"The server is the equivalent of what room you are in; people on the same " ++"server will be able to see each other, even when they aren't on the same " ++"network." ++ ++#: ../extensions/cpsection/network/view.py:149 ++msgid "Server:" ++msgstr "Server:" ++ ++#: ../extensions/cpsection/power/__init__.py:21 ++msgid "Power" ++msgstr "Power" ++ ++#: ../extensions/cpsection/power/model.py:90 ++msgid "Error in automatic pm argument, use on/off." ++msgstr "Error in automatic pm argument, use on/off." ++ ++#: ../extensions/cpsection/power/view.py:45 ++msgid "Power management" ++msgstr "Power management" ++ ++#: ../extensions/cpsection/power/view.py:55 ../data/sugar.schemas.in.h:5 ++msgid "Automatic power management (increases battery life)" ++msgstr "Automatic power management (increases battery life)" ++ ++#: ../extensions/cpsection/updater/__init__.py:21 ++msgid "Software Update" ++msgstr "Software Update" ++ ++#: ../extensions/cpsection/updater/view.py:65 ++msgid "" ++"Software updates correct errors, eliminate security vulnerabilities, and " ++"provide new features." ++msgstr "" ++"Software updates correct errors, eliminate security vulnerabilities, and " ++"provide new features." ++ ++#: ../extensions/cpsection/updater/view.py:79 ++msgid "Update in progress..." ++msgstr "Update in progress..." ++ ++#: ../extensions/cpsection/updater/view.py:106 ++msgid "Checking for updates..." ++msgstr "Checking for updates..." ++ ++#: ../extensions/cpsection/updater/view.py:108 ++msgid "Installing updates..." ++msgstr "Installing updates..." ++ ++#: ../extensions/cpsection/updater/view.py:137 ++#, python-format ++msgid "Checking %s..." ++msgstr "Checking %s..." ++ ++#: ../extensions/cpsection/updater/view.py:139 ++msgid "Looking for updates..." ++msgstr "Looking for updates..." ++ ++#: ../extensions/cpsection/updater/view.py:141 ++#, python-format ++msgid "Downloading %s..." ++msgstr "Downloading %s..." ++ ++#: ../extensions/cpsection/updater/view.py:143 ++#, python-format ++msgid "Updating %s..." ++msgstr "Updating %s..." ++ ++#: ../extensions/cpsection/updater/view.py:153 ++msgid "Your software is up-to-date" ++msgstr "Your software is up-to-date" ++ ++#: ../extensions/cpsection/updater/view.py:155 ++#, python-format ++msgid "You can install %s update" ++msgid_plural "You can install %s updates" ++msgstr[0] "You can install %s update" ++msgstr[1] "You can install %s updates" ++ ++#: ../extensions/cpsection/updater/view.py:184 ++#, python-format ++msgid "%s update was installed" ++msgid_plural "%s updates were installed" ++msgstr[0] "%s update was installed" ++msgstr[1] "%s updates were installed" ++ ++#: ../extensions/cpsection/updater/view.py:266 ++msgid "Install selected" ++msgstr "Install selected" ++ ++#: ../extensions/cpsection/updater/view.py:284 ++#, python-format ++msgid "Download size: %s" ++msgstr "Download size: %s" ++ ++#: ../extensions/cpsection/updater/view.py:373 ++#, python-format ++msgid "From version %(current)s to %(new)s (Size: %(size)s)" ++msgstr "From version %(current)s to %(new)s (Size: %(size)s)" ++ ++#: ../extensions/cpsection/updater/view.py:380 ++#, python-format ++msgid "Version %(version)s (Size: %(size)s)" ++msgstr "Version %(version)s (Size: %(size)s)" ++ ++#. TRANS: download size is 0 ++#: ../extensions/cpsection/updater/view.py:397 ++msgid "None" ++msgstr "None" ++ ++#. TRANS: download size of very small updates ++#: ../extensions/cpsection/updater/view.py:400 ++msgid "1 KB" ++msgstr "1 KB" ++ ++#. TRANS: download size of small updates, e.g. '250 KB' ++#: ../extensions/cpsection/updater/view.py:403 ++#, python-format ++msgid "%.0f KB" ++msgstr "%.0f KB" ++ ++#. TRANS: download size of updates, e.g. '2.3 MB' ++#: ../extensions/cpsection/updater/view.py:406 ++#, python-format ++msgid "%.1f MB" ++msgstr "%.1f MB" ++ ++#: ../extensions/cpsection/webaccount/__init__.py:24 ++msgid "Configure your Web Services" ++msgstr "Configure your Web Services" ++ ++#: ../extensions/cpsection/webaccount/view.py:42 ++#, python-format ++msgid "" ++"No web services are installed.\n" ++"Please visit %s for more details." ++msgstr "" ++"No web services are installed.\n" ++"Please visit %s for more details." ++ ++#: ../extensions/deviceicon/battery.py:71 ++msgid "My Battery" ++msgstr "My Battery" ++ ++#: ../extensions/deviceicon/battery.py:153 ++msgid "Removed" ++msgstr "Removed" ++ ++#: ../extensions/deviceicon/battery.py:156 ++msgid "Charging" ++msgstr "Charging" ++ ++#: ../extensions/deviceicon/battery.py:159 ++msgid "Very little power remaining" ++msgstr "Very little power remaining" ++ ++#. TRANS: do not translate %(hour)d:%(min).2d it is a variable, ++#. only translate the word "remaining" ++#: ../extensions/deviceicon/battery.py:166 ++#, python-format ++msgid "%(hour)d:%(min).2d remaining" ++msgstr "%(hour)d:%(min).2d remaining" ++ ++#: ../extensions/deviceicon/battery.py:169 ++msgid "Charged" ++msgstr "Charged" ++ ++#: ../extensions/deviceicon/frame.py:56 ++msgid "Show my keyboard" ++msgstr "Show my keyboard" ++ ++#: ../extensions/deviceicon/network.py:50 ++#, python-format ++msgid "IP address: %s" ++msgstr "IP address: %s" ++ ++#: ../extensions/deviceicon/network.py:82 ++#: ../extensions/deviceicon/network.py:298 ++#: ../src/jarabe/desktop/networkviews.py:135 ++#: ../src/jarabe/desktop/networkviews.py:509 ++msgid "Disconnect" ++msgstr "Disconnect" ++ ++#: ../extensions/deviceicon/network.py:107 ++#: ../extensions/deviceicon/network.py:290 ++#: ../src/jarabe/desktop/networkviews.py:251 ++#: ../src/jarabe/desktop/networkviews.py:551 ++#: ../src/jarabe/desktop/networkviews.py:693 ++msgid "Connecting..." ++msgstr "Connecting..." ++ ++#: ../extensions/deviceicon/network.py:112 ++#: ../extensions/deviceicon/network.py:180 ++#: ../src/jarabe/desktop/networkviews.py:258 ++#: ../src/jarabe/desktop/networkviews.py:557 ++#: ../src/jarabe/desktop/networkviews.py:699 ++msgid "Connected" ++msgstr "Connected" ++ ++#: ../extensions/deviceicon/network.py:125 ++msgid "No wireless connection" ++msgstr "No wireless connection" ++ ++#: ../extensions/deviceicon/network.py:139 ++msgid "Channel" ++msgstr "Channel" ++ ++#: ../extensions/deviceicon/network.py:154 ++msgid "Wired Network" ++msgstr "Wired Network" ++ ++#: ../extensions/deviceicon/network.py:183 ++msgid "Speed" ++msgstr "Speed" ++ ++#: ../extensions/deviceicon/network.py:208 ++msgid "Wireless modem" ++msgstr "Wireless modem" ++ ++#: ../extensions/deviceicon/network.py:276 ++msgid "Please wait..." ++msgstr "Please wait..." ++ ++#: ../extensions/deviceicon/network.py:281 ++#: ../src/jarabe/desktop/networkviews.py:129 ++#: ../src/jarabe/desktop/networkviews.py:503 ++#: ../src/jarabe/desktop/networkviews.py:644 ++msgid "Connect" ++msgstr "Connect" ++ ++#: ../extensions/deviceicon/network.py:282 ++msgid "Disconnected" ++msgstr "Disconnected" ++ ++#: ../extensions/deviceicon/network.py:289 ++#: ../src/jarabe/controlpanel/toolbar.py:121 ++#: ../src/jarabe/desktop/keydialog.py:101 ++#: ../src/jarabe/frame/activitiestray.py:625 ++#: ../src/jarabe/frame/activitiestray.py:746 ++#: ../src/jarabe/frame/activitiestray.py:778 ++#: ../src/jarabe/journal/expandedentry.py:159 ++#: ../src/jarabe/journal/journaltoolbox.py:480 ++#: ../src/jarabe/journal/palettes.py:159 ++msgid "Cancel" ++msgstr "Cancel" ++ ++#: ../extensions/deviceicon/network.py:328 ++msgid "Try connection again" ++msgstr "Try connection again" ++ ++#: ../extensions/deviceicon/network.py:331 ++#, python-format ++msgid "Error: %s" ++msgstr "Error: %s" ++ ++#: ../extensions/deviceicon/network.py:335 ++#, python-format ++msgid "Suggestion: %s" ++msgstr "Suggestion: %s" ++ ++#: ../extensions/deviceicon/network.py:344 ++#, python-format ++msgid "Connected for %s" ++msgstr "Connected for %s" ++ ++#: ../extensions/deviceicon/network.py:350 ++#: ../extensions/deviceicon/network.py:351 ++#, python-format ++msgid "%d KB" ++msgstr "%d KB" ++ ++#: ../extensions/deviceicon/network.py:356 ++msgid "Check your PIN/PUK configuration." ++msgstr "Check your PIN/PUK configuration." ++ ++#: ../extensions/deviceicon/network.py:359 ++msgid "Check your Access Point Name (APN) configuration" ++msgstr "Check your Access Point Name (APN) configuration" ++ ++#: ../extensions/deviceicon/network.py:363 ++msgid "Check the Number configuration." ++msgstr "Check the Number configuration." ++ ++#: ../extensions/deviceicon/network.py:365 ++msgid "Check your configuration." ++msgstr "Check your configuration." ++ ++#: ../extensions/deviceicon/network.py:621 ++msgid "Mesh Network" ++msgstr "Mesh Network" ++ ++#: ../extensions/deviceicon/network.py:668 ++#, python-format ++msgid "Mesh Network %s" ++msgstr "Mesh Network %s" ++ ++#: ../extensions/deviceicon/network.py:788 ++msgid "No GSM connection available." ++msgstr "No GSM connection available." ++ ++#: ../extensions/deviceicon/network.py:789 ++msgid "Create a connection in the control panel." ++msgstr "Create a connection in the control panel." ++ ++#: ../extensions/deviceicon/speech.py:52 ++msgid "Speech" ++msgstr "Speech" ++ ++#: ../extensions/deviceicon/speech.py:76 ++#: ../extensions/deviceicon/speech.py:150 ++#: ../extensions/deviceicon/speech.py:155 ++msgid "Say selected text" ++msgstr "Say selected text" ++ ++#: ../extensions/deviceicon/speech.py:83 ++msgid "Stop playback" ++msgstr "Stop playback" ++ ++#: ../extensions/deviceicon/speech.py:92 ++msgid "Pitch" ++msgstr "Pitch" ++ ++#: ../extensions/deviceicon/speech.py:107 ++msgid "Rate" ++msgstr "Rate" ++ ++#: ../extensions/deviceicon/speech.py:145 ++msgid "Pause playback" ++msgstr "Pause playback" ++ ++#: ../extensions/deviceicon/speaker.py:61 ++msgid "My Speakers" ++msgstr "My Speakers" ++ ++#: ../extensions/deviceicon/speaker.py:136 ++msgid "Unmute" ++msgstr "Unmute" ++ ++#: ../extensions/deviceicon/speaker.py:139 ++msgid "Mute" ++msgstr "Mute" ++ ++#: ../extensions/deviceicon/touchpad.py:38 ++msgid "finger" ++msgstr "finger" ++ ++#: ../extensions/deviceicon/touchpad.py:38 ++msgid "stylus" ++msgstr "stylus" ++ ++#: ../extensions/deviceicon/touchpad.py:64 ++msgid "My touchpad" ++msgstr "My touchpad" ++ ++#: ../extensions/deviceicon/volume.py:72 ../src/jarabe/view/palettes.py:184 ++msgid "Show contents" ++msgstr "Show contents" ++ ++#: ../extensions/globalkey/screenshot.py:61 ++msgid "Mesh" ++msgstr "Mesh" ++ ++#: ../extensions/globalkey/screenshot.py:63 ++#: ../src/jarabe/desktop/homewindow.py:221 ++#: ../src/jarabe/frame/zoomtoolbar.py:53 ++msgid "Group" ++msgstr "Group" ++ ++#: ../extensions/globalkey/screenshot.py:65 ++#: ../src/jarabe/desktop/homewindow.py:214 ++#: ../src/jarabe/desktop/viewtoolbar.py:73 ++#: ../src/jarabe/frame/zoomtoolbar.py:57 ++msgid "Home" ++msgstr "Home" ++ ++#: ../extensions/globalkey/screenshot.py:71 ++#: ../src/jarabe/frame/zoomtoolbar.py:62 ++msgid "Activity" ++msgstr "Activity" ++ ++#: ../extensions/globalkey/screenshot.py:74 ++msgid "Screenshot" ++msgstr "Screenshot" ++ ++#: ../extensions/globalkey/screenshot.py:76 ++#, python-format ++msgid "Screenshot of \"%s\"" ++msgstr "Screenshot of \"%s\"" ++ ++#: ../data/sugar.schemas.in.h:1 ++msgid "" ++"\"disabled\" to ask nick on initialization; \"system\" to reuse UNIX account " ++"long name." ++msgstr "" ++"\"disabled\" to ask nick on initialization; \"system\" to reuse UNIX account " ++"long name." ++ ++#: ../data/sugar.schemas.in.h:2 ++msgid "" ++"A unix timestamp (seconds since epoch) of the last successful activity " ++"update." ++msgstr "" ++"A unix timestamp (seconds since epoch) of the last successful activity " ++"update." ++ ++#: ../data/sugar.schemas.in.h:3 ++msgid "" ++"Activity update backend module, followed by a period, followed by the class " ++"name." ++msgstr "" ++"Activity update backend module, followed by a period, followed by the class " ++"name." ++ ++#: ../data/sugar.schemas.in.h:4 ++msgid "Activity update backend." ++msgstr "Activity update backend." ++ ++#: ../data/sugar.schemas.in.h:6 ++msgid "Automatic update frequency." ++msgstr "Automatic update frequency." ++ ++#: ../data/sugar.schemas.in.h:7 ++msgid "Backup URL" ++msgstr "Backup URL" ++ ++#: ../data/sugar.schemas.in.h:8 ++msgid "Bundle IDs of protected activities" ++msgstr "Bundle IDs of protected activities" ++ ++#: ../data/sugar.schemas.in.h:9 ++msgid "" ++"Color for the XO icon that is used throughout the desktop. The string is " ++"composed of the stroke color and fill color, format is that of rgb colors. " ++"Example: #AC32FF,#9A5200" ++msgstr "" ++"Color for the XO icon that is used throughout the desktop. The string is " ++"composed of the stroke color and fill color, format is that of rgb colors. " ++"Example: #AC32FF,#9A5200" ++ ++#: ../data/sugar.schemas.in.h:10 ++msgid "Corner Delay" ++msgstr "Corner Delay" ++ ++#: ../data/sugar.schemas.in.h:11 ++msgid "Default font face" ++msgstr "Default font face" ++ ++#: ../data/sugar.schemas.in.h:12 ++msgid "Default font size" ++msgstr "Default font size" ++ ++#: ../data/sugar.schemas.in.h:13 ++msgid "Default nick" ++msgstr "Default nick" ++ ++#: ../data/sugar.schemas.in.h:14 ++msgid "Delay for the activation of the frame using the corners." ++msgstr "Delay for the activation of the frame using the corners." ++ ++#: ../data/sugar.schemas.in.h:15 ++msgid "Delay for the activation of the frame using the edges." ++msgstr "Delay for the activation of the frame using the edges." ++ ++#: ../data/sugar.schemas.in.h:16 ++msgid "Edge Delay" ++msgstr "Edge Delay" ++ ++#: ../data/sugar.schemas.in.h:17 ++msgid "" ++"Extreme power management (disables wireless radio, increases battery life)" ++msgstr "" ++"Extreme power management (disables wireless radio, increases battery life)" ++ ++#: ../data/sugar.schemas.in.h:18 ++msgid "Favorites Layout" ++msgstr "Favorites Layout" ++ ++#: ../data/sugar.schemas.in.h:19 ++msgid "Favorites resume mode" ++msgstr "Favorites resume mode" ++ ++#: ../data/sugar.schemas.in.h:20 ++msgid "Font face that is used throughout the desktop." ++msgstr "Font face that is used throughout the desktop." ++ ++#: ../data/sugar.schemas.in.h:21 ++msgid "Font size that is used throughout the desktop." ++msgstr "Font size that is used throughout the desktop." ++ ++#: ../data/sugar.schemas.in.h:22 ++msgid "" ++"Frequency of automatic activity updates, measured in days. 0 means disabled." ++msgstr "" ++"Frequency of automatic activity updates, measured in days. 0 means disabled." ++ ++#: ../data/sugar.schemas.in.h:23 ++msgid "GSM network APN (DEPRECATED/UNUSED)" ++msgstr "GSM network APN (DEPRECATED/UNUSED)" ++ ++#: ../data/sugar.schemas.in.h:24 ++msgid "GSM network PIN (DEPRECATED/UNUSED)" ++msgstr "GSM network PIN (DEPRECATED/UNUSED)" ++ ++#: ../data/sugar.schemas.in.h:25 ++msgid "GSM network PUK (DEPRECATED/UNUSED)" ++msgstr "GSM network PUK (DEPRECATED/UNUSED)" ++ ++#: ../data/sugar.schemas.in.h:26 ++msgid "GSM network access point name configuration (DEPRECATED/UNUSED)" ++msgstr "GSM network access point name configuration (DEPRECATED/UNUSED)" ++ ++#: ../data/sugar.schemas.in.h:27 ++msgid "GSM network number (DEPRECATED/UNUSED)" ++msgstr "GSM network number (DEPRECATED/UNUSED)" ++ ++#: ../data/sugar.schemas.in.h:28 ++msgid "GSM network password (DEPRECATED/UNUSED)" ++msgstr "GSM network password (DEPRECATED/UNUSED)" ++ ++#: ../data/sugar.schemas.in.h:29 ++msgid "GSM network password configuration (DEPRECATED/UNUSED)" ++msgstr "GSM network password configuration (DEPRECATED/UNUSED)" ++ ++#: ../data/sugar.schemas.in.h:30 ++msgid "" ++"GSM network personal identification number configuration (DEPRECATED/UNUSED)" ++msgstr "" ++"GSM network personal identification number configuration (DEPRECATED/UNUSED)" ++ ++#: ../data/sugar.schemas.in.h:31 ++msgid "GSM network personal unlock key configuration (DEPRECATED/UNUSED)" ++msgstr "GSM network personal unlock key configuration (DEPRECATED/UNUSED)" ++ ++#: ../data/sugar.schemas.in.h:32 ++msgid "GSM network telephone number configuration (DEPRECATED/UNUSED)" ++msgstr "GSM network telephone number configuration (DEPRECATED/UNUSED)" ++ ++#: ../data/sugar.schemas.in.h:33 ++msgid "GSM network username (DEPRECATED/UNUSED)" ++msgstr "GSM network username (DEPRECATED/UNUSED)" ++ ++#: ../data/sugar.schemas.in.h:34 ++msgid "GSM network username configuration (DEPRECATED/UNUSED)" ++msgstr "GSM network username configuration (DEPRECATED/UNUSED)" ++ ++#: ../data/sugar.schemas.in.h:35 ++msgid "" ++"If TRUE, Sugar will make us searchable for the other users of the Jabber " ++"server." ++msgstr "" ++"If TRUE, Sugar will make us searchable for the other users of the Jabber " ++"server." ++ ++#: ../data/sugar.schemas.in.h:36 ++msgid "If TRUE, Sugar will show a \"Log out\" option." ++msgstr "If TRUE, Sugar will show a \"Log out\" option." ++ ++#: ../data/sugar.schemas.in.h:37 ++msgid "If TRUE, Sugar will show a \"Restart\" option." ++msgstr "If TRUE, Sugar will show a \"Restart\" option." ++ ++#: ../data/sugar.schemas.in.h:38 ++msgid "" ++"If TRUE, Sugar will show default Ad-hoc networks for channel 1,6 and 11. If " ++"Sugar sees no \"known\" network when it starts, it does autoconnect to an Ad-" ++"hoc network." ++msgstr "" ++"If TRUE, Sugar will show default Ad-hoc networks for channel 1,6 and 11. If " ++"Sugar sees no \"known\" network when it starts, it does autoconnect to an Ad-" ++"hoc network." ++ ++#: ../data/sugar.schemas.in.h:39 ++msgid "Jabber Server" ++msgstr "Jabber Server" ++ ++#: ../data/sugar.schemas.in.h:40 ++msgid "Keyboard layouts" ++msgstr "Keyboard layouts" ++ ++#: ../data/sugar.schemas.in.h:41 ++msgid "Keyboard model" ++msgstr "Keyboard model" ++ ++#: ../data/sugar.schemas.in.h:42 ++msgid "Keyboard options" ++msgstr "Keyboard options" ++ ++#: ../data/sugar.schemas.in.h:43 ++msgid "Layout of the favorites view." ++msgstr "Layout of the favorites view." ++ ++#: ../data/sugar.schemas.in.h:44 ++msgid "" ++"List of keyboard layouts. Each entry should be in the form layout(variant)" ++msgstr "" ++"List of keyboard layouts. Each entry should be in the form layout(variant)" ++ ++#: ../data/sugar.schemas.in.h:45 ++msgid "List of keyboard options." ++msgstr "List of keyboard options." ++ ++#: ../data/sugar.schemas.in.h:46 ++msgid "Microformat update URL." ++msgstr "Microformat update URL." ++ ++#: ../data/sugar.schemas.in.h:47 ++msgid "Pitch value for the speech sugar service" ++msgstr "Pitch value for the speech sugar service" ++ ++#: ../data/sugar.schemas.in.h:48 ++msgid "Pitch value used by the speech service in Sugar" ++msgstr "Pitch value used by the speech service in Sugar" ++ ++#: ../data/sugar.schemas.in.h:49 ++msgid "Power Automatic" ++msgstr "Power Automatic" ++ ++#: ../data/sugar.schemas.in.h:50 ++msgid "Power Extreme" ++msgstr "Power Extreme" ++ ++#: ../data/sugar.schemas.in.h:51 ++msgid "Publish to Gadget" ++msgstr "Publish to Gadget" ++ ++#: ../data/sugar.schemas.in.h:52 ++msgid "Rate value for the speech sugar service" ++msgstr "Rate value for the speech sugar service" ++ ++#: ../data/sugar.schemas.in.h:53 ++msgid "Rate value used by the speech service in Sugar" ++msgstr "Rate value used by the speech service in Sugar" ++ ++#: ../data/sugar.schemas.in.h:54 ++msgid "Setting for muting the sound device." ++msgstr "Setting for muting the sound device." ++ ++#: ../data/sugar.schemas.in.h:55 ++msgid "Show Log out" ++msgstr "Show Log out" ++ ++#: ../data/sugar.schemas.in.h:56 ++msgid "Show Restart" ++msgstr "Show Restart" ++ ++#: ../data/sugar.schemas.in.h:57 ++msgid "Show Sugar Ad-hoc networks" ++msgstr "Show Sugar Ad-hoc networks" ++ ++#: ../data/sugar.schemas.in.h:58 ++msgid "Sound Muted" ++msgstr "Sound Muted" ++ ++#: ../data/sugar.schemas.in.h:59 ++msgid "The keyboard model to be used" ++msgstr "The keyboard model to be used" ++ ++#: ../data/sugar.schemas.in.h:60 ++msgid "Timestamp of last activity update." ++msgstr "Timestamp of last activity update." ++ ++#: ../data/sugar.schemas.in.h:62 ++msgid "Timezone setting for the system." ++msgstr "Timezone setting for the system." ++ ++#: ../data/sugar.schemas.in.h:63 ++msgid "URL of the jabber server to use." ++msgstr "URL of the jabber server to use." ++ ++#: ../data/sugar.schemas.in.h:64 ++msgid "" ++"URL used by the microformat update backend for activity update information." ++msgstr "" ++"URL used by the microformat update backend for activity update information." ++ ++#: ../data/sugar.schemas.in.h:65 ++msgid "URL where the backup is saved to." ++msgstr "URL where the backup is saved to." ++ ++#: ../data/sugar.schemas.in.h:66 ++msgid "User Color" ++msgstr "User Color" ++ ++#: ../data/sugar.schemas.in.h:67 ++msgid "User Name" ++msgstr "User Name" ++ ++#: ../data/sugar.schemas.in.h:68 ++msgid "User name that is used throughout the desktop." ++msgstr "User name that is used throughout the desktop." ++ ++#: ../data/sugar.schemas.in.h:69 ++msgid "" ++"Users will not be allowed to erase these activities through the list view." ++msgstr "" ++"Users will not be allowed to erase these activities through the list view." ++ ++#: ../data/sugar.schemas.in.h:70 ++msgid "Volume Level" ++msgstr "Volume Level" ++ ++#: ../data/sugar.schemas.in.h:71 ++msgid "Volume level for the sound device." ++msgstr "Volume level for the sound device." ++ ++#: ../data/sugar.schemas.in.h:72 ++msgid "" ++"When in resume mode, clicking on a favorite icon will cause the last entry " ++"for that activity to be resumed." ++msgstr "" ++"When in resume mode, clicking on a favorite icon will cause the last entry " ++"for that activity to be resumed." ++ ++#: ../src/jarabe/controlpanel/cmd.py:28 ++#, python-format ++msgid "" ++"sugar-control-panel: WARNING, found more than one option with the same name: " ++"%s module: %r" ++msgstr "" ++"sugar-control-panel: WARNING, found more than one option with the same name: " ++"%s module: %r" ++ ++#: ../src/jarabe/controlpanel/cmd.py:30 ++#, python-format ++msgid "sugar-control-panel: key=%s not an available option" ++msgstr "sugar-control-panel: key=%s not an available option" ++ ++#: ../src/jarabe/controlpanel/cmd.py:31 ++#, python-format ++msgid "sugar-control-panel: %s" ++msgstr "sugar-control-panel: %s" ++ ++#. TRANS: Translators, there's a empty line at the end of this string, ++#. which must appear in the translated string (msgstr) as well. ++#: ../src/jarabe/controlpanel/cmd.py:38 ++msgid "" ++"Usage: sugar-control-panel [ option ] key [ args ... ] \n" ++" Control for the sugar environment. \n" ++" Options: \n" ++" -h show this help message and exit \n" ++" -l list all the available options \n" ++" -h key show information about this key \n" ++" -g key get the current value of the key \n" ++" -s key set the current value for the key \n" ++" -c key clear the current value for the key \n" ++" " ++msgstr "" ++"Usage: sugar-control-panel [ option ] key [ args ... ] \n" ++" Control for the sugar environment. \n" ++" Options: \n" ++" -h show this help message and exit \n" ++" -l list all the available options \n" ++" -h key show information about this key \n" ++" -g key get the current value of the key \n" ++" -s key set the current value for the key \n" ++" -c key clear the current value for the key \n" ++" " ++ ++#: ../src/jarabe/controlpanel/cmd.py:52 ++msgid "To apply your changes you have to restart Sugar.\n" ++msgstr "To apply your changes you have to restart Sugar.\n" ++ ++#: ../src/jarabe/controlpanel/gui.py:323 ../src/jarabe/journal/palettes.py:187 ++#: ../src/jarabe/journal/palettes.py:350 ../src/jarabe/journal/palettes.py:410 ++#: ../src/jarabe/journal/volumestoolbar.py:302 ++msgid "Warning" ++msgstr "Warning" ++ ++#: ../src/jarabe/controlpanel/gui.py:324 ++#: ../src/jarabe/controlpanel/sectionview.py:41 ++msgid "Changes require restart" ++msgstr "Changes require restart" ++ ++#: ../src/jarabe/controlpanel/gui.py:328 ++msgid "Cancel changes" ++msgstr "Cancel changes" ++ ++#: ../src/jarabe/controlpanel/gui.py:333 ++msgid "Later" ++msgstr "Later" ++ ++#: ../src/jarabe/controlpanel/gui.py:337 ++msgid "Restart now" ++msgstr "Restart now" ++ ++#: ../src/jarabe/controlpanel/toolbar.py:56 ++#: ../src/jarabe/desktop/viewtoolbar.py:129 ++#: ../src/jarabe/journal/journaltoolbox.py:89 ++#, python-format ++msgid "Search in %s" ++msgstr "Search in %s" ++ ++#: ../src/jarabe/controlpanel/toolbar.py:56 ++msgid "Settings" ++msgstr "Settings" ++ ++#: ../src/jarabe/controlpanel/toolbar.py:65 ../src/jarabe/intro/window.py:211 ++msgid "Done" ++msgstr "Done" ++ ++#: ../src/jarabe/controlpanel/toolbar.py:127 ++#: ../src/jarabe/desktop/favoritesview.py:374 ++#: ../src/jarabe/desktop/keydialog.py:105 ++msgid "Ok" ++msgstr "Ok" ++ ++#: ../src/jarabe/desktop/activitieslist.py:282 ++#, python-format ++msgid "Version %s" ++msgstr "Version %s" ++ ++#: ../src/jarabe/desktop/activitieslist.py:385 ++#: ../src/jarabe/journal/listview.py:475 ../src/jarabe/journal/iconview.py:299 ++msgid "Clear search" ++msgstr "Clear search" ++ ++#: ../src/jarabe/desktop/activitieslist.py:469 ++msgid "No matching activities" ++msgstr "No matching activities" ++ ++#: ../src/jarabe/desktop/activitieslist.py:505 ++msgid "Confirm erase" ++msgstr "Confirm erase" ++ ++#: ../src/jarabe/desktop/activitieslist.py:507 ++#, python-format ++msgid "Confirm erase: Do you want to permanently erase %s?" ++msgstr "Confirm erase: Do you want to permanently erase %s?" ++ ++#: ../src/jarabe/desktop/activitieslist.py:511 ++#: ../src/jarabe/frame/clipboardmenu.py:65 ++#: ../src/jarabe/view/viewsource.py:288 ++msgid "Keep" ++msgstr "Keep" ++ ++#: ../src/jarabe/desktop/activitieslist.py:514 ++#: ../src/jarabe/desktop/activitieslist.py:578 ++#: ../src/jarabe/journal/expandedentry.py:153 ++#: ../src/jarabe/journal/journaltoolbox.py:443 ++#: ../src/jarabe/journal/journaltoolbox.py:475 ++#: ../src/jarabe/journal/journaltoolbox.py:689 ++#: ../src/jarabe/journal/journaltoolbox.py:695 ++#: ../src/jarabe/journal/palettes.py:132 ../src/jarabe/journal/palettes.py:154 ++msgid "Erase" ++msgstr "Erase" ++ ++#: ../src/jarabe/desktop/activitieslist.py:594 ++msgid "Remove favorite" ++msgstr "Remove favorite" ++ ++#: ../src/jarabe/desktop/activitieslist.py:598 ++msgid "Make favorite" ++msgstr "Make favorite" ++ ++#. TRANS: label for the freeform layout in the favorites view ++#: ../src/jarabe/desktop/favoriteslayout.py:199 ++msgid "Freeform" ++msgstr "Freeform" ++ ++#. TRANS: label for the ring layout in the favorites view ++#: ../src/jarabe/desktop/favoriteslayout.py:295 ++msgid "Ring" ++msgstr "Ring" ++ ++#. TRANS: label for the spiral layout in the favorites view ++#: ../src/jarabe/desktop/favoriteslayout.py:459 ++msgid "Spiral" ++msgstr "Spiral" ++ ++#. TRANS: label for the box layout in the favorites view ++#: ../src/jarabe/desktop/favoriteslayout.py:527 ++msgid "Box" ++msgstr "Box" ++ ++#. TRANS: label for the box layout in the favorites view ++#: ../src/jarabe/desktop/favoriteslayout.py:570 ++msgid "Triangle" ++msgstr "Triangle" ++ ++#: ../src/jarabe/desktop/favoritesview.py:365 ++msgid "Registration Failed" ++msgstr "Registration Failed" ++ ++#: ../src/jarabe/desktop/favoritesview.py:368 ++msgid "Registration Successful" ++msgstr "Registration Successful" ++ ++#: ../src/jarabe/desktop/favoritesview.py:369 ++msgid "You are now registered with your school server." ++msgstr "You are now registered with your school server." ++ ++#: ../src/jarabe/desktop/favoritesview.py:653 ++msgid "Register" ++msgstr "Register" ++ ++#: ../src/jarabe/desktop/favoritesview.py:656 ++#: ../src/jarabe/desktop/favoritesview.py:672 ++msgid "Register again" ++msgstr "Register again" ++ ++#: ../src/jarabe/desktop/homewindow.py:228 ++#: ../src/jarabe/frame/zoomtoolbar.py:49 ++msgid "Neighborhood" ++msgstr "Neighborhood" ++ ++#: ../src/jarabe/desktop/keydialog.py:94 ++#, python-format ++msgid "" ++"A wireless encryption key is required for\n" ++" the wireless network '%s'." ++msgstr "" ++"A wireless encryption key is required for\n" ++" the wireless network '%s'." ++ ++#: ../src/jarabe/desktop/keydialog.py:150 ++msgid "Key Type:" ++msgstr "Key Type:" ++ ++#: ../src/jarabe/desktop/keydialog.py:170 ++msgid "Authentication Type:" ++msgstr "Authentication Type:" ++ ++#: ../src/jarabe/desktop/keydialog.py:233 ++msgid "WPA & WPA2 Personal" ++msgstr "WPA & WPA2 Personal" ++ ++#: ../src/jarabe/desktop/keydialog.py:242 ++msgid "Wireless Security:" ++msgstr "Wireless Security:" ++ ++#. TRANS: Action label for resuming an activity. ++#: ../src/jarabe/desktop/meshbox.py:82 ++#: ../src/jarabe/journal/journaltoolbox.py:548 ++#: ../src/jarabe/journal/palettes.py:77 ../src/jarabe/view/palettes.py:96 ++msgid "Resume" ++msgstr "Resume" ++ ++#: ../src/jarabe/desktop/meshbox.py:89 ++#: ../src/jarabe/frame/activitiestray.py:190 ++msgid "Join" ++msgstr "Join" ++ ++#: ../src/jarabe/desktop/networkviews.py:497 ++#, python-format ++msgid "Ad-hoc Network %d" ++msgstr "Ad-hoc Network %d" ++ ++#: ../src/jarabe/desktop/networkviews.py:639 ++#, python-format ++msgid "Mesh Network %d" ++msgstr "Mesh Network %d" ++ ++#: ../src/jarabe/desktop/schoolserver.py:144 ++msgid "Cannot connect to the server." ++msgstr "Cannot connect to the server." ++ ++#: ../src/jarabe/desktop/schoolserver.py:151 ++msgid "The server could not complete the request." ++msgstr "The server could not complete the request." ++ ++#: ../src/jarabe/desktop/viewtoolbar.py:95 ++msgid "List view" ++msgstr "List view" ++ ++#: ../src/jarabe/desktop/viewtoolbar.py:97 ++#: ../src/jarabe/desktop/viewtoolbar.py:195 ++#: ../src/jarabe/desktop/viewtoolbar.py:209 ++#, python-format ++#, python-format, ++msgid "<Ctrl>%d" ++msgstr "<Ctrl>%d" ++ ++#: ../src/jarabe/desktop/viewtoolbar.py:208 ++#, python-format ++#, python-format, ++msgid "Favorites view %d" ++msgstr "Favorites view %d" ++ ++#: ../src/jarabe/frame/activitiestray.py:195 ++#: ../src/jarabe/frame/activitiestray.py:593 ++msgid "Decline" ++msgstr "Decline" ++ ++#: ../src/jarabe/frame/activitiestray.py:534 ++#, python-format ++msgid "%dB" ++msgstr "%dB" ++ ++#: ../src/jarabe/frame/activitiestray.py:536 ++#, python-format ++msgid "%dKB" ++msgstr "%dKB" ++ ++#: ../src/jarabe/frame/activitiestray.py:538 ++#, python-format ++msgid "%dMB" ++msgstr "%dMB" ++ ++#. TRANS: file transfer, bytes transferred, e.g. 128 of 1024 ++#: ../src/jarabe/frame/activitiestray.py:556 ++#, python-format ++msgid "%s of %s" ++msgstr "%s of %s" ++ ++#: ../src/jarabe/frame/activitiestray.py:570 ++#, python-format ++#, python-format, ++msgid "Transfer from %s" ++msgstr "Transfer from %s" ++ ++#: ../src/jarabe/frame/activitiestray.py:585 ++msgid "Accept" ++msgstr "Accept" ++ ++#: ../src/jarabe/frame/activitiestray.py:653 ++#: ../src/jarabe/frame/activitiestray.py:666 ++#: ../src/jarabe/frame/activitiestray.py:807 ++msgid "Dismiss" ++msgstr "Dismiss" ++ ++#: ../src/jarabe/frame/activitiestray.py:680 ++msgid "The other participant canceled the file transfer" ++msgstr "The other participant canceled the file transfer" ++ ++#: ../src/jarabe/frame/activitiestray.py:730 ++#, python-format ++#, python-format, ++msgid "Transfer to %s" ++msgstr "Transfer to %s" ++ ++#: ../src/jarabe/frame/clipboardmenu.py:54 ++msgctxt "Clipboard" ++msgid "Remove" ++msgstr "Remove" ++ ++#: ../src/jarabe/frame/clipboardmenu.py:60 ++#: ../src/jarabe/frame/clipboardmenu.py:83 ++msgid "Open" ++msgstr "Open" ++ ++#: ../src/jarabe/frame/clipboardmenu.py:88 ++msgid "Open with" ++msgstr "Open with" ++ ++#: ../src/jarabe/frame/clipboardobject.py:50 ++#, python-format ++msgid "%s clipping" ++msgstr "%s clipping" ++ ++#: ../src/jarabe/frame/zoomtoolbar.py:50 ++msgid "F1" ++msgstr "F1" ++ ++#: ../src/jarabe/frame/zoomtoolbar.py:54 ++msgid "F2" ++msgstr "F2" ++ ++#: ../src/jarabe/frame/zoomtoolbar.py:58 ++msgid "F3" ++msgstr "F3" ++ ++#: ../src/jarabe/frame/zoomtoolbar.py:63 ++msgid "F4" ++msgstr "F4" ++ ++#: ../src/jarabe/intro/window.py:106 ++msgid "Name:" ++msgstr "Name:" ++ ++#: ../src/jarabe/intro/window.py:136 ++msgid "Click to change color:" ++msgstr "Click to change color:" ++ ++#: ../src/jarabe/intro/window.py:200 ../src/jarabe/journal/detailview.py:95 ++msgid "Back" ++msgstr "Back" ++ ++#: ../src/jarabe/intro/window.py:214 ++msgid "Next" ++msgstr "Next" ++ ++#: ../src/jarabe/journal/expandedentry.py:155 ++#: ../src/jarabe/journal/journaltoolbox.py:477 ++#: ../src/jarabe/journal/palettes.py:156 ++#, python-format ++msgid "Do you want to permanently erase \"%s\"?" ++msgstr "Do you want to permanently erase \"%s\"?" ++ ++#: ../src/jarabe/journal/expandedentry.py:296 ++#: ../src/jarabe/journal/listmodel.py:159 ../src/jarabe/journal/model.py:721 ++#: ../src/jarabe/journal/palettes.py:70 ../src/jarabe/journal/palettes.py:597 ++#: ../src/jarabe/journal/volumestoolbar.py:131 ++#: ../src/jarabe/journal/iconmodel.py:110 ++msgid "Untitled" ++msgstr "Untitled" ++ ++#: ../src/jarabe/journal/expandedentry.py:367 ++msgid "No preview" ++msgstr "No preview" ++ ++#: ../src/jarabe/journal/expandedentry.py:382 ++#, python-format ++msgid "Kind: %s" ++msgstr "Kind: %s" ++ ++#: ../src/jarabe/journal/expandedentry.py:382 ++#: ../src/jarabe/journal/listmodel.py:165 ++#: ../src/jarabe/journal/listmodel.py:173 ++msgid "Unknown" ++msgstr "Unknown" ++ ++#: ../src/jarabe/journal/expandedentry.py:383 ++#, python-format ++msgid "Date: %s" ++msgstr "Date: %s" ++ ++#: ../src/jarabe/journal/expandedentry.py:384 ++#, python-format ++msgid "Size: %s" ++msgstr "Size: %s" ++ ++#: ../src/jarabe/journal/expandedentry.py:411 ++#: ../src/jarabe/journal/misc.py:109 ++msgid "No date" ++msgstr "No date" ++ ++#: ../src/jarabe/journal/expandedentry.py:420 ++msgid "Participants:" ++msgstr "Participants:" ++ ++#: ../src/jarabe/journal/expandedentry.py:458 ++msgid "Description:" ++msgstr "Description:" ++ ++#: ../src/jarabe/journal/expandedentry.py:464 ++msgid "Tags:" ++msgstr "Tags:" ++ ++#: ../src/jarabe/journal/expandedentry.py:469 ++msgid "Comments:" ++msgstr "Comments:" ++ ++#: ../src/jarabe/journal/journalactivity.py:140 ++#: ../src/jarabe/journal/journaltoolbox.py:89 ++#: ../src/jarabe/journal/palettes.py:248 ++#: ../src/jarabe/journal/volumestoolbar.py:363 ++msgid "Journal" ++msgstr "Journal" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:98 ++msgid "Favorite entries" ++msgstr "Favorite entries" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:134 ++msgid "Anytime" ++msgstr "Anytime" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:136 ++msgid "Today" ++msgstr "Today" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:138 ++msgid "Since yesterday" ++msgstr "Since yesterday" ++ ++#. TRANS: Filter entries modified during the last 7 days. ++#: ../src/jarabe/journal/journaltoolbox.py:140 ++msgid "Past week" ++msgstr "Past week" ++ ++#. TRANS: Filter entries modified during the last 30 days. ++#: ../src/jarabe/journal/journaltoolbox.py:142 ++msgid "Past month" ++msgstr "Past month" ++ ++#. TRANS: Filter entries modified during the last 356 days. ++#: ../src/jarabe/journal/journaltoolbox.py:144 ++msgid "Past year" ++msgstr "Past year" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:151 ++msgid "Anyone" ++msgstr "Anyone" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:153 ++msgid "My friends" ++msgstr "My friends" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:154 ++msgid "My class" ++msgstr "My class" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:327 ++msgid "Anything" ++msgstr "Anything" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:419 ++#: ../src/jarabe/journal/palettes.py:99 ++msgid "Copy to" ++msgstr "Copy to" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:427 ++#: ../src/jarabe/journal/palettes.py:110 ../src/jarabe/view/viewsource.py:282 ++msgid "Duplicate" ++msgstr "Duplicate" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:433 ++msgid "Refresh" ++msgstr "Refresh" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:470 ++#: ../src/jarabe/journal/palettes.py:149 ../src/jarabe/journal/palettes.py:360 ++#: ../src/jarabe/journal/volumestoolbar.py:310 ++#, python-format ++msgid "Error while copying the entry. %s" ++msgstr "Error while copying the entry. %s" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:471 ++#: ../src/jarabe/journal/palettes.py:150 ../src/jarabe/journal/palettes.py:361 ++#: ../src/jarabe/journal/volumestoolbar.py:311 ++msgid "Error" ++msgstr "Error" ++ ++#. TRANS: Action label for starting an entry. ++#: ../src/jarabe/journal/journaltoolbox.py:551 ++#: ../src/jarabe/journal/palettes.py:80 ++msgid "Start" ++msgstr "Start" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:579 ++msgid "Sort by date modified" ++msgstr "Sort by date modified" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:580 ++msgid "Sort by date created" ++msgstr "Sort by date created" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:581 ++msgid "Sort by size" ++msgstr "Sort by size" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:590 ++msgid "Sort view" ++msgstr "Sort view" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:661 ++msgid "Deselect all" ++msgstr "Deselect all" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:674 ++msgid "Select all" ++msgstr "Select all" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:700 ++#, python-format ++msgid "Do you want to erase %d entry?" ++msgid_plural "Do you want to erase %d entries?" ++msgstr[0] "Do you want to erase %d entry?" ++msgstr[1] "Do you want to erase %d entries?" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:714 ++#: ../src/jarabe/journal/palettes.py:364 ++msgid "Copy" ++msgstr "Copy" ++ ++#. TRANS: Do not translate %(selected)d and %(total)d. ++#: ../src/jarabe/journal/journaltoolbox.py:759 ++#, python-format ++msgid "Selected %(selected)d of %(total)d" ++msgstr "Selected %(selected)d of %(total)d" ++ ++#: ../src/jarabe/journal/listview.py:387 ../src/jarabe/journal/iconview.py:211 ++msgid "Your Journal is empty" ++msgstr "Your Journal is empty" ++ ++#: ../src/jarabe/journal/listview.py:390 ../src/jarabe/journal/iconview.py:214 ++msgid "Your documents folder is empty" ++msgstr "Your documents folder is empty" ++ ++#: ../src/jarabe/journal/listview.py:392 ../src/jarabe/journal/iconview.py:216 ++msgid "The device is empty" ++msgstr "The device is empty" ++ ++#: ../src/jarabe/journal/listview.py:394 ../src/jarabe/journal/iconview.py:218 ++msgid "No matching entries" ++msgstr "No matching entries" ++ ++#: ../src/jarabe/journal/misc.py:252 ++#, python-format ++msgid "Older Version Of %s Activity" ++msgstr "Older Version Of %s Activity" ++ ++#: ../src/jarabe/journal/misc.py:253 ++#, python-format ++msgid "Do you want to downgrade to version %s" ++msgstr "Do you want to downgrade to version %s" ++ ++#: ../src/jarabe/journal/modalalert.py:65 ++msgid "Your Journal is full" ++msgstr "Your Journal is full" ++ ++#: ../src/jarabe/journal/modalalert.py:70 ++msgid "Please delete some old Journal entries to make space for new ones." ++msgstr "Please delete some old Journal entries to make space for new ones." ++ ++#: ../src/jarabe/journal/modalalert.py:84 ++msgid "Show Journal" ++msgstr "Show Journal" ++ ++#: ../src/jarabe/journal/objectchooser.py:170 ++msgid "Choose an object" ++msgstr "Choose an object" ++ ++#: ../src/jarabe/journal/objectchooser.py:175 ++#, python-format ++msgid "Choose an object to open with %s activity" ++msgstr "Choose an object to open with %s activity" ++ ++#: ../src/jarabe/journal/objectchooser.py:183 ++#: ../src/jarabe/view/viewsource.py:418 ++msgid "Close" ++msgstr "Close" ++ ++#: ../src/jarabe/journal/palettes.py:78 ++msgid "Resume with" ++msgstr "Resume with" ++ ++#: ../src/jarabe/journal/palettes.py:81 ++msgid "Start with" ++msgstr "Start with" ++ ++#: ../src/jarabe/journal/palettes.py:94 ../src/jarabe/journal/palettes.py:489 ++msgid "No activity to start entry" ++msgstr "No activity to start entry" ++ ++#: ../src/jarabe/journal/palettes.py:118 ++msgid "Send to" ++msgstr "Send to" ++ ++#: ../src/jarabe/journal/palettes.py:127 ++msgid "View Details" ++msgstr "View Details" ++ ++#: ../src/jarabe/journal/palettes.py:186 ++msgid "Entries without a file cannot be sent." ++msgstr "Entries without a file cannot be sent." ++ ++#: ../src/jarabe/journal/palettes.py:260 ++#: ../src/jarabe/journal/volumestoolbar.py:211 ++msgid "Documents" ++msgstr "Documents" ++ ++#: ../src/jarabe/journal/palettes.py:349 ../src/jarabe/journal/palettes.py:409 ++#: ../src/jarabe/journal/volumestoolbar.py:301 ++msgid "Entries without a file cannot be copied." ++msgstr "Entries without a file cannot be copied." ++ ++#: ../src/jarabe/journal/palettes.py:369 ++#, python-format ++msgid "Do you want to copy %d entry?" ++msgid_plural "Do you want to copy %d entries?" ++msgstr[0] "Do you want to copy %d entry?" ++msgstr[1] "Do you want to copy %d entries?" ++ ++#: ../src/jarabe/journal/palettes.py:394 ++msgid "Clipboard" ++msgstr "Clipboard" ++ ++#: ../src/jarabe/journal/palettes.py:454 ++msgid "No friends present" ++msgstr "No friends present" ++ ++#: ../src/jarabe/journal/palettes.py:459 ++msgid "No valid connection found" ++msgstr "No valid connection found" ++ ++#: ../src/jarabe/journal/palettes.py:487 ++msgid "No activity to resume entry" ++msgstr "No activity to resume entry" ++ ++#: ../src/jarabe/journal/palettes.py:556 ../src/jarabe/view/palettes.py:110 ++msgid "Stop" ++msgstr "Stop" ++ ++#: ../src/jarabe/journal/palettes.py:561 ++msgid "Continue" ++msgstr "Continue" ++ ++#: ../src/jarabe/journal/palettes.py:598 ++#, python-format ++msgid "%(index)d of %(total)d : %(object_title)s" ++msgstr "%(index)d of %(total)d : %(object_title)s" ++ ++#: ../src/jarabe/journal/volumestoolbar.py:386 ++#: ../src/jarabe/view/palettes.py:225 ../src/jarabe/view/palettes.py:292 ++#, python-format ++msgid "%(free_space)d MB Free" ++msgstr "%(free_space)d MB Free" ++ ++#: ../src/jarabe/model/network.py:214 ++msgid "The reason for the device state change is unknown." ++msgstr "The reason for the device state change is unknown." ++ ++#: ../src/jarabe/model/network.py:216 ++msgid "The state change is normal." ++msgstr "The state change is normal." ++ ++#: ../src/jarabe/model/network.py:218 ++msgid "The device is now managed." ++msgstr "The device is now managed." ++ ++#: ../src/jarabe/model/network.py:220 ++msgid "The device is no longer managed." ++msgstr "The device is no longer managed." ++ ++#: ../src/jarabe/model/network.py:222 ++msgid "The device could not be readied for configuration." ++msgstr "The device could not be readied for configuration." ++ ++#: ../src/jarabe/model/network.py:224 ++msgid "" ++"IP configuration could not be reserved (no available address, timeout, etc)." ++msgstr "" ++"IP configuration could not be reserved (no available address, timeout, etc)." ++ ++#: ../src/jarabe/model/network.py:227 ++msgid "The IP configuration is no longer valid." ++msgstr "The IP configuration is no longer valid." ++ ++#: ../src/jarabe/model/network.py:229 ++msgid "Secrets were required, but not provided." ++msgstr "Secrets were required, but not provided." ++ ++#: ../src/jarabe/model/network.py:231 ++msgid "" ++"The 802.1X supplicant disconnected from the access point or authentication " ++"server." ++msgstr "" ++"The 802.1X supplicant disconnected from the access point or authentication " ++"server." ++ ++#: ../src/jarabe/model/network.py:234 ++msgid "Configuration of the 802.1X supplicant failed." ++msgstr "Configuration of the 802.1X supplicant failed." ++ ++#: ../src/jarabe/model/network.py:236 ++msgid "The 802.1X supplicant quit or failed unexpectedly." ++msgstr "The 802.1X supplicant quit or failed unexpectedly." ++ ++#: ../src/jarabe/model/network.py:238 ++msgid "The 802.1X supplicant took too long to authenticate." ++msgstr "The 802.1X supplicant took too long to authenticate." ++ ++#: ../src/jarabe/model/network.py:240 ++msgid "The PPP service failed to start within the allowed time." ++msgstr "The PPP service failed to start within the allowed time." ++ ++#: ../src/jarabe/model/network.py:242 ++msgid "The PPP service disconnected unexpectedly." ++msgstr "The PPP service disconnected unexpectedly." ++ ++#: ../src/jarabe/model/network.py:244 ++msgid "The PPP service quit or failed unexpectedly." ++msgstr "The PPP service quit or failed unexpectedly." ++ ++#: ../src/jarabe/model/network.py:246 ++msgid "The DHCP service failed to start within the allowed time." ++msgstr "The DHCP service failed to start within the allowed time." ++ ++#: ../src/jarabe/model/network.py:248 ++msgid "The DHCP service reported an unexpected error." ++msgstr "The DHCP service reported an unexpected error." ++ ++#: ../src/jarabe/model/network.py:250 ++msgid "The DHCP service quit or failed unexpectedly." ++msgstr "The DHCP service quit or failed unexpectedly." ++ ++#: ../src/jarabe/model/network.py:252 ++msgid "The shared connection service failed to start." ++msgstr "The shared connection service failed to start." ++ ++#: ../src/jarabe/model/network.py:254 ++msgid "The shared connection service quit or failed unexpectedly." ++msgstr "The shared connection service quit or failed unexpectedly." ++ ++#: ../src/jarabe/model/network.py:257 ++msgid "The AutoIP service failed to start." ++msgstr "The AutoIP service failed to start." ++ ++#: ../src/jarabe/model/network.py:259 ++msgid "The AutoIP service reported an unexpected error." ++msgstr "The AutoIP service reported an unexpected error." ++ ++#: ../src/jarabe/model/network.py:261 ++msgid "The AutoIP service quit or failed unexpectedly." ++msgstr "The AutoIP service quit or failed unexpectedly." ++ ++#: ../src/jarabe/model/network.py:263 ++msgid "Dialing failed because the line was busy." ++msgstr "Dialing failed because the line was busy." ++ ++#: ../src/jarabe/model/network.py:265 ++msgid "Dialing failed because there was no dial tone." ++msgstr "Dialing failed because there was no dial tone." ++ ++#: ../src/jarabe/model/network.py:267 ++msgid "Dialing failed because there was no carrier." ++msgstr "Dialing failed because there was no carrier." ++ ++#: ../src/jarabe/model/network.py:269 ++msgid "Dialing timed out." ++msgstr "Dialing timed out." ++ ++#: ../src/jarabe/model/network.py:271 ++msgid "Dialing failed." ++msgstr "Dialing failed." ++ ++#: ../src/jarabe/model/network.py:273 ++msgid "Modem initialization failed." ++msgstr "Modem initialization failed." ++ ++#: ../src/jarabe/model/network.py:275 ++msgid "Failed to select the specified GSM APN" ++msgstr "Failed to select the specified GSM APN" ++ ++#: ../src/jarabe/model/network.py:277 ++msgid "Not searching for networks." ++msgstr "Not searching for networks." ++ ++#: ../src/jarabe/model/network.py:279 ++msgid "Network registration was denied." ++msgstr "Network registration was denied." ++ ++#: ../src/jarabe/model/network.py:281 ++msgid "Network registration timed out." ++msgstr "Network registration timed out." ++ ++#: ../src/jarabe/model/network.py:283 ++msgid "Failed to register with the requested GSM network." ++msgstr "Failed to register with the requested GSM network." ++ ++#: ../src/jarabe/model/network.py:285 ++msgid "PIN check failed." ++msgstr "PIN check failed." ++ ++#: ../src/jarabe/model/network.py:287 ++msgid "Necessary firmware for the device may be missing." ++msgstr "Necessary firmware for the device may be missing." ++ ++#: ../src/jarabe/model/network.py:289 ++msgid "The device was removed." ++msgstr "The device was removed." ++ ++#: ../src/jarabe/model/network.py:291 ++msgid "NetworkManager went to sleep." ++msgstr "NetworkManager went to sleep." ++ ++#: ../src/jarabe/model/network.py:293 ++msgid "The device's active connection was removed or disappeared." ++msgstr "The device's active connection was removed or disappeared." ++ ++#: ../src/jarabe/model/network.py:296 ++msgid "A user or client requested the disconnection." ++msgstr "A user or client requested the disconnection." ++ ++#: ../src/jarabe/model/network.py:298 ++msgid "The device's carrier/link changed." ++msgstr "The device's carrier/link changed." ++ ++#: ../src/jarabe/model/network.py:300 ++msgid "The device's existing connection was assumed." ++msgstr "The device's existing connection was assumed." ++ ++#: ../src/jarabe/model/network.py:302 ++msgid "The supplicant is now available." ++msgstr "The supplicant is now available." ++ ++#: ../src/jarabe/model/network.py:304 ++msgid "The modem could not be found." ++msgstr "The modem could not be found." ++ ++#: ../src/jarabe/model/network.py:306 ++msgid "The Bluetooth connection failed or timed out." ++msgstr "The Bluetooth connection failed or timed out." ++ ++#: ../src/jarabe/model/network.py:308 ++msgid "Unused." ++msgstr "Unused." ++ ++#: ../src/jarabe/view/buddymenu.py:72 ++msgid "Remove friend" ++msgstr "Remove friend" ++ ++#: ../src/jarabe/view/buddymenu.py:75 ++msgid "Make friend" ++msgstr "Make friend" ++ ++#: ../src/jarabe/view/buddymenu.py:91 ++msgid "Shutdown" ++msgstr "Shutdown" ++ ++#: ../src/jarabe/view/buddymenu.py:98 ++msgid "Restart" ++msgstr "Restart" ++ ++#: ../src/jarabe/view/buddymenu.py:104 ++msgid "Logout" ++msgstr "Logout" ++ ++#: ../src/jarabe/view/buddymenu.py:109 ++msgid "My Settings" ++msgstr "My Settings" ++ ++#: ../src/jarabe/view/buddymenu.py:149 ++#, python-format ++msgid "Invite to %s" ++msgstr "Invite to %s" ++ ++#: ../src/jarabe/view/launcher.py:144 ++#, python-format ++msgid "<b>%s</b> failed to start." ++msgstr "<b>%s</b> failed to start." ++ ++#: ../src/jarabe/view/palettes.py:51 ++msgid "Starting..." ++msgstr "Starting..." ++ ++#: ../src/jarabe/view/palettes.py:61 ++msgid "Activity failed to start" ++msgstr "Activity failed to start" ++ ++#. TODO: share-with, keep ++#: ../src/jarabe/view/palettes.py:102 ++msgid "View Source" ++msgstr "View Source" ++ ++#: ../src/jarabe/view/palettes.py:153 ++msgid "Start new" ++msgstr "Start new" ++ ++#: ../src/jarabe/view/palettes.py:241 ++msgctxt "Volume" ++msgid "Remove" ++msgstr "Remove" ++ ++#: ../src/jarabe/view/viewsource.py:271 ++msgid "Instance Source" ++msgstr "Instance Source" ++ ++#: ../src/jarabe/view/viewsource.py:320 ++msgid "Source" ++msgstr "Source" ++ ++#: ../src/jarabe/view/viewsource.py:382 ++msgid "Activity Bundle Source" ++msgstr "Activity Bundle Source" ++ ++#: ../src/jarabe/view/viewsource.py:401 ++msgid "Sugar Toolkit Source" ++msgstr "Sugar Toolkit Source" ++ ++#: ../src/jarabe/view/viewsource.py:408 ++#, python-format ++#, python-format, ++msgid "View source: %s" ++msgstr "View source: %s" ++ ++#: ../src/jarabe/view/viewsource.py:409 ++#, python-format ++msgid "View source: %r" ++msgstr "View source: %r" ++ ++#~ msgid "<Ctrl>1" ++#~ msgstr "<Ctrl>1" ++ ++#~ msgid "Update your activities to ensure compatibility with your new software" ++#~ msgstr "Update your activities to ensure compatibility with your new software" ++ ++#~ msgid "Check now" ++#~ msgstr "Check now" ++ ++#~ msgid "Sugar in a window" ++#~ msgstr "Sugar in a window" ++ ++#~ msgid "Software update" ++#~ msgstr "Software update" ++ ++#~ msgid "Search" ++#~ msgstr "Search" ++ ++#~ msgid "Additional directories which can contain updated translations." ++#~ msgstr "Additional directories which can contain updated translations." ++ ++#~ msgid "Directory to search for translations" ++#~ msgstr "Directory to search for translations" ++ ++#~ msgid "Error in extreme pm argument, use on/off." ++#~ msgstr "Error in extreme pm argument, use on/off." +diff --git b/po/kab.po a/po/kab.po +new file mode 100644 +index 0000000..66c4bee +--- /dev/null ++++ a/po/kab.po +@@ -0,0 +1,2414 @@ ++# SOME DESCRIPTIVE TITLE. ++# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER ++# This file is distributed under the same license as the PACKAGE package. ++# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. ++msgid "" ++msgstr "" ++"Project-Id-Version: PACKAGE VERSION\n" ++"Report-Msgid-Bugs-To: \n" ++"POT-Creation-Date: 2016-01-30 14:24+0000\n" ++"PO-Revision-Date: 2017-10-15 20:28+0000\n" ++"Last-Translator: Yacine-Bouklif <yacine_tizi2003@yahoo.fr>\n" ++"Language-Team: LANGUAGE <LL@li.org>\n" ++"Language: kab\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=2; plural=(n != 1);\n" ++"X-Generator: Pootle 2.5.1.1\n" ++"X-POOTLE-MTIME: 1508099328.000000\n" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:1 ++msgid "Migrated to GSettings" ++msgstr "Yuneg ar GSettings" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:2 ++msgid "This key shows whether or not GConf values were migrated to GSettings" ++msgstr "" ++"Tasarutt-agi teskan-d ma yella neÉ£ ala azalen n GConf unagen ar GSettings" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:3 ../data/sugar.schemas.in.h:11 ++msgid "Backup URL" ++msgstr "Asekles n URL" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:4 ../data/sugar.schemas.in.h:12 ++msgid "URL where the backup is saved to." ++msgstr "Tansa URL n usekles n uḥraz." ++ ++#: ../data/org.sugarlabs.gschema.xml.h:5 ../data/sugar.schemas.in.h:31 ++msgid "Show Log out" ++msgstr "Sken tuffÉ£a" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:6 ../data/sugar.schemas.in.h:32 ++msgid "If TRUE, Sugar will show a \"Log out\" option." ++msgstr "Ma IH, Sugar ad d-yesken asefran \"FfeÉ£\"." ++ ++#: ../data/org.sugarlabs.gschema.xml.h:7 ../data/sugar.schemas.in.h:33 ++msgid "Show Restart" ++msgstr "Sken Ales Asenker" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:8 ../data/sugar.schemas.in.h:34 ++msgid "If TRUE, Sugar will show a \"Restart\" option." ++msgstr "Ma IH, Sugar ad d-yesken asefran \"Ales Asenker\"." ++ ++#: ../data/org.sugarlabs.gschema.xml.h:9 ../data/sugar.schemas.in.h:35 ++msgid "Show Shutdown" ++msgstr "Sken Sens" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:10 ../data/sugar.schemas.in.h:36 ++msgid "If TRUE, Sugar will show a \"Shutdown\" option." ++msgstr "Ma IH, Sugar ad d-yesken asefran \"Sens\"." ++ ++#: ../data/org.sugarlabs.gschema.xml.h:11 ../data/sugar.schemas.in.h:37 ++msgid "Show Register" ++msgstr "Sken ajerred" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:12 ../data/sugar.schemas.in.h:38 ++msgid "If TRUE, Sugar will show a \"Register\" option in the buddy palette." ++msgstr "Ma IH, Sugar ad d-yesken asefran \"Ajerred\"." ++ ++#: ../data/org.sugarlabs.gschema.xml.h:13 ../data/sugar.schemas.in.h:63 ++msgid "Bundle IDs of protected activities" ++msgstr "Isulayen n iukemmes n irmuden yettwammestnen" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:14 ../data/sugar.schemas.in.h:64 ++msgid "" ++"Users will not be allowed to erase these activities through the list view." ++msgstr "Iseqdacen ur ttwasirgen ara ad kksen irmuden-agi seg tmeẓri tabdart." ++ ++#: ../data/org.sugarlabs.gschema.xml.h:15 ../data/sugar.schemas.in.h:79 ++msgid "A limit to the number of simultaneously open activities." ++msgstr "Talast n umá¸an n urmud yeldin akken." ++ ++#: ../data/org.sugarlabs.gschema.xml.h:16 ../data/sugar.schemas.in.h:80 ++msgid "" ++"This int is used to set a limit to the number of open activities. By default " ++"(0), there is no limit." ++msgstr "" ++"Umá¸an-agi ummid yettwaseqdec i usbadu n talast n umá¸an n irmuden yeldin. " ++"Azal amezwer d (0), ulac talast." ++ ++#: ../data/org.sugarlabs.gschema.xml.h:17 ../data/sugar.schemas.in.h:1 ++msgid "User Name" ++msgstr "Isem n useqdac" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:18 ../data/sugar.schemas.in.h:2 ++msgid "User name that is used throughout the desktop." ++msgstr "Isem n useqdac yettwaseqdacen deg tnarit." ++ ++#: ../data/org.sugarlabs.gschema.xml.h:19 ../data/sugar.schemas.in.h:3 ++msgid "Default nick" ++msgstr "Meffer isem amezwer" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:20 ../data/sugar.schemas.in.h:4 ++msgid "" ++"\"disabled\" to ask nick on initialization; \"system\" to reuse UNIX account " ++"long name." ++msgstr "" ++"\"yensa\" i usuter deg uwennez; \"anagraw\" i useqdec n yisem aÉ£ezfan n " ++"umiá¸an UNIX." ++ ++#: ../data/org.sugarlabs.gschema.xml.h:21 ../data/sugar.schemas.in.h:5 ++msgid "User Color" ++msgstr "Ini n useqdac" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:22 ../data/sugar.schemas.in.h:6 ++msgid "" ++"Color for the XO icon that is used throughout the desktop. The string is " ++"composed of the stroke color and fill color, format is that of rgb colors. " ++"Example: #AC32FF,#9A5200" ++msgstr "" ++"Ini n tignit XO yettwaseqdacen deg tnarit. Azrir n isekkilen yegber initen n " ++"ujerriḠakked taÄcart. Amasal icudd ar yiniten rgb, Amedya: #AC32FF,#9A5200" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:23 ++msgid "User Gender" ++msgstr "Tuzuft n useqdac" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:24 ++msgid "Gender of the Sugar user, either male, female, or unassigned" ++msgstr "Tuzuft n useqdac n Sugar, amalay, unti, neÉ£ ulac" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:25 ++msgid "User Birth Timestamp" ++msgstr "Azemzakudn tlalit n useqdac" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:26 ++msgid "Birth timestamp (seconds since the epoch)" ++msgstr "Azemzakud n tlalit (tasinin deg epoch n unagraw)" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:27 ++msgid "Group Label" ++msgstr "Tacreá¹ n ugraw" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:28 ++msgid "Label associated with age, e.g., '2nd Grade'" ++msgstr "Tacreá¹ icudden ar tneÉ£rit n tÉ£uri, amedya 'Aseggas wis 2'" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:29 ++msgid "Background image path" ++msgstr "Abrid n unekcum ar tugna n tugna n ugilal" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:30 ++msgid "Path to the image to be used as a background." ++msgstr "Abrid n unekcum n tugna yettwaseqdacen d agilal." ++ ++#: ../data/org.sugarlabs.gschema.xml.h:31 ++msgid "Background alpha level" ++msgstr "Aswir n tefrawant n ubadu alpha i tugna n ugilal" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:32 ++msgid "The opacity of the background image." ++msgstr "Aswir n tebrek n tugna n ugilal." ++ ++#: ../data/org.sugarlabs.gschema.xml.h:33 ++msgid "Mimetype registry" ++msgstr "Anaw MIME (azmam IANA)" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:34 ++msgid "Consists of key-value pairs mimetypes and their corresponding activity" ++msgstr "" ++"Yettwammel s tyugiwin tasarutt-azalen n wanawen MIME akked irmuden-nsen " ++"imená¹aá¸en" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:35 ../data/sugar.schemas.in.h:7 ++msgid "Volume Level" ++msgstr "Aswir n ubleÉ£" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:36 ../data/sugar.schemas.in.h:8 ++msgid "Volume level for the sound device." ++msgstr "Aswir n ubleÉ£ n yibenk ameslaw." ++ ++#: ../data/org.sugarlabs.gschema.xml.h:37 ../data/sugar.schemas.in.h:9 ++msgid "Sound Muted" ++msgstr "Ameslaw yensa" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:38 ../data/sugar.schemas.in.h:10 ++msgid "Setting for muting the sound device." ++msgstr "Aseggem n usexsi n yibenk ameslaw." ++ ++#: ../data/org.sugarlabs.gschema.xml.h:39 ++msgid "Brightness Level" ++msgstr "Aswir n ubruá¹›eq" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:40 ++msgid "Brightness level for the computer screen." ++msgstr "Aswir n tafat n ugdil n uselkim." ++ ++#: ../data/org.sugarlabs.gschema.xml.h:41 ++#: ../extensions/cpsection/datetime/view.py:66 ../data/sugar.schemas.in.h:13 ++msgid "Timezone" ++msgstr "Izdi usrig" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:42 ../data/sugar.schemas.in.h:14 ++msgid "Timezone setting for the system." ++msgstr "Tawila n izá¸i usrig n unagraw." ++ ++#: ../data/org.sugarlabs.gschema.xml.h:43 ++msgid "Home views" ++msgstr "Timeẓriyin tigejdanin" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:44 ++msgid "" ++"List of home views, including the view icon, the favorite icon and the layout" ++msgstr "" ++"Tubdarin n tmeẓriyin tigejdanin, igebren timeẓri tabdart, timeẓri tanurift " ++"akked d tmeẓri anarag" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:45 ++msgid "Launcher animation interval" ++msgstr "Azilal n umray n umsenker" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:46 ++msgid "" ++"Delay in milliseconds between animation updates for launcher pulsing icon." ++msgstr "Tansagt s tmilisinin gar usmiren n imrayen i yiwen n umseker. " ++ ++#: ../data/org.sugarlabs.gschema.xml.h:47 ../data/sugar.schemas.in.h:19 ++msgid "Edge Delay" ++msgstr "Tanzagt n rrif" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:48 ../data/sugar.schemas.in.h:20 ++msgid "Delay for the activation of the frame using the edges." ++msgstr "Tanzagt n tilmi iseqdacen lerryuf n tmeẓri." ++ ++#: ../data/org.sugarlabs.gschema.xml.h:49 ../data/sugar.schemas.in.h:21 ++msgid "Corner Delay" ++msgstr "Tanzagt n tiÉ£mert" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:50 ../data/sugar.schemas.in.h:22 ++msgid "Delay for the activation of the frame using the corners." ++msgstr "Tanzagt n urmad n tilmi iseqdacen tiÉ£mar n tmeẓri" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:51 ++msgid "Trigger Size" ++msgstr "TeÉ£zi n temnaá¸t n urmad" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:52 ++msgid "Size of the frame trigger area, in px from the corner/edge." ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:53 ../data/sugar.schemas.in.h:23 ++msgid "Jabber Server" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:54 ../data/sugar.schemas.in.h:24 ++msgid "URL of the jabber server to use." ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:55 ../data/sugar.schemas.in.h:29 ++msgid "Publish to Gadget" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:56 ../data/sugar.schemas.in.h:30 ++msgid "" ++"If TRUE, Sugar will make us searchable for the other users of the Jabber " ++"server." ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:57 ++msgid "Social Help Server" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:58 ++msgid "URL of the social help server to use with protocol." ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:59 ../data/sugar.schemas.in.h:25 ++msgid "Power Automatic" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:60 ++#: ../extensions/cpsection/power/view.py:55 ../data/sugar.schemas.in.h:26 ++msgid "Automatic power management (increases battery life)" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:61 ../data/sugar.schemas.in.h:27 ++msgid "Power Extreme" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:62 ../data/sugar.schemas.in.h:28 ++msgid "" ++"Extreme power management (disables wireless radio, increases battery life)" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:63 ../data/sugar.schemas.in.h:39 ++msgid "Keyboard layouts" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:64 ../data/sugar.schemas.in.h:40 ++msgid "" ++"List of keyboard layouts. Each entry should be in the form layout(variant)" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:65 ../data/sugar.schemas.in.h:41 ++msgid "Keyboard options" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:66 ../data/sugar.schemas.in.h:42 ++msgid "List of keyboard options." ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:67 ../data/sugar.schemas.in.h:43 ++msgid "Keyboard model" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:68 ../data/sugar.schemas.in.h:44 ++msgid "The keyboard model to be used" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:69 ../data/sugar.schemas.in.h:45 ++msgid "Default font face" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:70 ../data/sugar.schemas.in.h:46 ++msgid "Font face that is used throughout the desktop." ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:71 ../data/sugar.schemas.in.h:47 ++msgid "Default font size" ++msgstr "Tiddi n lexá¹£as" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:72 ../data/sugar.schemas.in.h:48 ++msgid "Font size that is used throughout the desktop." ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:73 ../data/sugar.schemas.in.h:61 ++msgid "Show Sugar Ad-hoc networks" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:74 ../data/sugar.schemas.in.h:62 ++msgid "" ++"If TRUE, Sugar will show default Ad-hoc networks for channel 1,6 and 11. If " ++"Sugar sees no \"known\" network when it starts, it does autoconnect to an Ad-" ++"hoc network." ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:75 ++msgid "Enable Ad-hoc autoconnect" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:76 ++msgid "If TRUE, Sugar will autoconnect to Ad-hoc networks." ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:77 ../data/sugar.schemas.in.h:49 ++msgid "GSM network username (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:78 ../data/sugar.schemas.in.h:50 ++msgid "GSM network username configuration (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:79 ../data/sugar.schemas.in.h:51 ++msgid "GSM network password (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:80 ../data/sugar.schemas.in.h:52 ++msgid "GSM network password configuration (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:81 ../data/sugar.schemas.in.h:53 ++msgid "GSM network number (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:82 ../data/sugar.schemas.in.h:54 ++msgid "GSM network telephone number configuration (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:83 ../data/sugar.schemas.in.h:55 ++msgid "GSM network APN (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:84 ../data/sugar.schemas.in.h:56 ++msgid "GSM network access point name configuration (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:85 ../data/sugar.schemas.in.h:57 ++msgid "GSM network PIN (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:86 ../data/sugar.schemas.in.h:58 ++msgid "" ++"GSM network personal identification number configuration (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:87 ../data/sugar.schemas.in.h:59 ++msgid "GSM network PUK (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:88 ../data/sugar.schemas.in.h:60 ++msgid "GSM network personal unlock key configuration (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:89 ++msgid "TODO: add summary" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:90 ++msgid "TODO: add description" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:91 ../data/sugar.schemas.in.h:65 ++msgid "Pitch value for the speech sugar service" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:92 ../data/sugar.schemas.in.h:66 ++msgid "Pitch value used by the speech service in Sugar" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:93 ../data/sugar.schemas.in.h:67 ++msgid "Rate value for the speech sugar service" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:94 ../data/sugar.schemas.in.h:68 ++msgid "Rate value used by the speech service in Sugar" ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:95 ../data/sugar.schemas.in.h:69 ++msgid "Activity update backend." ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:96 ../data/sugar.schemas.in.h:70 ++msgid "" ++"Activity update backend module, followed by a period, followed by the class " ++"name." ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:97 ../data/sugar.schemas.in.h:71 ++msgid "Microformat update URL." ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:98 ../data/sugar.schemas.in.h:72 ++msgid "" ++"URL used by the microformat update backend for activity update information." ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:99 ../data/sugar.schemas.in.h:73 ++msgid "Automatic update frequency." ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:100 ../data/sugar.schemas.in.h:74 ++msgid "" ++"Frequency of automatic activity updates, measured in days. 0 means disabled." ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:101 ../data/sugar.schemas.in.h:75 ++msgid "Timestamp of last activity update." ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:102 ../data/sugar.schemas.in.h:76 ++msgid "" ++"A unix timestamp (seconds since epoch) of the last successful activity " ++"update." ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:103 ++msgid "New ASLO update.json URL." ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:104 ++msgid "URL used by the new ASLO updater to download activity data." ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:105 ../data/sugar.schemas.in.h:77 ++msgid "A description of the hardware available to the user." ++msgstr "" ++ ++#: ../data/org.sugarlabs.gschema.xml.h:106 ../data/sugar.schemas.in.h:78 ++msgid "This string is displayed in the control panel, about computer section." ++msgstr "" ++ ++#: ../extensions/cpsection/aboutme/__init__.py:23 ++msgid "About Me" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutme/model.py:51 ++msgid "You must enter a name." ++msgstr "" ++ ++#: ../extensions/cpsection/aboutme/model.py:83 ++#, python-format ++msgid "stroke: color=%s hue=%s" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutme/model.py:86 ++#, python-format ++msgid "stroke: %s" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutme/model.py:88 ++#, python-format ++msgid "fill: color=%s hue=%s" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutme/model.py:90 ++#, python-format ++msgid "fill: %s" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutme/model.py:102 ++msgid "Error in specified color modifiers." ++msgstr "" ++ ++#: ../extensions/cpsection/aboutme/model.py:105 ++msgid "Error in specified colors." ++msgstr "" ++ ++#: ../extensions/cpsection/aboutme/view.py:243 ++msgid "Click to change your color:" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutme/view.py:294 ++#: ../src/jarabe/intro/window.py:203 ++msgid "Select gender:" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutcomputer/__init__.py:21 ++msgid "About my Computer" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutcomputer/model.py:37 ++msgid "Not available" ++msgstr "Ulac" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:76 ++msgid "Identity" ++msgstr "Tamagit" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:87 ++msgid "Model:" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:91 ++msgid "Serial Number:" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:103 ++msgid "Software" ++msgstr "Aseɣẓan" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:112 ++msgid "Build:" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:117 ++msgid "Sugar:" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:122 ++msgid "Firmware:" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:127 ++msgid "Wireless Firmware:" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:134 ++#, python-format ++msgid "%d days ago" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:136 ++#: ../src/jarabe/journal/journaltoolbox.py:169 ++msgid "Today" ++msgstr "Ass-a" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:139 ++msgid "Last system update:" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:150 ++msgid "Copyright and License" ++msgstr "Izerfan n umeskar d turagt" ++ ++#. TRANS: The word "Sugar" should not be translated. ++#: ../extensions/cpsection/aboutcomputer/view.py:169 ++msgid "" ++"Sugar is the graphical user interface that you are looking at. Sugar is free " ++"software, covered by the GNU General Public License, and you are welcome to " ++"change it and/or distribute copies of it under certain conditions described " ++"therein." ++msgstr "" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:181 ++msgid "Full license:" ++msgstr "" ++ ++#: ../extensions/cpsection/background/__init__.py:21 ++msgid "Background" ++msgstr "Agilal" ++ ++#: ../extensions/cpsection/background/view.py:48 ++msgid "Select a background:" ++msgstr "Fren agilal:" ++ ++#: ../extensions/cpsection/background/view.py:57 ++msgid "Clear background" ++msgstr "SfeḠagilal" ++ ++#: ../extensions/cpsection/datetime/__init__.py:21 ++msgid "Date & Time" ++msgstr "Azemz akked usrag" ++ ++#: ../extensions/cpsection/datetime/model.py:100 ++msgid "Error: timezone does not exist." ++msgstr "Tuccá¸a: tamnaá¸t tasragant ulac-itt." ++ ++#: ../extensions/cpsection/frame/__init__.py:21 ++msgid "Frame" ++msgstr "Akatar" ++ ++#: ../extensions/cpsection/frame/view.py:26 ++msgid "never" ++msgstr "werǧin" ++ ++#: ../extensions/cpsection/frame/view.py:27 ++msgid "instantaneous" ++msgstr "" ++ ++#: ../extensions/cpsection/frame/view.py:28 ++#, python-format ++msgid "%s seconds" ++msgstr "" ++ ++#: ../extensions/cpsection/frame/view.py:52 ++msgid "Activation Delay" ++msgstr "" ++ ++#: ../extensions/cpsection/frame/view.py:68 ++msgid "Activation Area" ++msgstr "" ++ ++#: ../extensions/cpsection/frame/view.py:85 ++msgid "Corner" ++msgstr "" ++ ++#: ../extensions/cpsection/frame/view.py:104 ++msgid "Edge" ++msgstr "" ++ ++#: ../extensions/cpsection/frame/view.py:123 ++msgid "Size" ++msgstr "Tiddi (bytes/octets)" ++ ++#: ../extensions/cpsection/frame/view.py:221 ++msgid "toolbar size" ++msgstr "Tiddi n tfeggagt n ifecka" ++ ++#: ../extensions/cpsection/frame/view.py:226 ++msgid "exact corner or edge" ++msgstr "" ++ ++#: ../extensions/cpsection/frame/view.py:228 ++msgid "exact corner" ++msgstr "" ++ ++#: ../extensions/cpsection/frame/view.py:230 ++msgid "exact edge" ++msgstr "" ++ ++#: ../extensions/cpsection/frame/view.py:232 ++msgid "ignored" ++msgstr "yettwanef" ++ ++#. TRANS: px as in pixels ++#: ../extensions/cpsection/frame/view.py:235 ++msgid "{}px" ++msgstr "" ++ ++#: ../extensions/cpsection/keyboard/__init__.py:21 ++#: ../extensions/cpsection/keyboard/view.py:38 ++msgid "Keyboard" ++msgstr "Anasiw" ++ ++#: ../extensions/cpsection/keyboard/view.py:240 ++msgid "Keyboard Model" ++msgstr "" ++ ++#: ../extensions/cpsection/keyboard/view.py:301 ++msgid "Key(s) to change layout" ++msgstr "" ++ ++#: ../extensions/cpsection/keyboard/view.py:369 ++msgid "Keyboard Layout(s)" ++msgstr "" ++ ++#: ../extensions/cpsection/language/__init__.py:21 ++#: ../extensions/cpsection/language/view.py:39 ++msgid "Language" ++msgstr "Tutlayt" ++ ++#: ../extensions/cpsection/language/model.py:29 ++msgid "Could not access ~/.i18n. Create standard settings." ++msgstr "" ++ ++#: ../extensions/cpsection/language/model.py:156 ++#, python-format ++msgid "Language for code=%s could not be determined." ++msgstr "" ++ ++#: ../extensions/cpsection/language/model.py:179 ++#, python-format ++msgid "Sorry I do not speak '%s'." ++msgstr "" ++ ++#: ../extensions/cpsection/language/view.py:75 ++msgid "" ++"Add languages in the order you prefer. If a translation is not available, " ++"the next in the list will be used." ++msgstr "" ++ ++#: ../extensions/cpsection/language/view.py:383 ++#, python-format ++msgid "Error writting language configuration (%s)" ++msgstr "" ++ ++#: ../extensions/cpsection/modemconfiguration/__init__.py:21 ++msgid "Modem" ++msgstr "" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:94 ++msgid "" ++"You will need to provide the following information to set up a mobile " ++"broadband connection to a cellular (3G) network." ++msgstr "" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:117 ++msgid "Country:" ++msgstr "Tamurt:" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:118 ++msgid "Provider:" ++msgstr "" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:119 ++msgid "Plan:" ++msgstr "" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:160 ++msgid "Username:" ++msgstr "Isem n wemseqdac:" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:167 ++msgid "Password:" ++msgstr "Awal n tbaá¸nit:" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:174 ++msgid "Number:" ++msgstr "" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:181 ++msgid "Access Point Name (APN):" ++msgstr "" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:188 ++msgid "Personal Identity Number (PIN):" ++msgstr "" ++ ++#: ../extensions/cpsection/modemconfiguration/model.py:162 ++#, python-format ++msgid "Plan #%s" ++msgstr "" ++ ++#: ../extensions/cpsection/modemconfiguration/model.py:292 ++#, python-format ++msgid "Provider %s" ++msgstr "" ++ ++#: ../extensions/cpsection/network/__init__.py:21 ++#: ../extensions/cpsection/network/view.py:30 ++msgid "Network" ++msgstr "Azeá¹á¹a" ++ ++#: ../extensions/cpsection/network/model.py:88 ++msgid "State is unknown." ++msgstr "" ++ ++#: ../extensions/cpsection/network/model.py:104 ++msgid "Error in specified radio argument use on/off." ++msgstr "" ++ ++#: ../extensions/cpsection/network/model.py:197 ++msgid "Error in specified argument use 0/1." ++msgstr "" ++ ++#: ../extensions/cpsection/network/view.py:65 ++msgid "Wireless" ++msgstr "" ++ ++#: ../extensions/cpsection/network/view.py:73 ++msgid "The wireless radio may be turned off to save battery life." ++msgstr "" ++ ++#: ../extensions/cpsection/network/view.py:86 ++msgid "Radio" ++msgstr "" ++ ++#: ../extensions/cpsection/network/view.py:103 ++msgid "" ++"Discard wireless connections if you have trouble connecting to the network" ++msgstr "" ++ ++#: ../extensions/cpsection/network/view.py:113 ++msgid "Discard wireless connections" ++msgstr "" ++ ++#: ../extensions/cpsection/network/view.py:129 ++msgid "Collaboration" ++msgstr "" ++ ++#: ../extensions/cpsection/network/view.py:137 ++msgid "" ++"The server is the equivalent of what room you are in; people on the same " ++"server will be able to see each other, even when they aren't on the same " ++"network." ++msgstr "" ++ ++#: ../extensions/cpsection/network/view.py:147 ++msgid "Server:" ++msgstr "Aqeddac:" ++ ++#: ../extensions/cpsection/network/view.py:163 ++msgid "" ++"Social Help is a forum that lets you connect with developers and discuss " ++"Sugar Activities. Changing servers means discussions will happen in a " ++"different place with different people." ++msgstr "" ++ ++#: ../extensions/cpsection/network/view.py:173 ++msgid "Social Help Server:" ++msgstr "" ++ ++#: ../extensions/cpsection/power/__init__.py:24 ++msgid "Power" ++msgstr "" ++ ++#: ../extensions/cpsection/power/model.py:90 ++msgid "Error in automatic pm argument, use on/off." ++msgstr "" ++ ++#: ../extensions/cpsection/power/view.py:45 ++msgid "Power management" ++msgstr "" ++ ++#: ../extensions/cpsection/updater/__init__.py:21 ++msgid "Software Update" ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:70 ++msgid "" ++"Software updates correct errors, eliminate security vulnerabilities, and " ++"provide new features." ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:84 ++msgid "Update in progress..." ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:119 ++msgid "Checking for updates..." ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:121 ++msgid "Installing updates..." ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:150 ++#, python-format ++msgid "Checking %s..." ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:152 ++msgid "Looking for updates..." ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:154 ++#, python-format ++msgid "Downloading %s..." ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:156 ++#, python-format ++msgid "Updating %s..." ++msgstr "AmucceḠ%s..." ++ ++#: ../extensions/cpsection/updater/view.py:166 ++msgid "Your software is up-to-date" ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:168 ++#, python-format ++msgid "You can install %s update" ++msgid_plural "You can install %s updates" ++msgstr[0] "" ++msgstr[1] "" ++ ++#: ../extensions/cpsection/updater/view.py:183 ++msgid "Can't connect to the activity server" ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:186 ++msgid "Verify your connection to internet and try again, or try again later" ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:206 ++#, python-format ++msgid "%s update was installed" ++msgid_plural "%s updates were installed" ++msgstr[0] "" ++msgstr[1] "" ++ ++#: ../extensions/cpsection/updater/view.py:288 ++msgid "Install selected" ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:307 ++#, python-format ++msgid "Download size: %s" ++msgstr "Tiddi n usider: %s" ++ ++#: ../extensions/cpsection/updater/view.py:399 ++#, python-format ++msgid "From version %(current)s to %(new)s (Size: %(size)s)" ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:406 ++#, python-format ++msgid "Version %(version)s (Size: %(size)s)" ++msgstr "" ++ ++#. TRANS: download size is 0 ++#: ../extensions/cpsection/updater/view.py:423 ++msgid "None" ++msgstr "Aucun" ++ ++#. TRANS: download size of very small updates ++#: ../extensions/cpsection/updater/view.py:426 ++msgid "1 KB" ++msgstr "" ++ ++#. TRANS: download size of small updates, e.g. '250 KB' ++#: ../extensions/cpsection/updater/view.py:429 ++#, python-format ++msgid "%.0f KB" ++msgstr "" ++ ++#. TRANS: download size of updates, e.g. '2.3 MB' ++#: ../extensions/cpsection/updater/view.py:432 ++#, python-format ++msgid "%.1f MB" ++msgstr "%.1f MAṬ" ++ ++#: ../extensions/cpsection/webaccount/__init__.py:24 ++msgid "Web Services" ++msgstr "Imeẓla Web" ++ ++#: ../extensions/cpsection/webaccount/view.py:65 ++#, python-format ++msgid "" ++"No web services are installed.\n" ++"Please visit %s for more details." ++msgstr "" ++ ++#: ../extensions/deviceicon/audio.py:69 ++msgid "My Audio" ++msgstr "Ameslaw-iw" ++ ++#: ../extensions/deviceicon/audio.py:330 ++msgid "Speaker" ++msgstr "" ++ ++#: ../extensions/deviceicon/audio.py:331 ++msgid "Microphone" ++msgstr "Asawaá¸" ++ ++#: ../extensions/deviceicon/battery.py:69 ++msgid "My Battery" ++msgstr "" ++ ++#: ../extensions/deviceicon/battery.py:151 ++msgid "Removed" ++msgstr "" ++ ++#: ../extensions/deviceicon/battery.py:154 ++msgid "Charging" ++msgstr "Asali" ++ ++#: ../extensions/deviceicon/battery.py:157 ++msgid "Very little power remaining" ++msgstr "" ++ ++#. TRANS: do not translate %(hour)d:%(min).2d it is a variable, ++#. only translate the word "remaining" ++#: ../extensions/deviceicon/battery.py:164 ++#, python-format ++msgid "%(hour)d:%(min).2d remaining" ++msgstr "" ++ ++#: ../extensions/deviceicon/battery.py:167 ++msgid "Charged" ++msgstr "Yuli" ++ ++#: ../extensions/deviceicon/display.py:187 ++msgid "My Display" ++msgstr "Agdil-iw" ++ ++#: ../extensions/deviceicon/display.py:189 ++msgid "Take a screenshot" ++msgstr "Ṭá¹ef agdil" ++ ++#: ../extensions/deviceicon/display.py:211 ++msgid "Brightness" ++msgstr "" ++ ++#: ../extensions/deviceicon/display.py:239 ++msgid "Display" ++msgstr "Sken" ++ ++#: ../extensions/deviceicon/frame.py:53 ++msgid "Show my keyboard" ++msgstr "Sken anasiw-iw" ++ ++#: ../extensions/deviceicon/network.py:48 ++#, python-format ++msgid "IP address: %s" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:80 ++#: ../extensions/deviceicon/network.py:297 ++#: ../src/jarabe/desktop/networkviews.py:134 ++#: ../src/jarabe/desktop/networkviews.py:510 ++msgid "Disconnect" ++msgstr "FfeÉ£" ++ ++#: ../extensions/deviceicon/network.py:106 ++#: ../extensions/deviceicon/network.py:290 ++#: ../src/jarabe/desktop/networkviews.py:250 ++#: ../src/jarabe/desktop/networkviews.py:552 ++#: ../src/jarabe/desktop/networkviews.py:696 ++msgid "Connecting..." ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:110 ++#: ../extensions/deviceicon/network.py:181 ++#: ../src/jarabe/desktop/networkviews.py:257 ++#: ../src/jarabe/desktop/networkviews.py:558 ++#: ../src/jarabe/desktop/networkviews.py:702 ++msgid "Connected" ++msgstr "Iqqen" ++ ++#: ../extensions/deviceicon/network.py:123 ++msgid "No wireless connection" ++msgstr "Tuqqna war tinelli" ++ ++#: ../extensions/deviceicon/network.py:137 ++#: ../extensions/deviceicon/network.py:140 ++msgid "Channel" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:138 ++#: ../src/jarabe/journal/expandedentry.py:386 ++#: ../src/jarabe/journal/listmodel.py:191 ++#: ../src/jarabe/journal/listmodel.py:199 ++msgid "Unknown" ++msgstr "Arussin" ++ ++#: ../extensions/deviceicon/network.py:156 ++msgid "Wired Network" ++msgstr "Aẓeá¹á¹a n tnelli" ++ ++#: ../extensions/deviceicon/network.py:184 ++msgid "Speed" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:209 ++msgid "Wireless modem" ++msgstr "Atrar war tinelli" ++ ++#: ../extensions/deviceicon/network.py:278 ++msgid "Please wait..." ++msgstr "Ttxil-k arǧu..." ++ ++#: ../extensions/deviceicon/network.py:282 ++#: ../src/jarabe/desktop/networkviews.py:128 ++#: ../src/jarabe/desktop/networkviews.py:504 ++#: ../src/jarabe/desktop/networkviews.py:647 ++msgid "Connect" ++msgstr "Qqen" ++ ++#: ../extensions/deviceicon/network.py:283 ++#, fuzzy ++msgid "Disconnected" ++msgstr "Yenser" ++ ++#: ../extensions/deviceicon/network.py:289 ++#: ../src/jarabe/controlpanel/toolbar.py:121 ++#: ../src/jarabe/frame/activitiestray.py:693 ++#: ../src/jarabe/frame/activitiestray.py:815 ++#: ../src/jarabe/frame/activitiestray.py:848 ++#: ../src/jarabe/journal/expandedentry.py:157 ++#: ../src/jarabe/journal/journaltoolbox.py:587 ++#: ../src/jarabe/journal/palettes.py:166 ++msgid "Cancel" ++msgstr "Sesfex" ++ ++#: ../extensions/deviceicon/network.py:327 ++msgid "Try connection again" ++msgstr "ÆreḠtikelt nniá¸en tuqqna" ++ ++#: ../extensions/deviceicon/network.py:330 ++#, python-format ++msgid "Error: %s" ++msgstr "Tuccá¸a: %s" ++ ++#: ../extensions/deviceicon/network.py:334 ++#, python-format ++msgid "Suggestion: %s" ++msgstr "Asumer: %s" ++ ++#: ../extensions/deviceicon/network.py:344 ++#, python-format ++msgid "Connected for %s" ++msgstr "Iqqen É£er %s" ++ ++#: ../extensions/deviceicon/network.py:349 ++#: ../extensions/deviceicon/network.py:350 ++#, python-format ++msgid "%d KB" ++msgstr "%d KAṬ" ++ ++#: ../extensions/deviceicon/network.py:355 ++msgid "Check your PIN/PUK configuration." ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:358 ++msgid "Check your Access Point Name (APN) configuration" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:362 ++msgid "Check the Number configuration." ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:364 ++msgid "Check your configuration." ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:619 ++msgid "Mesh Network" ++msgstr "Azeá¹á¹a Mesh" ++ ++#: ../extensions/deviceicon/network.py:665 ++#, python-format ++msgid "Mesh Network %s" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:782 ++msgid "No GSM connection available." ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:783 ++msgid "Create a connection in My Settings." ++msgstr "" ++ ++#: ../extensions/deviceicon/speech.py:49 ++msgid "Speech" ++msgstr "Ameslay" ++ ++#: ../extensions/deviceicon/speech.py:72 ++#: ../extensions/deviceicon/speech.py:147 ++#: ../extensions/deviceicon/speech.py:152 ++msgid "Say selected text" ++msgstr "" ++ ++#: ../extensions/deviceicon/speech.py:80 ++msgid "Stop playback" ++msgstr "" ++ ++#: ../extensions/deviceicon/speech.py:89 ++msgid "Pitch" ++msgstr "" ++ ++#: ../extensions/deviceicon/speech.py:104 ++msgid "Rate" ++msgstr "Afmiá¸i" ++ ++#: ../extensions/deviceicon/speech.py:142 ++msgid "Pause playback" ++msgstr "" ++ ++#: ../extensions/deviceicon/touchpad.py:36 ++msgid "finger" ++msgstr "" ++ ++#: ../extensions/deviceicon/touchpad.py:36 ++msgid "stylus" ++msgstr "" ++ ++#: ../extensions/deviceicon/touchpad.py:61 ++msgid "My touchpad" ++msgstr "" ++ ++#: ../extensions/deviceicon/volume.py:62 ../src/jarabe/view/palettes.py:210 ++msgid "Show contents" ++msgstr "Sken Igburen" ++ ++#: ../data/sugar.schemas.in.h:15 ++msgid "Favorites Layout" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:16 ++msgid "Layout of the favorites view." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:17 ++msgid "Favorites resume mode" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:18 ++msgid "" ++"When in resume mode, clicking on a favorite icon will cause the last entry " ++"for that activity to be resumed." ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/cmd.py:28 ++#, python-format ++msgid "" ++"sugar-control-panel: WARNING, found more than one option with the same name: " ++"%s module: %r" ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/cmd.py:30 ++#, python-format ++msgid "sugar-control-panel: key=%s not an available option" ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/cmd.py:31 ++#, python-format ++msgid "sugar-control-panel: %s" ++msgstr "" ++ ++#. TRANS: Translators, there's a empty line at the end of this string, ++#. which must appear in the translated string (msgstr) as well. ++#: ../src/jarabe/controlpanel/cmd.py:38 ++msgid "" ++"Usage: sugar-control-panel [ option ] key [ args ... ] \n" ++" Control for the sugar environment. \n" ++" Options: \n" ++" -h show this help message and exit \n" ++" -l list all the available options \n" ++" -h key show information about this key \n" ++" -g key get the current value of the key \n" ++" -s key set the current value for the key \n" ++" -c key clear the current value for the key \n" ++" " ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/cmd.py:52 ++msgid "" ++"To apply your changes you have to restart Sugar.\n" ++"Hit ctrl+alt+erase on the keyboard to trigger a restart." ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/gui.py:373 ../src/jarabe/journal/palettes.py:194 ++#: ../src/jarabe/journal/palettes.py:364 ../src/jarabe/journal/palettes.py:424 ++#: ../src/jarabe/journal/volumestoolbar.py:304 ++msgid "Warning" ++msgstr "Æ”ur-k" ++ ++#: ../src/jarabe/controlpanel/gui.py:374 ++#: ../src/jarabe/controlpanel/sectionview.py:45 ++msgid "Changes require restart" ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/gui.py:379 ++msgid "Cancel changes" ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/gui.py:384 ++msgid "Later" ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/gui.py:388 ++msgid "Restart now" ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/gui.py:419 ../src/jarabe/view/buddymenu.py:137 ++msgid "An activity is not responding." ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/gui.py:420 ../src/jarabe/view/buddymenu.py:138 ++msgid "You may lose unsaved work if you continue." ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/toolbar.py:56 ++#: ../src/jarabe/desktop/viewtoolbar.py:129 ++#: ../src/jarabe/journal/journaltoolbox.py:94 ++#, python-format ++msgid "Search in %s" ++msgstr "Nadi di %s" ++ ++#: ../src/jarabe/controlpanel/toolbar.py:56 ++msgid "Settings" ++msgstr "Iγewwaá¹›en" ++ ++#: ../src/jarabe/controlpanel/toolbar.py:65 ../src/jarabe/intro/window.py:349 ++msgid "Done" ++msgstr "Immed" ++ ++#: ../src/jarabe/controlpanel/toolbar.py:127 ++msgid "Ok" ++msgstr "Ih" ++ ++#: ../src/jarabe/desktop/activitieslist.py:340 ++#, python-format ++msgid "Version %s" ++msgstr "Lqem %s" ++ ++#: ../src/jarabe/desktop/activitieslist.py:424 ++#: ../src/jarabe/journal/listview.py:566 ../src/jarabe/journal/iconview.py:301 ++msgid "Clear search" ++msgstr "" ++ ++#: ../src/jarabe/desktop/activitieslist.py:510 ++msgid "No matching activities" ++msgstr "" ++ ++#: ../src/jarabe/desktop/activitieslist.py:546 ++msgid "Confirm erase" ++msgstr "" ++ ++#: ../src/jarabe/desktop/activitieslist.py:548 ++#, python-format ++msgid "Confirm erase: Do you want to permanently erase %s?" ++msgstr "" ++ ++#: ../src/jarabe/desktop/activitieslist.py:552 ++#: ../src/jarabe/frame/clipboardmenu.py:65 ++#: ../src/jarabe/view/viewsource.py:383 ++msgid "Keep" ++msgstr "Eǧǧ" ++ ++#: ../src/jarabe/desktop/activitieslist.py:555 ++#: ../src/jarabe/desktop/activitieslist.py:625 ++#: ../src/jarabe/journal/expandedentry.py:151 ++#: ../src/jarabe/journal/journaltoolbox.py:545 ++#: ../src/jarabe/journal/journaltoolbox.py:582 ++#: ../src/jarabe/journal/journaltoolbox.py:806 ++#: ../src/jarabe/journal/journaltoolbox.py:812 ++#: ../src/jarabe/journal/palettes.py:138 ../src/jarabe/journal/palettes.py:161 ++msgid "Erase" ++msgstr "Sfeá¸" ++ ++#: ../src/jarabe/desktop/activitieslist.py:641 ++msgid "Remove favorite" ++msgstr "" ++ ++#: ../src/jarabe/desktop/activitieslist.py:645 ++msgid "Make favorite" ++msgstr "" ++ ++#. TRANS: label for the freeform layout in the favorites view ++#: ../src/jarabe/desktop/favoriteslayout.py:209 ++msgid "Freeform" ++msgstr "" ++ ++#. TRANS: label for the ring layout in the favorites view ++#: ../src/jarabe/desktop/favoriteslayout.py:305 ++msgid "Ring" ++msgstr "" ++ ++#. TRANS: label for the spiral layout in the favorites view ++#: ../src/jarabe/desktop/favoriteslayout.py:469 ++msgid "Spiral" ++msgstr "" ++ ++#. TRANS: label for the box layout in the favorites view ++#: ../src/jarabe/desktop/favoriteslayout.py:537 ++msgid "Box" ++msgstr "" ++ ++#. TRANS: label for the box layout in the favorites view ++#: ../src/jarabe/desktop/favoriteslayout.py:580 ++msgid "Triangle" ++msgstr "" ++ ++#: ../src/jarabe/desktop/favoritesview.py:376 ++msgid "Registration" ++msgstr "Ajerred" ++ ++#: ../src/jarabe/desktop/favoritesview.py:377 ++msgid "Please wait, searching for your school server." ++msgstr "" ++ ++#: ../src/jarabe/desktop/favoritesview.py:387 ++msgid "Registration Failed" ++msgstr "" ++ ++#: ../src/jarabe/desktop/favoritesview.py:390 ++msgid "Registration Successful" ++msgstr "" ++ ++#: ../src/jarabe/desktop/favoritesview.py:391 ++msgid "You are now registered with your school server." ++msgstr "" ++ ++#: ../src/jarabe/desktop/favoritesview.py:680 ++msgid "Register" ++msgstr "Sekles" ++ ++#: ../src/jarabe/desktop/favoritesview.py:682 ++msgid "Register again" ++msgstr "" ++ ++#: ../src/jarabe/desktop/homewindow.py:255 ++#: ../src/jarabe/desktop/viewtoolbar.py:73 ++#: ../src/jarabe/frame/zoomtoolbar.py:57 ../src/jarabe/model/screenshot.py:63 ++#: ../src/jarabe/view/viewhelp.py:76 ++msgid "Home" ++msgstr "Agejdan" ++ ++#: ../src/jarabe/desktop/homewindow.py:262 ++#: ../src/jarabe/frame/zoomtoolbar.py:53 ../src/jarabe/model/screenshot.py:61 ++#: ../src/jarabe/view/viewhelp.py:73 ++msgid "Group" ++msgstr "Agraw" ++ ++#: ../src/jarabe/desktop/homewindow.py:269 ++#: ../src/jarabe/frame/zoomtoolbar.py:49 ++msgid "Neighborhood" ++msgstr "Anarag-iw" ++ ++#: ../src/jarabe/desktop/keydialog.py:92 ++#, python-format ++msgid "" ++"A wireless encryption key is required for\n" ++" the wireless network '%s'." ++msgstr "" ++ ++#: ../src/jarabe/desktop/keydialog.py:141 ++msgid "Key Type:" ++msgstr "Anaw n tsarutt:" ++ ++#: ../src/jarabe/desktop/keydialog.py:161 ++msgid "Authentication Type:" ++msgstr "" ++ ++#: ../src/jarabe/desktop/keydialog.py:224 ++msgid "WPA & WPA2 Personal" ++msgstr "" ++ ++#: ../src/jarabe/desktop/keydialog.py:233 ++msgid "Wireless Security:" ++msgstr "" ++ ++#. TRANS: Action label for resuming an activity. ++#: ../src/jarabe/desktop/meshbox.py:82 ++#: ../src/jarabe/journal/journaltoolbox.py:659 ++#: ../src/jarabe/journal/palettes.py:83 ../src/jarabe/view/palettes.py:98 ++msgid "Resume" ++msgstr "" ++ ++#: ../src/jarabe/desktop/meshbox.py:89 ++#: ../src/jarabe/frame/activitiestray.py:208 ++msgid "Join" ++msgstr "Asemlil" ++ ++#: ../src/jarabe/desktop/networkviews.py:499 ++#, python-format ++msgid "Ad-hoc Network %d" ++msgstr "" ++ ++#: ../src/jarabe/desktop/networkviews.py:643 ++#, python-format ++msgid "Mesh Network %d" ++msgstr "" ++ ++#: ../src/jarabe/desktop/schoolserver.py:144 ++msgid "Cannot connect to the server." ++msgstr "" ++ ++#: ../src/jarabe/desktop/schoolserver.py:151 ++msgid "The server could not complete the request." ++msgstr "" ++ ++#: ../src/jarabe/desktop/viewtoolbar.py:95 ++msgid "List view" ++msgstr "Timeẓri n tebdart" ++ ++#: ../src/jarabe/desktop/viewtoolbar.py:97 ++#: ../src/jarabe/desktop/viewtoolbar.py:196 ++#: ../src/jarabe/desktop/viewtoolbar.py:210 ++#, python-format ++msgid "<Ctrl>%d" ++msgstr "" ++ ++#: ../src/jarabe/frame/activitiestray.py:213 ++#: ../src/jarabe/frame/activitiestray.py:657 ++msgid "Decline" ++msgstr "Agwi" ++ ++#: ../src/jarabe/frame/activitiestray.py:598 ++#, python-format ++msgid "%dB" ++msgstr "%dAṬ" ++ ++#: ../src/jarabe/frame/activitiestray.py:600 ++#, python-format ++msgid "%dKB" ++msgstr "%dKAṬ" ++ ++#: ../src/jarabe/frame/activitiestray.py:602 ++#, python-format ++msgid "%dMB" ++msgstr "%dMAṬ" ++ ++#. TRANS: file transfer, bytes transferred, e.g. 128 of 1024 ++#: ../src/jarabe/frame/activitiestray.py:620 ++#, python-format ++msgid "%s of %s" ++msgstr "%s, si %s" ++ ++#: ../src/jarabe/frame/activitiestray.py:634 ++#, python-format ++msgid "Transfer from %s" ++msgstr "" ++ ++#: ../src/jarabe/frame/activitiestray.py:648 ++#: ../extensions/cpsection/backup/view.py:324 ++msgid "Accept" ++msgstr "Qbel" ++ ++#: ../src/jarabe/frame/activitiestray.py:722 ++#: ../src/jarabe/frame/activitiestray.py:736 ++#: ../src/jarabe/frame/activitiestray.py:878 ++msgid "Dismiss" ++msgstr "Kkes" ++ ++#: ../src/jarabe/frame/activitiestray.py:750 ++msgid "The other participant canceled the file transfer" ++msgstr "" ++ ++#: ../src/jarabe/frame/activitiestray.py:800 ++#, python-format ++msgid "Transfer to %s" ++msgstr "" ++ ++#: ../src/jarabe/frame/clipboardmenu.py:54 ++msgctxt "Clipboard" ++msgid "Remove" ++msgstr "Kkes" ++ ++#: ../src/jarabe/frame/clipboardmenu.py:60 ++#: ../src/jarabe/frame/clipboardmenu.py:83 ++msgid "Open" ++msgstr "Ldi" ++ ++#: ../src/jarabe/frame/clipboardmenu.py:88 ++msgid "Open with" ++msgstr "Ldi s" ++ ++#: ../src/jarabe/frame/clipboardobject.py:50 ++#, python-format ++msgid "%s clipping" ++msgstr "" ++ ++#: ../src/jarabe/frame/zoomtoolbar.py:50 ++msgid "F1" ++msgstr "" ++ ++#: ../src/jarabe/frame/zoomtoolbar.py:54 ++msgid "F2" ++msgstr "" ++ ++#: ../src/jarabe/frame/zoomtoolbar.py:58 ++msgid "F3" ++msgstr "" ++ ++#: ../src/jarabe/frame/zoomtoolbar.py:62 ../src/jarabe/model/screenshot.py:69 ++msgid "Activity" ++msgstr "Armud" ++ ++#: ../src/jarabe/frame/zoomtoolbar.py:63 ++msgid "F4" ++msgstr "" ++ ++#: ../src/jarabe/intro/window.py:135 ++msgid "Name:" ++msgstr "Isem :" ++ ++#: ../src/jarabe/intro/window.py:174 ++msgid "Click to change color:" ++msgstr "" ++ ++#: ../src/jarabe/intro/window.py:337 ../src/jarabe/journal/detailview.py:95 ++msgid "Back" ++msgstr "UÉ£al" ++ ++#: ../src/jarabe/intro/window.py:352 ++msgid "Next" ++msgstr "Ar zdat" ++ ++#: ../src/jarabe/intro/agepicker.py:38 ++msgid "Select grade:" ++msgstr "" ++ ++#: ../src/jarabe/intro/agepicker.py:39 ++msgid "Preschool" ++msgstr "" ++ ++#: ../src/jarabe/intro/agepicker.py:39 ++msgid "Kindergarten" ++msgstr "AÉ£erbaz n warrac" ++ ++#: ../src/jarabe/intro/agepicker.py:39 ++msgid "1st Grade" ++msgstr "" ++ ++#: ../src/jarabe/intro/agepicker.py:40 ++msgid "2nd Grade" ++msgstr "" ++ ++#: ../src/jarabe/intro/agepicker.py:40 ++msgid "3rd Grade" ++msgstr "" ++ ++#: ../src/jarabe/intro/agepicker.py:40 ++msgid "4th Grade" ++msgstr "" ++ ++#: ../src/jarabe/intro/agepicker.py:41 ++msgid "5th Grade" ++msgstr "" ++ ++#: ../src/jarabe/intro/agepicker.py:41 ++msgid "6th Grade" ++msgstr "" ++ ++#: ../src/jarabe/intro/agepicker.py:41 ++msgid "7th Grade" ++msgstr "" ++ ++#: ../src/jarabe/intro/agepicker.py:42 ++msgid "High School" ++msgstr "" ++ ++#: ../src/jarabe/intro/agepicker.py:42 ++msgid "Adult" ++msgstr "" ++ ++#: ../src/jarabe/journal/expandedentry.py:153 ++#: ../src/jarabe/journal/journaltoolbox.py:584 ++#: ../src/jarabe/journal/palettes.py:163 ++#, python-format ++msgid "Do you want to permanently erase \"%s\"?" ++msgstr "" ++ ++#: ../src/jarabe/journal/expandedentry.py:296 ++#: ../src/jarabe/journal/listmodel.py:185 ../src/jarabe/journal/model.py:794 ++#: ../src/jarabe/journal/palettes.py:72 ../src/jarabe/journal/palettes.py:621 ++#: ../src/jarabe/journal/volumestoolbar.py:134 ++#: ../src/jarabe/journal/iconmodel.py:110 ++msgid "Untitled" ++msgstr "War azwel" ++ ++#: ../src/jarabe/journal/expandedentry.py:366 ++msgid "No preview" ++msgstr "Ulac taskant" ++ ++#: ../src/jarabe/journal/expandedentry.py:386 ++#, python-format ++msgid "Kind: %s" ++msgstr "" ++ ++#: ../src/jarabe/journal/expandedentry.py:387 ++#, python-format ++msgid "Date: %s" ++msgstr "Azmez: %s" ++ ++#: ../src/jarabe/journal/expandedentry.py:388 ++#, python-format ++msgid "Size: %s" ++msgstr "TaÉ£zi : %s." ++ ++#: ../src/jarabe/journal/expandedentry.py:412 ++#: ../src/jarabe/journal/misc.py:131 ++msgid "No date" ++msgstr "Ulac azemz" ++ ++#: ../src/jarabe/journal/expandedentry.py:421 ++msgid "Participants:" ++msgstr "" ++ ++#: ../src/jarabe/journal/expandedentry.py:459 ++msgid "Description:" ++msgstr "Aglam" ++ ++#: ../src/jarabe/journal/expandedentry.py:465 ++msgid "Tags:" ++msgstr "Ticraá¸:" ++ ++#: ../src/jarabe/journal/expandedentry.py:470 ++msgid "Comments:" ++msgstr "Iwenniten:" ++ ++#: ../src/jarabe/journal/journalactivity.py:182 ++#: ../src/jarabe/journal/journaltoolbox.py:94 ++#: ../src/jarabe/journal/palettes.py:260 ++#: ../src/jarabe/journal/volumestoolbar.py:349 ++#: ../src/jarabe/view/viewhelp.py:79 ++msgid "Journal" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:103 ++msgid "Favorite entries" ++msgstr "" ++ ++#. TRANS: Item on a palette that filters by entry type. ++#: ../src/jarabe/journal/journaltoolbox.py:112 ++#: ../src/jarabe/journal/journaltoolbox.py:403 ++#: ../src/jarabe/journal/journaltoolbox.py:479 ++msgid "Anything" ++msgstr "Yal taÉ£awsa" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:118 ++#: ../src/jarabe/journal/journaltoolbox.py:165 ++#: ../src/jarabe/journal/journaltoolbox.py:483 ++msgid "Anytime" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:172 ++msgid "Since yesterday" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:175 ++msgid "Past week" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:178 ++msgid "Past month" ++msgstr "Aggur yezrin" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:181 ++msgid "Past year" ++msgstr "Aseggas yezrin" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:521 ++#: ../src/jarabe/journal/palettes.py:105 ++msgid "Copy to" ++msgstr "NÉ£el ar" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:529 ++#: ../src/jarabe/journal/palettes.py:116 ../src/jarabe/view/viewsource.py:379 ++msgid "Duplicate" ++msgstr "Sleg" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:535 ++msgid "Refresh" ++msgstr "Sismeá¸" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:577 ++#: ../src/jarabe/journal/palettes.py:156 ../src/jarabe/journal/palettes.py:374 ++#: ../src/jarabe/journal/volumestoolbar.py:312 ++#, python-format ++msgid "Error while copying the entry. %s" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:578 ++#: ../src/jarabe/journal/palettes.py:157 ../src/jarabe/journal/palettes.py:375 ++#: ../src/jarabe/journal/volumestoolbar.py:313 ++msgid "Error" ++msgstr "Tuccá¸a" ++ ++#. TRANS: Action label for starting an entry. ++#: ../src/jarabe/journal/journaltoolbox.py:662 ++#: ../src/jarabe/journal/palettes.py:86 ++msgid "Start" ++msgstr "Exécuté le" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:682 ++#: ../src/jarabe/journal/palettes.py:100 ../src/jarabe/journal/palettes.py:513 ++msgid "No activity to start entry" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:700 ++msgid "Sort view" ++msgstr "Smizzwer timeẓri" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:711 ++msgid "Sort by date modified" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:712 ++msgid "Sort by date created" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:713 ++msgid "Sort by size" ++msgstr "Smizzwer s" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:778 ++msgid "Deselect all" ++msgstr "Kkes afran i meṛṛa" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:791 ++msgid "Select all" ++msgstr "Fren kulec" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:817 ++#, python-format ++msgid "Do you want to erase %d entry?" ++msgid_plural "Do you want to erase %d entries?" ++msgstr[0] "" ++msgstr[1] "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:831 ++#: ../src/jarabe/journal/palettes.py:378 ++msgid "Copy" ++msgstr "NÉ£el" ++ ++#. TRANS: Do not translate %(selected)d and %(total)d. ++#: ../src/jarabe/journal/journaltoolbox.py:882 ++#, python-format ++msgid "Selected %(selected)d of %(total)d" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:917 ++msgid "Select filter" ++msgstr "" ++ ++#: ../src/jarabe/journal/listview.py:473 ../src/jarabe/journal/iconview.py:212 ++msgid "Your Journal is empty" ++msgstr "" ++ ++#: ../src/jarabe/journal/listview.py:476 ../src/jarabe/journal/iconview.py:215 ++msgid "Your documents folder is empty" ++msgstr "" ++ ++#: ../src/jarabe/journal/listview.py:478 ../src/jarabe/journal/iconview.py:217 ++msgid "The device is empty" ++msgstr "" ++ ++#: ../src/jarabe/journal/listview.py:480 ../src/jarabe/journal/iconview.py:220 ++msgid "No matching entries" ++msgstr "" ++ ++#: ../src/jarabe/journal/misc.py:313 ++#, python-format ++msgid "Older Version Of %s Activity" ++msgstr "" ++ ++#: ../src/jarabe/journal/misc.py:314 ++#, python-format ++msgid "Do you want to downgrade to version %s" ++msgstr "" ++ ++#: ../src/jarabe/journal/modalalert.py:63 ++msgid "Your Journal is full" ++msgstr "" ++ ++#: ../src/jarabe/journal/modalalert.py:68 ++msgid "Please delete some old Journal entries to make space for new ones." ++msgstr "" ++ ++#: ../src/jarabe/journal/modalalert.py:82 ++msgid "Show Journal" ++msgstr "" ++ ++#: ../src/jarabe/journal/objectchooser.py:171 ++msgid "Choose an object" ++msgstr "" ++ ++#: ../src/jarabe/journal/objectchooser.py:176 ++#, python-format ++msgid "Choose an object to open with %s activity" ++msgstr "" ++ ++#: ../src/jarabe/journal/objectchooser.py:184 ++#: ../src/jarabe/view/viewhelp.py:335 ../src/jarabe/view/viewsource.py:579 ++msgid "Close" ++msgstr "Mdel" ++ ++#: ../src/jarabe/journal/palettes.py:84 ++msgid "Resume with" ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:87 ++msgid "Start with" ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:124 ++msgid "Send to" ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:133 ++msgid "View Details" ++msgstr "Wali talqayt" ++ ++#: ../src/jarabe/journal/palettes.py:193 ++msgid "Entries without a file cannot be sent." ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:272 ++#: ../src/jarabe/journal/volumestoolbar.py:214 ++msgid "Documents" ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:363 ../src/jarabe/journal/palettes.py:423 ++#: ../src/jarabe/journal/volumestoolbar.py:303 ++msgid "Entries without a file cannot be copied." ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:383 ++#, python-format ++msgid "Do you want to copy %d entry?" ++msgid_plural "Do you want to copy %d entries?" ++msgstr[0] "" ++msgstr[1] "" ++ ++#: ../src/jarabe/journal/palettes.py:408 ++msgid "Clipboard" ++msgstr "Æ”ef afus" ++ ++#: ../src/jarabe/journal/palettes.py:478 ++msgid "No friends present" ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:483 ++msgid "No valid connection found" ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:511 ++msgid "No activity to resume entry" ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:580 ../src/jarabe/view/palettes.py:133 ++msgid "Stop" ++msgstr "Seḥbes" ++ ++#: ../src/jarabe/journal/palettes.py:585 ++#: ../extensions/cpsection/backup/view.py:212 ++#: ../extensions/cpsection/backup/view.py:265 ++msgid "Continue" ++msgstr "Kemmel" ++ ++#: ../src/jarabe/journal/palettes.py:622 ++#, python-format ++msgid "%(index)d of %(total)d : %(object_title)s" ++msgstr "" ++ ++#: ../src/jarabe/journal/volumestoolbar.py:375 ++#: ../src/jarabe/view/palettes.py:251 ../src/jarabe/view/palettes.py:317 ++#, python-format ++msgid "%(free_space)d MB Free" ++msgstr "" ++ ++#: ../src/jarabe/model/desktop.py:85 ++#, python-format ++msgid "Favorites view %d" ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:217 ++msgid "The reason for the device state change is unknown." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:219 ++msgid "The state change is normal." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:221 ++msgid "The device is now managed." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:223 ++msgid "The device is no longer managed." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:225 ++msgid "The device could not be readied for configuration." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:227 ++msgid "" ++"IP configuration could not be reserved (no available address, timeout, etc)." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:230 ++msgid "The IP configuration is no longer valid." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:232 ++msgid "Secrets were required, but not provided." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:234 ++msgid "" ++"The 802.1X supplicant disconnected from the access point or authentication " ++"server." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:237 ++msgid "Configuration of the 802.1X supplicant failed." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:239 ++msgid "The 802.1X supplicant quit or failed unexpectedly." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:241 ++msgid "The 802.1X supplicant took too long to authenticate." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:243 ++msgid "The PPP service failed to start within the allowed time." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:245 ++msgid "The PPP service disconnected unexpectedly." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:247 ++msgid "The PPP service quit or failed unexpectedly." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:249 ++msgid "The DHCP service failed to start within the allowed time." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:251 ++msgid "The DHCP service reported an unexpected error." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:253 ++msgid "The DHCP service quit or failed unexpectedly." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:255 ++msgid "The shared connection service failed to start." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:257 ++msgid "The shared connection service quit or failed unexpectedly." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:260 ++msgid "The AutoIP service failed to start." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:262 ++msgid "The AutoIP service reported an unexpected error." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:264 ++msgid "The AutoIP service quit or failed unexpectedly." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:266 ++msgid "Dialing failed because the line was busy." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:268 ++msgid "Dialing failed because there was no dial tone." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:270 ++msgid "Dialing failed because there was no carrier." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:272 ++msgid "Dialing timed out." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:274 ++msgid "Dialing failed." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:276 ++msgid "Modem initialization failed." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:278 ++msgid "Failed to select the specified GSM APN" ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:280 ++msgid "Not searching for networks." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:282 ++msgid "Network registration was denied." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:284 ++msgid "Network registration timed out." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:286 ++msgid "Failed to register with the requested GSM network." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:288 ++msgid "PIN check failed." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:290 ++msgid "Necessary firmware for the device may be missing." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:292 ++msgid "The device was removed." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:294 ++msgid "NetworkManager went to sleep." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:296 ++msgid "The device's active connection was removed or disappeared." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:299 ++msgid "A user or client requested the disconnection." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:301 ++msgid "The device's carrier/link changed." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:303 ++msgid "The device's existing connection was assumed." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:305 ++msgid "The supplicant is now available." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:307 ++msgid "The modem could not be found." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:309 ++msgid "The Bluetooth connection failed or timed out." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:311 ++msgid "Unused." ++msgstr "" ++ ++#: ../src/jarabe/model/screenshot.py:59 ../src/jarabe/view/viewhelp.py:70 ++msgid "Mesh" ++msgstr "" ++ ++#: ../src/jarabe/model/screenshot.py:72 ++msgid "Screenshot" ++msgstr "Tuá¹á¹fa n ugdil" ++ ++#: ../src/jarabe/model/screenshot.py:74 ++#, python-format ++msgid "Screenshot of \"%s\"" ++msgstr "" ++ ++#: ../src/jarabe/view/alerts.py:38 ../src/jarabe/view/alerts.py:48 ++msgid "Activity launcher" ++msgstr "" ++ ++#: ../src/jarabe/view/alerts.py:39 ++#, python-format ++msgid "%s is already running. Please stop %s before launching it again." ++msgstr "" ++ ++#: ../src/jarabe/view/alerts.py:49 ++msgid "" ++"The maximum number of open activities has been reached. Please close an " ++"activity before launching a new one." ++msgstr "" ++ ++#: ../src/jarabe/view/buddymenu.py:73 ++msgid "Remove friend" ++msgstr "" ++ ++#: ../src/jarabe/view/buddymenu.py:76 ++msgid "Make friend" ++msgstr "" ++ ++#: ../src/jarabe/view/buddymenu.py:108 ++msgid "Shutdown" ++msgstr "Sexsi" ++ ++#: ../src/jarabe/view/buddymenu.py:113 ++msgid "Restart" ++msgstr "Ales tanekra" ++ ++#: ../src/jarabe/view/buddymenu.py:119 ++msgid "Logout" ++msgstr "TuffÉ£a" ++ ++#: ../src/jarabe/view/buddymenu.py:124 ++msgid "My Settings" ++msgstr "IÉ£ewwaá¹›en-iw" ++ ++#: ../src/jarabe/view/buddymenu.py:183 ++#, python-format ++msgid "Invite to %s" ++msgstr "" ++ ++#: ../src/jarabe/view/launcher.py:159 ++#, python-format ++msgid "<b>%s</b> failed to start." ++msgstr "" ++ ++#: ../src/jarabe/view/palettes.py:53 ++msgid "Starting..." ++msgstr "Tanekra..." ++ ++#: ../src/jarabe/view/palettes.py:63 ++msgid "Activity failed to start" ++msgstr "" ++ ++#. TODO: share-with, keep ++#: ../src/jarabe/view/palettes.py:105 ++msgid "View Source" ++msgstr "Sken aÉ£balu" ++ ++#: ../src/jarabe/view/palettes.py:112 ++msgid "View Help" ++msgstr "Wali asebter n tallelt" ++ ++#: ../src/jarabe/view/palettes.py:179 ++msgid "Start new" ++msgstr "" ++ ++#: ../src/jarabe/view/palettes.py:266 ++msgctxt "Volume" ++msgid "Remove" ++msgstr "Kkes" ++ ++#: ../src/jarabe/view/viewhelp.py:304 ++msgid "Help Manual" ++msgstr "" ++ ++#: ../src/jarabe/view/viewhelp.py:318 ++msgid "Social Help" ++msgstr "" ++ ++#: ../src/jarabe/view/viewhelp.py:326 ++#, python-format ++msgid "Help: %s" ++msgstr "" ++ ++#: ../src/jarabe/view/viewsource.py:364 ++msgid "Instance Source" ++msgstr "" ++ ++#: ../src/jarabe/view/viewsource.py:392 ++#, python-format ++msgid "Do you want to duplicate %s Activity?" ++msgstr "" ++ ++#: ../src/jarabe/view/viewsource.py:394 ++msgid "This may take a few minutes" ++msgstr "" ++ ++#: ../src/jarabe/view/viewsource.py:408 ++msgid "Duplicating activity..." ++msgstr "" ++ ++#: ../src/jarabe/view/viewsource.py:447 ++msgid "Duplicated" ++msgstr "" ++ ++#: ../src/jarabe/view/viewsource.py:448 ++msgid "The activity has been duplicated" ++msgstr "" ++ ++#: ../src/jarabe/view/viewsource.py:462 ++msgid "Duplicated activity already exists" ++msgstr "" ++ ++#: ../src/jarabe/view/viewsource.py:463 ++msgid "Delete your copy before trying to duplicate the activity again" ++msgstr "" ++ ++#: ../src/jarabe/view/viewsource.py:478 ++msgid "Source" ++msgstr "Aqbalu" ++ ++#: ../src/jarabe/view/viewsource.py:542 ++msgid "Activity Bundle Source" ++msgstr "" ++ ++#: ../src/jarabe/view/viewsource.py:561 ++msgid "Sugar Toolkit Source" ++msgstr "" ++ ++#: ../src/jarabe/view/viewsource.py:568 ++#, python-format ++msgid "View source: %s" ++msgstr "" ++ ++#: ../src/jarabe/view/viewsource.py:569 ++#, python-format ++msgid "View source: %r" ++msgstr "" ++ ++#: ../src/jarabe/view/viewsource.py:809 ++msgid "Please select a file in the left panel." ++msgstr "" ++ ++#: ../extensions/cpsection/backup/__init__.py:22 ++msgid "Backup" ++msgstr "Sekles" ++ ++#: ../extensions/cpsection/backup/backends/volume.py:61 ++#: ../extensions/cpsection/backup/backends/volume.py:171 ++msgid "Please connect a device to continue" ++msgstr "" ++ ++#: ../extensions/cpsection/backup/backends/volume.py:69 ++#: ../extensions/cpsection/backup/backends/volume.py:178 ++msgid "Select your volume" ++msgstr "" ++ ++#: ../extensions/cpsection/backup/backends/volume.py:78 ++msgid "Not enough space in volume" ++msgstr "" ++ ++#: ../extensions/cpsection/backup/backends/volume.py:122 ++#, python-format ++msgid "Backup from user %s" ++msgstr "" ++ ++#: ../extensions/cpsection/backup/backends/volume.py:191 ++msgid "No checkpoints found in the device" ++msgstr "" ++ ++#: ../extensions/cpsection/backup/backends/volume.py:199 ++msgid "Select your checkpoint" ++msgstr "" ++ ++#: ../extensions/cpsection/backup/backends/volume.py:210 ++msgid "Not enough space in disk" ++msgstr "" ++ ++#: ../extensions/cpsection/backup/backends/volume.py:329 ++msgid "Local Device Backup" ++msgstr "" ++ ++#: ../extensions/cpsection/backup/view.py:133 ++msgid "Save the contents of your Journal" ++msgstr "" ++ ++#: ../extensions/cpsection/backup/view.py:141 ++msgid "Restore the contents of your Journal" ++msgstr "" ++ ++#: ../extensions/cpsection/backup/view.py:223 ++msgid "Please close all the activities, and start again" ++msgstr "" ++ ++#: ../extensions/cpsection/backup/view.py:229 ++msgid "Select where you want create your backup" ++msgstr "" ++ ++#: ../extensions/cpsection/backup/view.py:231 ++msgid "Select where you want retrieve your restore" ++msgstr "" ++ ++#: ../extensions/cpsection/backup/view.py:271 ++msgid "Retry" ++msgstr "ÆrefÌ£ tikelt-nniá¸en" ++ ++#: ../extensions/cpsection/backup/view.py:290 ++msgid "Starting backup..." ++msgstr "Asenker n uḥraz..." ++ ++#: ../extensions/cpsection/backup/view.py:294 ++msgid "Starting restore..." ++msgstr "Asenker n tririt..." ++ ++#: ../extensions/cpsection/backup/view.py:321 ++msgid "" ++"I want to restore the content of my Journal. In order to do this, my Journal " ++"will first be emptied of all its content; then the restored content will be " ++"added." ++msgstr "" ++ ++#: ../extensions/cpsection/backup/view.py:327 ++msgid "Confirm" ++msgstr "Sentem" ++ ++#: ../extensions/cpsection/backup/view.py:365 ++msgid "Operation started" ++msgstr "Tamhelt tebda" ++ ++#: ../extensions/cpsection/backup/view.py:377 ++msgid "Backup finished successfully" ++msgstr "" ++ ++#: ../extensions/cpsection/backup/view.py:379 ++msgid "Restore realized successfully." ++msgstr "" ++ ++#: ../src/jarabe/frame/notification.py:62 ++msgid "Clear notifications" ++msgstr "SfeḠilÉ£a" +diff --git b/po/sr@latin.po a/po/sr@latin.po +new file mode 100644 +index 0000000..669d03d +--- /dev/null ++++ a/po/sr@latin.po +@@ -0,0 +1,1935 @@ ++# SOME DESCRIPTIVE TITLE. ++# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER ++# This file is distributed under the same license as the PACKAGE package. ++# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. ++msgid "" ++msgstr "" ++"Project-Id-Version: PACKAGE VERSION\n" ++"Report-Msgid-Bugs-To: \n" ++"POT-Creation-Date: 2013-07-31 00:33-0400\n" ++"PO-Revision-Date: 2013-06-18 20:00+0200\n" ++"Last-Translator: Chris <cjl@laptop.org>\n" ++"Language-Team: LANGUAGE <LL@li.org>\n" ++"Language: sr@latin\n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=UTF-8\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%" ++"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" ++"X-Generator: Pootle 2.0.5\n" ++ ++#: ../extensions/cpsection/aboutme/__init__.py:24 ++msgid "About Me" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutme/model.py:48 ++msgid "You must enter a name." ++msgstr "" ++ ++#: ../extensions/cpsection/aboutme/model.py:75 ++#, python-format ++msgid "stroke: color=%s hue=%s" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutme/model.py:78 ++#, python-format ++msgid "stroke: %s" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutme/model.py:80 ++#, python-format ++msgid "fill: color=%s hue=%s" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutme/model.py:82 ++#, python-format ++msgid "fill: %s" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutme/model.py:94 ++msgid "Error in specified color modifiers." ++msgstr "" ++ ++#: ../extensions/cpsection/aboutme/model.py:97 ++msgid "Error in specified colors." ++msgstr "" ++ ++#: ../extensions/cpsection/aboutme/view.py:212 ++msgid "Click to change your color:" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutcomputer/__init__.py:21 ++msgid "About my Computer" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutcomputer/model.py:42 ++msgid "Not available" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:60 ++msgid "Identity" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:69 ++msgid "Serial Number:" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:91 ++msgid "Software" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:100 ++msgid "Build:" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:115 ++msgid "Sugar:" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:130 ++msgid "Firmware:" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:145 ++msgid "Wireless Firmware:" ++msgstr "" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:168 ++msgid "Copyright and License" ++msgstr "" ++ ++#. TRANS: The word "Sugar" should not be translated. ++#: ../extensions/cpsection/aboutcomputer/view.py:187 ++msgid "" ++"Sugar is the graphical user interface that you are looking at. Sugar is free " ++"software, covered by the GNU General Public License, and you are welcome to " ++"change it and/or distribute copies of it under certain conditions described " ++"therein." ++msgstr "" ++ ++#: ../extensions/cpsection/aboutcomputer/view.py:199 ++msgid "Full license:" ++msgstr "" ++ ++#: ../extensions/cpsection/background/__init__.py:21 ++msgid "Background" ++msgstr "Pozadina" ++ ++#: ../extensions/cpsection/background/view.py:39 ++msgid "Select a background:" ++msgstr "" ++ ++#: ../extensions/cpsection/background/view.py:46 ++msgid "Clear background" ++msgstr "" ++ ++#: ../extensions/cpsection/datetime/__init__.py:21 ++msgid "Date & Time" ++msgstr "" ++ ++#: ../extensions/cpsection/datetime/model.py:92 ++msgid "Error timezone does not exist." ++msgstr "" ++ ++#: ../extensions/cpsection/datetime/view.py:66 ../data/sugar.schemas.in.h:61 ++msgid "Timezone" ++msgstr "" ++ ++#: ../extensions/cpsection/frame/__init__.py:21 ++msgid "Frame" ++msgstr "" ++ ++#: ../extensions/cpsection/frame/model.py:41 ++#: ../extensions/cpsection/frame/model.py:66 ++msgid "Value must be an integer." ++msgstr "" ++ ++#: ../extensions/cpsection/frame/view.py:27 ++msgid "never" ++msgstr "" ++ ++#: ../extensions/cpsection/frame/view.py:28 ++msgid "instantaneous" ++msgstr "" ++ ++#: ../extensions/cpsection/frame/view.py:29 ++#, python-format ++msgid "%s seconds" ++msgstr "" ++ ++#: ../extensions/cpsection/frame/view.py:54 ++msgid "Activation Delay" ++msgstr "" ++ ++#: ../extensions/cpsection/frame/view.py:78 ++msgid "Corner" ++msgstr "" ++ ++#: ../extensions/cpsection/frame/view.py:114 ++msgid "Edge" ++msgstr "" ++ ++#: ../extensions/cpsection/keyboard/__init__.py:21 ++#: ../extensions/cpsection/keyboard/view.py:38 ++msgid "Keyboard" ++msgstr "" ++ ++#: ../extensions/cpsection/keyboard/view.py:240 ++msgid "Keyboard Model" ++msgstr "" ++ ++#: ../extensions/cpsection/keyboard/view.py:301 ++msgid "Key(s) to change layout" ++msgstr "" ++ ++#: ../extensions/cpsection/keyboard/view.py:369 ++msgid "Keyboard Layout(s)" ++msgstr "" ++ ++#: ../extensions/cpsection/language/__init__.py:21 ++#: ../extensions/cpsection/language/view.py:33 ++msgid "Language" ++msgstr "" ++ ++#: ../extensions/cpsection/language/model.py:30 ++msgid "Could not access ~/.i18n. Create standard settings." ++msgstr "" ++ ++#: ../extensions/cpsection/language/model.py:129 ++#, python-format ++msgid "Language for code=%s could not be determined." ++msgstr "" ++ ++#: ../extensions/cpsection/language/model.py:152 ++#, python-format ++msgid "Sorry I do not speak '%s'." ++msgstr "" ++ ++#: ../extensions/cpsection/language/view.py:57 ++msgid "" ++"Add languages in the order you prefer. If a translation is not available, " ++"the next in the list will be used." ++msgstr "" ++ ++#: ../extensions/cpsection/modemconfiguration/__init__.py:21 ++msgid "Modem Configuration" ++msgstr "" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:94 ++msgid "" ++"You will need to provide the following information to set up a mobile " ++"broadband connection to a cellular (3G) network." ++msgstr "" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:117 ++msgid "Country:" ++msgstr "" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:118 ++msgid "Provider:" ++msgstr "" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:119 ++msgid "Plan:" ++msgstr "" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:160 ++msgid "Username:" ++msgstr "" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:167 ++msgid "Password:" ++msgstr "" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:174 ++msgid "Number:" ++msgstr "" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:181 ++msgid "Access Point Name (APN):" ++msgstr "" ++ ++#: ../extensions/cpsection/modemconfiguration/view.py:188 ++msgid "Personal Identity Number (PIN):" ++msgstr "" ++ ++#: ../extensions/cpsection/modemconfiguration/model.py:161 ++#, python-format ++msgid "Plan #%s" ++msgstr "" ++ ++#: ../extensions/cpsection/modemconfiguration/model.py:291 ++#, python-format ++msgid "Provider %s" ++msgstr "" ++ ++#: ../extensions/cpsection/network/__init__.py:21 ++#: ../extensions/cpsection/network/view.py:30 ++msgid "Network" ++msgstr "" ++ ++#: ../extensions/cpsection/network/model.py:73 ++msgid "State is unknown." ++msgstr "" ++ ++#: ../extensions/cpsection/network/model.py:101 ++msgid "Error in specified radio argument use on/off." ++msgstr "" ++ ++#: ../extensions/cpsection/network/model.py:152 ++msgid "Error in specified argument use 0/1." ++msgstr "" ++ ++#: ../extensions/cpsection/network/view.py:68 ++msgid "Wireless" ++msgstr "" ++ ++#: ../extensions/cpsection/network/view.py:77 ++msgid "Turn off the wireless radio to save battery life" ++msgstr "" ++ ++#: ../extensions/cpsection/network/view.py:90 ++msgid "Radio" ++msgstr "" ++ ++#: ../extensions/cpsection/network/view.py:106 ++msgid "Discard network history if you have trouble connecting to the network" ++msgstr "" ++ ++#: ../extensions/cpsection/network/view.py:115 ++msgid "Discard network history" ++msgstr "" ++ ++#: ../extensions/cpsection/network/view.py:131 ++msgid "Collaboration" ++msgstr "" ++ ++#: ../extensions/cpsection/network/view.py:139 ++msgid "" ++"The server is the equivalent of what room you are in; people on the same " ++"server will be able to see each other, even when they aren't on the same " ++"network." ++msgstr "" ++ ++#: ../extensions/cpsection/network/view.py:149 ++msgid "Server:" ++msgstr "" ++ ++#: ../extensions/cpsection/power/__init__.py:21 ++msgid "Power" ++msgstr "" ++ ++#: ../extensions/cpsection/power/model.py:90 ++msgid "Error in automatic pm argument, use on/off." ++msgstr "" ++ ++#: ../extensions/cpsection/power/view.py:45 ++msgid "Power management" ++msgstr "" ++ ++#: ../extensions/cpsection/power/view.py:55 ../data/sugar.schemas.in.h:5 ++msgid "Automatic power management (increases battery life)" ++msgstr "" ++ ++#: ../extensions/cpsection/updater/__init__.py:21 ++msgid "Software Update" ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:65 ++msgid "" ++"Software updates correct errors, eliminate security vulnerabilities, and " ++"provide new features." ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:79 ++msgid "Update in progress..." ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:106 ++msgid "Checking for updates..." ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:108 ++msgid "Installing updates..." ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:137 ++#, python-format ++msgid "Checking %s..." ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:139 ++msgid "Looking for updates..." ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:141 ++#, python-format ++msgid "Downloading %s..." ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:143 ++#, python-format ++msgid "Updating %s..." ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:153 ++msgid "Your software is up-to-date" ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:155 ++#, python-format ++msgid "You can install %s update" ++msgid_plural "You can install %s updates" ++msgstr[0] "" ++msgstr[1] "" ++msgstr[2] "" ++ ++#: ../extensions/cpsection/updater/view.py:184 ++#, python-format ++msgid "%s update was installed" ++msgid_plural "%s updates were installed" ++msgstr[0] "" ++msgstr[1] "" ++msgstr[2] "" ++ ++#: ../extensions/cpsection/updater/view.py:266 ++msgid "Install selected" ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:284 ++#, python-format ++msgid "Download size: %s" ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:373 ++#, python-format ++msgid "From version %(current)s to %(new)s (Size: %(size)s)" ++msgstr "" ++ ++#: ../extensions/cpsection/updater/view.py:380 ++#, python-format ++msgid "Version %(version)s (Size: %(size)s)" ++msgstr "" ++ ++#. TRANS: download size is 0 ++#: ../extensions/cpsection/updater/view.py:397 ++msgid "None" ++msgstr "" ++ ++#. TRANS: download size of very small updates ++#: ../extensions/cpsection/updater/view.py:400 ++msgid "1 KB" ++msgstr "" ++ ++#. TRANS: download size of small updates, e.g. '250 KB' ++#: ../extensions/cpsection/updater/view.py:403 ++#, python-format ++msgid "%.0f KB" ++msgstr "" ++ ++#. TRANS: download size of updates, e.g. '2.3 MB' ++#: ../extensions/cpsection/updater/view.py:406 ++#, python-format ++msgid "%.1f MB" ++msgstr "" ++ ++#: ../extensions/cpsection/webaccount/__init__.py:24 ++msgid "Configure your Web Services" ++msgstr "" ++ ++#: ../extensions/cpsection/webaccount/view.py:42 ++#, python-format ++msgid "" ++"No web services are installed.\n" ++"Please visit %s for more details." ++msgstr "" ++ ++#: ../extensions/deviceicon/battery.py:71 ++msgid "My Battery" ++msgstr "" ++ ++#: ../extensions/deviceicon/battery.py:153 ++msgid "Removed" ++msgstr "" ++ ++#: ../extensions/deviceicon/battery.py:156 ++msgid "Charging" ++msgstr "" ++ ++#: ../extensions/deviceicon/battery.py:159 ++msgid "Very little power remaining" ++msgstr "" ++ ++#. TRANS: do not translate %(hour)d:%(min).2d it is a variable, ++#. only translate the word "remaining" ++#: ../extensions/deviceicon/battery.py:166 ++#, python-format ++msgid "%(hour)d:%(min).2d remaining" ++msgstr "" ++ ++#: ../extensions/deviceicon/battery.py:169 ++msgid "Charged" ++msgstr "" ++ ++#: ../extensions/deviceicon/frame.py:56 ++msgid "Show my keyboard" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:50 ++#, python-format ++msgid "IP address: %s" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:82 ++#: ../extensions/deviceicon/network.py:298 ++#: ../src/jarabe/desktop/networkviews.py:135 ++#: ../src/jarabe/desktop/networkviews.py:509 ++msgid "Disconnect" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:107 ++#: ../extensions/deviceicon/network.py:290 ++#: ../src/jarabe/desktop/networkviews.py:251 ++#: ../src/jarabe/desktop/networkviews.py:551 ++#: ../src/jarabe/desktop/networkviews.py:693 ++msgid "Connecting..." ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:112 ++#: ../extensions/deviceicon/network.py:180 ++#: ../src/jarabe/desktop/networkviews.py:258 ++#: ../src/jarabe/desktop/networkviews.py:557 ++#: ../src/jarabe/desktop/networkviews.py:699 ++msgid "Connected" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:125 ++msgid "No wireless connection" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:139 ++msgid "Channel" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:154 ++msgid "Wired Network" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:183 ++msgid "Speed" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:208 ++msgid "Wireless modem" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:276 ++msgid "Please wait..." ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:281 ++#: ../src/jarabe/desktop/networkviews.py:129 ++#: ../src/jarabe/desktop/networkviews.py:503 ++#: ../src/jarabe/desktop/networkviews.py:644 ++msgid "Connect" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:282 ++msgid "Disconnected" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:289 ++#: ../src/jarabe/controlpanel/toolbar.py:121 ++#: ../src/jarabe/desktop/keydialog.py:101 ++#: ../src/jarabe/frame/activitiestray.py:625 ++#: ../src/jarabe/frame/activitiestray.py:746 ++#: ../src/jarabe/frame/activitiestray.py:778 ++#: ../src/jarabe/journal/expandedentry.py:159 ++#: ../src/jarabe/journal/journaltoolbox.py:480 ++#: ../src/jarabe/journal/palettes.py:159 ++msgid "Cancel" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:328 ++msgid "Try connection again" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:331 ++#, python-format ++msgid "Error: %s" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:335 ++#, python-format ++msgid "Suggestion: %s" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:344 ++#, python-format ++msgid "Connected for %s" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:350 ++#: ../extensions/deviceicon/network.py:351 ++#, python-format ++msgid "%d KB" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:356 ++msgid "Check your PIN/PUK configuration." ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:359 ++msgid "Check your Access Point Name (APN) configuration" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:363 ++msgid "Check the Number configuration." ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:365 ++msgid "Check your configuration." ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:621 ++msgid "Mesh Network" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:668 ++#, python-format ++msgid "Mesh Network %s" ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:788 ++msgid "No GSM connection available." ++msgstr "" ++ ++#: ../extensions/deviceicon/network.py:789 ++msgid "Create a connection in the control panel." ++msgstr "" ++ ++#: ../extensions/deviceicon/speech.py:52 ++msgid "Speech" ++msgstr "" ++ ++#: ../extensions/deviceicon/speech.py:76 ++#: ../extensions/deviceicon/speech.py:150 ++#: ../extensions/deviceicon/speech.py:155 ++msgid "Say selected text" ++msgstr "" ++ ++#: ../extensions/deviceicon/speech.py:83 ++msgid "Stop playback" ++msgstr "" ++ ++#: ../extensions/deviceicon/speech.py:92 ++msgid "Pitch" ++msgstr "" ++ ++#: ../extensions/deviceicon/speech.py:107 ++msgid "Rate" ++msgstr "" ++ ++#: ../extensions/deviceicon/speech.py:145 ++msgid "Pause playback" ++msgstr "" ++ ++#: ../extensions/deviceicon/speaker.py:61 ++msgid "My Speakers" ++msgstr "" ++ ++#: ../extensions/deviceicon/speaker.py:136 ++msgid "Unmute" ++msgstr "" ++ ++#: ../extensions/deviceicon/speaker.py:139 ++msgid "Mute" ++msgstr "" ++ ++#: ../extensions/deviceicon/touchpad.py:38 ++msgid "finger" ++msgstr "" ++ ++#: ../extensions/deviceicon/touchpad.py:38 ++msgid "stylus" ++msgstr "" ++ ++#: ../extensions/deviceicon/touchpad.py:64 ++msgid "My touchpad" ++msgstr "" ++ ++#: ../extensions/deviceicon/volume.py:72 ../src/jarabe/view/palettes.py:184 ++msgid "Show contents" ++msgstr "" ++ ++#: ../extensions/globalkey/screenshot.py:61 ++msgid "Mesh" ++msgstr "" ++ ++#: ../extensions/globalkey/screenshot.py:63 ++#: ../src/jarabe/desktop/homewindow.py:221 ++#: ../src/jarabe/frame/zoomtoolbar.py:53 ++msgid "Group" ++msgstr "" ++ ++#: ../extensions/globalkey/screenshot.py:65 ++#: ../src/jarabe/desktop/homewindow.py:214 ++#: ../src/jarabe/desktop/viewtoolbar.py:73 ++#: ../src/jarabe/frame/zoomtoolbar.py:57 ++msgid "Home" ++msgstr "" ++ ++#: ../extensions/globalkey/screenshot.py:71 ++#: ../src/jarabe/frame/zoomtoolbar.py:62 ++msgid "Activity" ++msgstr "" ++ ++#: ../extensions/globalkey/screenshot.py:74 ++msgid "Screenshot" ++msgstr "" ++ ++#: ../extensions/globalkey/screenshot.py:76 ++#, python-format ++msgid "Screenshot of \"%s\"" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:1 ++msgid "" ++"\"disabled\" to ask nick on initialization; \"system\" to reuse UNIX account " ++"long name." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:2 ++msgid "" ++"A unix timestamp (seconds since epoch) of the last successful activity " ++"update." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:3 ++msgid "" ++"Activity update backend module, followed by a period, followed by the class " ++"name." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:4 ++msgid "Activity update backend." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:6 ++msgid "Automatic update frequency." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:7 ++msgid "Backup URL" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:8 ++msgid "Bundle IDs of protected activities" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:9 ++msgid "" ++"Color for the XO icon that is used throughout the desktop. The string is " ++"composed of the stroke color and fill color, format is that of rgb colors. " ++"Example: #AC32FF,#9A5200" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:10 ++msgid "Corner Delay" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:11 ++msgid "Default font face" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:12 ++msgid "Default font size" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:13 ++msgid "Default nick" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:14 ++msgid "Delay for the activation of the frame using the corners." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:15 ++msgid "Delay for the activation of the frame using the edges." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:16 ++msgid "Edge Delay" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:17 ++msgid "" ++"Extreme power management (disables wireless radio, increases battery life)" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:18 ++msgid "Favorites Layout" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:19 ++msgid "Favorites resume mode" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:20 ++msgid "Font face that is used throughout the desktop." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:21 ++msgid "Font size that is used throughout the desktop." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:22 ++msgid "" ++"Frequency of automatic activity updates, measured in days. 0 means disabled." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:23 ++msgid "GSM network APN (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:24 ++msgid "GSM network PIN (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:25 ++msgid "GSM network PUK (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:26 ++msgid "GSM network access point name configuration (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:27 ++msgid "GSM network number (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:28 ++msgid "GSM network password (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:29 ++msgid "GSM network password configuration (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:30 ++msgid "" ++"GSM network personal identification number configuration (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:31 ++msgid "GSM network personal unlock key configuration (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:32 ++msgid "GSM network telephone number configuration (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:33 ++msgid "GSM network username (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:34 ++msgid "GSM network username configuration (DEPRECATED/UNUSED)" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:35 ++msgid "" ++"If TRUE, Sugar will make us searchable for the other users of the Jabber " ++"server." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:36 ++msgid "If TRUE, Sugar will show a \"Log out\" option." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:37 ++msgid "If TRUE, Sugar will show a \"Restart\" option." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:38 ++msgid "" ++"If TRUE, Sugar will show default Ad-hoc networks for channel 1,6 and 11. If " ++"Sugar sees no \"known\" network when it starts, it does autoconnect to an Ad-" ++"hoc network." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:39 ++msgid "Jabber Server" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:40 ++msgid "Keyboard layouts" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:41 ++msgid "Keyboard model" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:42 ++msgid "Keyboard options" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:43 ++msgid "Layout of the favorites view." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:44 ++msgid "" ++"List of keyboard layouts. Each entry should be in the form layout(variant)" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:45 ++msgid "List of keyboard options." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:46 ++msgid "Microformat update URL." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:47 ++msgid "Pitch value for the speech sugar service" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:48 ++msgid "Pitch value used by the speech service in Sugar" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:49 ++msgid "Power Automatic" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:50 ++msgid "Power Extreme" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:51 ++msgid "Publish to Gadget" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:52 ++msgid "Rate value for the speech sugar service" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:53 ++msgid "Rate value used by the speech service in Sugar" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:54 ++msgid "Setting for muting the sound device." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:55 ++msgid "Show Log out" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:56 ++msgid "Show Restart" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:57 ++msgid "Show Sugar Ad-hoc networks" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:58 ++msgid "Sound Muted" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:59 ++msgid "The keyboard model to be used" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:60 ++msgid "Timestamp of last activity update." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:62 ++msgid "Timezone setting for the system." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:63 ++msgid "URL of the jabber server to use." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:64 ++msgid "" ++"URL used by the microformat update backend for activity update information." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:65 ++msgid "URL where the backup is saved to." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:66 ++msgid "User Color" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:67 ++msgid "User Name" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:68 ++msgid "User name that is used throughout the desktop." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:69 ++msgid "" ++"Users will not be allowed to erase these activities through the list view." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:70 ++msgid "Volume Level" ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:71 ++msgid "Volume level for the sound device." ++msgstr "" ++ ++#: ../data/sugar.schemas.in.h:72 ++msgid "" ++"When in resume mode, clicking on a favorite icon will cause the last entry " ++"for that activity to be resumed." ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/cmd.py:28 ++#, python-format ++msgid "" ++"sugar-control-panel: WARNING, found more than one option with the same name: " ++"%s module: %r" ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/cmd.py:30 ++#, python-format ++msgid "sugar-control-panel: key=%s not an available option" ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/cmd.py:31 ++#, python-format ++msgid "sugar-control-panel: %s" ++msgstr "" ++ ++#. TRANS: Translators, there's a empty line at the end of this string, ++#. which must appear in the translated string (msgstr) as well. ++#: ../src/jarabe/controlpanel/cmd.py:38 ++msgid "" ++"Usage: sugar-control-panel [ option ] key [ args ... ] \n" ++" Control for the sugar environment. \n" ++" Options: \n" ++" -h show this help message and exit \n" ++" -l list all the available options \n" ++" -h key show information about this key \n" ++" -g key get the current value of the key \n" ++" -s key set the current value for the key \n" ++" -c key clear the current value for the key \n" ++" " ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/cmd.py:52 ++msgid "To apply your changes you have to restart Sugar.\n" ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/gui.py:323 ../src/jarabe/journal/palettes.py:187 ++#: ../src/jarabe/journal/palettes.py:350 ../src/jarabe/journal/palettes.py:410 ++#: ../src/jarabe/journal/volumestoolbar.py:302 ++msgid "Warning" ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/gui.py:324 ++#: ../src/jarabe/controlpanel/sectionview.py:41 ++msgid "Changes require restart" ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/gui.py:328 ++msgid "Cancel changes" ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/gui.py:333 ++msgid "Later" ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/gui.py:337 ++msgid "Restart now" ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/toolbar.py:56 ++#: ../src/jarabe/desktop/viewtoolbar.py:129 ++#: ../src/jarabe/journal/journaltoolbox.py:89 ++#, python-format ++msgid "Search in %s" ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/toolbar.py:56 ++msgid "Settings" ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/toolbar.py:65 ../src/jarabe/intro/window.py:211 ++msgid "Done" ++msgstr "" ++ ++#: ../src/jarabe/controlpanel/toolbar.py:127 ++#: ../src/jarabe/desktop/favoritesview.py:374 ++#: ../src/jarabe/desktop/keydialog.py:105 ++msgid "Ok" ++msgstr "" ++ ++#: ../src/jarabe/desktop/activitieslist.py:282 ++#, python-format ++msgid "Version %s" ++msgstr "" ++ ++#: ../src/jarabe/desktop/activitieslist.py:385 ++#: ../src/jarabe/journal/listview.py:475 ../src/jarabe/journal/iconview.py:299 ++msgid "Clear search" ++msgstr "" ++ ++#: ../src/jarabe/desktop/activitieslist.py:469 ++msgid "No matching activities" ++msgstr "" ++ ++#: ../src/jarabe/desktop/activitieslist.py:505 ++msgid "Confirm erase" ++msgstr "" ++ ++#: ../src/jarabe/desktop/activitieslist.py:507 ++#, python-format ++msgid "Confirm erase: Do you want to permanently erase %s?" ++msgstr "" ++ ++#: ../src/jarabe/desktop/activitieslist.py:511 ++#: ../src/jarabe/frame/clipboardmenu.py:65 ++#: ../src/jarabe/view/viewsource.py:288 ++msgid "Keep" ++msgstr "" ++ ++#: ../src/jarabe/desktop/activitieslist.py:514 ++#: ../src/jarabe/desktop/activitieslist.py:578 ++#: ../src/jarabe/journal/expandedentry.py:153 ++#: ../src/jarabe/journal/journaltoolbox.py:443 ++#: ../src/jarabe/journal/journaltoolbox.py:475 ++#: ../src/jarabe/journal/journaltoolbox.py:689 ++#: ../src/jarabe/journal/journaltoolbox.py:695 ++#: ../src/jarabe/journal/palettes.py:132 ../src/jarabe/journal/palettes.py:154 ++msgid "Erase" ++msgstr "" ++ ++#: ../src/jarabe/desktop/activitieslist.py:594 ++msgid "Remove favorite" ++msgstr "" ++ ++#: ../src/jarabe/desktop/activitieslist.py:598 ++msgid "Make favorite" ++msgstr "" ++ ++#. TRANS: label for the freeform layout in the favorites view ++#: ../src/jarabe/desktop/favoriteslayout.py:199 ++msgid "Freeform" ++msgstr "" ++ ++#. TRANS: label for the ring layout in the favorites view ++#: ../src/jarabe/desktop/favoriteslayout.py:295 ++msgid "Ring" ++msgstr "" ++ ++#. TRANS: label for the spiral layout in the favorites view ++#: ../src/jarabe/desktop/favoriteslayout.py:459 ++msgid "Spiral" ++msgstr "" ++ ++#. TRANS: label for the box layout in the favorites view ++#: ../src/jarabe/desktop/favoriteslayout.py:527 ++msgid "Box" ++msgstr "" ++ ++#. TRANS: label for the box layout in the favorites view ++#: ../src/jarabe/desktop/favoriteslayout.py:570 ++msgid "Triangle" ++msgstr "" ++ ++#: ../src/jarabe/desktop/favoritesview.py:365 ++msgid "Registration Failed" ++msgstr "" ++ ++#: ../src/jarabe/desktop/favoritesview.py:368 ++msgid "Registration Successful" ++msgstr "" ++ ++#: ../src/jarabe/desktop/favoritesview.py:369 ++msgid "You are now registered with your school server." ++msgstr "" ++ ++#: ../src/jarabe/desktop/favoritesview.py:653 ++msgid "Register" ++msgstr "" ++ ++#: ../src/jarabe/desktop/favoritesview.py:656 ++#: ../src/jarabe/desktop/favoritesview.py:672 ++msgid "Register again" ++msgstr "" ++ ++#: ../src/jarabe/desktop/homewindow.py:228 ++#: ../src/jarabe/frame/zoomtoolbar.py:49 ++msgid "Neighborhood" ++msgstr "" ++ ++#: ../src/jarabe/desktop/keydialog.py:94 ++#, python-format ++msgid "" ++"A wireless encryption key is required for\n" ++" the wireless network '%s'." ++msgstr "" ++ ++#: ../src/jarabe/desktop/keydialog.py:150 ++msgid "Key Type:" ++msgstr "" ++ ++#: ../src/jarabe/desktop/keydialog.py:170 ++msgid "Authentication Type:" ++msgstr "" ++ ++#: ../src/jarabe/desktop/keydialog.py:233 ++msgid "WPA & WPA2 Personal" ++msgstr "" ++ ++#: ../src/jarabe/desktop/keydialog.py:242 ++msgid "Wireless Security:" ++msgstr "" ++ ++#. TRANS: Action label for resuming an activity. ++#: ../src/jarabe/desktop/meshbox.py:82 ++#: ../src/jarabe/journal/journaltoolbox.py:548 ++#: ../src/jarabe/journal/palettes.py:77 ../src/jarabe/view/palettes.py:96 ++msgid "Resume" ++msgstr "" ++ ++#: ../src/jarabe/desktop/meshbox.py:89 ++#: ../src/jarabe/frame/activitiestray.py:190 ++msgid "Join" ++msgstr "" ++ ++#: ../src/jarabe/desktop/networkviews.py:497 ++#, python-format ++msgid "Ad-hoc Network %d" ++msgstr "" ++ ++#: ../src/jarabe/desktop/networkviews.py:639 ++#, python-format ++msgid "Mesh Network %d" ++msgstr "" ++ ++#: ../src/jarabe/desktop/schoolserver.py:144 ++msgid "Cannot connect to the server." ++msgstr "" ++ ++#: ../src/jarabe/desktop/schoolserver.py:151 ++msgid "The server could not complete the request." ++msgstr "" ++ ++#: ../src/jarabe/desktop/viewtoolbar.py:95 ++msgid "List view" ++msgstr "" ++ ++#: ../src/jarabe/desktop/viewtoolbar.py:97 ++#: ../src/jarabe/desktop/viewtoolbar.py:195 ++#: ../src/jarabe/desktop/viewtoolbar.py:209 ++#, python-format ++msgid "<Ctrl>%d" ++msgstr "" ++ ++#: ../src/jarabe/desktop/viewtoolbar.py:208 ++#, python-format ++msgid "Favorites view %d" ++msgstr "" ++ ++#: ../src/jarabe/frame/activitiestray.py:195 ++#: ../src/jarabe/frame/activitiestray.py:593 ++msgid "Decline" ++msgstr "" ++ ++#: ../src/jarabe/frame/activitiestray.py:534 ++#, python-format ++msgid "%dB" ++msgstr "" ++ ++#: ../src/jarabe/frame/activitiestray.py:536 ++#, python-format ++msgid "%dKB" ++msgstr "" ++ ++#: ../src/jarabe/frame/activitiestray.py:538 ++#, python-format ++msgid "%dMB" ++msgstr "" ++ ++#. TRANS: file transfer, bytes transferred, e.g. 128 of 1024 ++#: ../src/jarabe/frame/activitiestray.py:556 ++#, python-format ++msgid "%s of %s" ++msgstr "" ++ ++#: ../src/jarabe/frame/activitiestray.py:570 ++#, python-format ++msgid "Transfer from %s" ++msgstr "" ++ ++#: ../src/jarabe/frame/activitiestray.py:585 ++msgid "Accept" ++msgstr "" ++ ++#: ../src/jarabe/frame/activitiestray.py:653 ++#: ../src/jarabe/frame/activitiestray.py:666 ++#: ../src/jarabe/frame/activitiestray.py:807 ++msgid "Dismiss" ++msgstr "" ++ ++#: ../src/jarabe/frame/activitiestray.py:680 ++msgid "The other participant canceled the file transfer" ++msgstr "" ++ ++#: ../src/jarabe/frame/activitiestray.py:730 ++#, python-format ++msgid "Transfer to %s" ++msgstr "" ++ ++#: ../src/jarabe/frame/clipboardmenu.py:54 ++msgctxt "Clipboard" ++msgid "Remove" ++msgstr "" ++ ++#: ../src/jarabe/frame/clipboardmenu.py:60 ++#: ../src/jarabe/frame/clipboardmenu.py:83 ++msgid "Open" ++msgstr "" ++ ++#: ../src/jarabe/frame/clipboardmenu.py:88 ++msgid "Open with" ++msgstr "" ++ ++#: ../src/jarabe/frame/clipboardobject.py:50 ++#, python-format ++msgid "%s clipping" ++msgstr "" ++ ++#: ../src/jarabe/frame/zoomtoolbar.py:50 ++msgid "F1" ++msgstr "" ++ ++#: ../src/jarabe/frame/zoomtoolbar.py:54 ++msgid "F2" ++msgstr "" ++ ++#: ../src/jarabe/frame/zoomtoolbar.py:58 ++msgid "F3" ++msgstr "" ++ ++#: ../src/jarabe/frame/zoomtoolbar.py:63 ++msgid "F4" ++msgstr "" ++ ++#: ../src/jarabe/intro/window.py:106 ++msgid "Name:" ++msgstr "" ++ ++#: ../src/jarabe/intro/window.py:136 ++msgid "Click to change color:" ++msgstr "" ++ ++#: ../src/jarabe/intro/window.py:200 ../src/jarabe/journal/detailview.py:95 ++msgid "Back" ++msgstr "" ++ ++#: ../src/jarabe/intro/window.py:214 ++msgid "Next" ++msgstr "" ++ ++#: ../src/jarabe/journal/expandedentry.py:155 ++#: ../src/jarabe/journal/journaltoolbox.py:477 ++#: ../src/jarabe/journal/palettes.py:156 ++#, python-format ++msgid "Do you want to permanently erase \"%s\"?" ++msgstr "" ++ ++#: ../src/jarabe/journal/expandedentry.py:296 ++#: ../src/jarabe/journal/listmodel.py:159 ../src/jarabe/journal/model.py:721 ++#: ../src/jarabe/journal/palettes.py:70 ../src/jarabe/journal/palettes.py:597 ++#: ../src/jarabe/journal/volumestoolbar.py:131 ++#: ../src/jarabe/journal/iconmodel.py:110 ++msgid "Untitled" ++msgstr "" ++ ++#: ../src/jarabe/journal/expandedentry.py:367 ++msgid "No preview" ++msgstr "" ++ ++#: ../src/jarabe/journal/expandedentry.py:382 ++#, python-format ++msgid "Kind: %s" ++msgstr "" ++ ++#: ../src/jarabe/journal/expandedentry.py:382 ++#: ../src/jarabe/journal/listmodel.py:165 ++#: ../src/jarabe/journal/listmodel.py:173 ++msgid "Unknown" ++msgstr "" ++ ++#: ../src/jarabe/journal/expandedentry.py:383 ++#, python-format ++msgid "Date: %s" ++msgstr "" ++ ++#: ../src/jarabe/journal/expandedentry.py:384 ++#, python-format ++msgid "Size: %s" ++msgstr "" ++ ++#: ../src/jarabe/journal/expandedentry.py:411 ++#: ../src/jarabe/journal/misc.py:109 ++msgid "No date" ++msgstr "" ++ ++#: ../src/jarabe/journal/expandedentry.py:420 ++msgid "Participants:" ++msgstr "" ++ ++#: ../src/jarabe/journal/expandedentry.py:458 ++msgid "Description:" ++msgstr "" ++ ++#: ../src/jarabe/journal/expandedentry.py:464 ++msgid "Tags:" ++msgstr "" ++ ++#: ../src/jarabe/journal/expandedentry.py:469 ++msgid "Comments:" ++msgstr "" ++ ++#: ../src/jarabe/journal/journalactivity.py:140 ++#: ../src/jarabe/journal/journaltoolbox.py:89 ++#: ../src/jarabe/journal/palettes.py:248 ++#: ../src/jarabe/journal/volumestoolbar.py:363 ++msgid "Journal" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:98 ++msgid "Favorite entries" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:134 ++msgid "Anytime" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:136 ++msgid "Today" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:138 ++msgid "Since yesterday" ++msgstr "" ++ ++#. TRANS: Filter entries modified during the last 7 days. ++#: ../src/jarabe/journal/journaltoolbox.py:140 ++msgid "Past week" ++msgstr "" ++ ++#. TRANS: Filter entries modified during the last 30 days. ++#: ../src/jarabe/journal/journaltoolbox.py:142 ++msgid "Past month" ++msgstr "" ++ ++#. TRANS: Filter entries modified during the last 356 days. ++#: ../src/jarabe/journal/journaltoolbox.py:144 ++msgid "Past year" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:151 ++msgid "Anyone" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:153 ++msgid "My friends" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:154 ++msgid "My class" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:327 ++msgid "Anything" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:419 ++#: ../src/jarabe/journal/palettes.py:99 ++msgid "Copy to" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:427 ++#: ../src/jarabe/journal/palettes.py:110 ../src/jarabe/view/viewsource.py:282 ++msgid "Duplicate" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:433 ++msgid "Refresh" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:470 ++#: ../src/jarabe/journal/palettes.py:149 ../src/jarabe/journal/palettes.py:360 ++#: ../src/jarabe/journal/volumestoolbar.py:310 ++#, python-format ++msgid "Error while copying the entry. %s" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:471 ++#: ../src/jarabe/journal/palettes.py:150 ../src/jarabe/journal/palettes.py:361 ++#: ../src/jarabe/journal/volumestoolbar.py:311 ++msgid "Error" ++msgstr "" ++ ++#. TRANS: Action label for starting an entry. ++#: ../src/jarabe/journal/journaltoolbox.py:551 ++#: ../src/jarabe/journal/palettes.py:80 ++msgid "Start" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:579 ++msgid "Sort by date modified" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:580 ++msgid "Sort by date created" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:581 ++msgid "Sort by size" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:590 ++msgid "Sort view" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:661 ++msgid "Deselect all" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:674 ++msgid "Select all" ++msgstr "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:700 ++#, python-format ++msgid "Do you want to erase %d entry?" ++msgid_plural "Do you want to erase %d entries?" ++msgstr[0] "" ++msgstr[1] "" ++msgstr[2] "" ++ ++#: ../src/jarabe/journal/journaltoolbox.py:714 ++#: ../src/jarabe/journal/palettes.py:364 ++msgid "Copy" ++msgstr "" ++ ++#. TRANS: Do not translate %(selected)d and %(total)d. ++#: ../src/jarabe/journal/journaltoolbox.py:759 ++#, python-format ++msgid "Selected %(selected)d of %(total)d" ++msgstr "" ++ ++#: ../src/jarabe/journal/listview.py:387 ../src/jarabe/journal/iconview.py:211 ++msgid "Your Journal is empty" ++msgstr "" ++ ++#: ../src/jarabe/journal/listview.py:390 ../src/jarabe/journal/iconview.py:214 ++msgid "Your documents folder is empty" ++msgstr "" ++ ++#: ../src/jarabe/journal/listview.py:392 ../src/jarabe/journal/iconview.py:216 ++msgid "The device is empty" ++msgstr "" ++ ++#: ../src/jarabe/journal/listview.py:394 ../src/jarabe/journal/iconview.py:218 ++msgid "No matching entries" ++msgstr "" ++ ++#: ../src/jarabe/journal/misc.py:252 ++#, python-format ++msgid "Older Version Of %s Activity" ++msgstr "" ++ ++#: ../src/jarabe/journal/misc.py:253 ++#, python-format ++msgid "Do you want to downgrade to version %s" ++msgstr "" ++ ++#: ../src/jarabe/journal/modalalert.py:65 ++msgid "Your Journal is full" ++msgstr "" ++ ++#: ../src/jarabe/journal/modalalert.py:70 ++msgid "Please delete some old Journal entries to make space for new ones." ++msgstr "" ++ ++#: ../src/jarabe/journal/modalalert.py:84 ++msgid "Show Journal" ++msgstr "" ++ ++#: ../src/jarabe/journal/objectchooser.py:170 ++msgid "Choose an object" ++msgstr "" ++ ++#: ../src/jarabe/journal/objectchooser.py:175 ++#, python-format ++msgid "Choose an object to open with %s activity" ++msgstr "" ++ ++#: ../src/jarabe/journal/objectchooser.py:183 ++#: ../src/jarabe/view/viewsource.py:418 ++msgid "Close" ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:78 ++msgid "Resume with" ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:81 ++msgid "Start with" ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:94 ../src/jarabe/journal/palettes.py:489 ++msgid "No activity to start entry" ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:118 ++msgid "Send to" ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:127 ++msgid "View Details" ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:186 ++msgid "Entries without a file cannot be sent." ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:260 ++#: ../src/jarabe/journal/volumestoolbar.py:211 ++msgid "Documents" ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:349 ../src/jarabe/journal/palettes.py:409 ++#: ../src/jarabe/journal/volumestoolbar.py:301 ++msgid "Entries without a file cannot be copied." ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:369 ++#, python-format ++msgid "Do you want to copy %d entry?" ++msgid_plural "Do you want to copy %d entries?" ++msgstr[0] "" ++msgstr[1] "" ++msgstr[2] "" ++ ++#: ../src/jarabe/journal/palettes.py:394 ++msgid "Clipboard" ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:454 ++msgid "No friends present" ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:459 ++msgid "No valid connection found" ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:487 ++msgid "No activity to resume entry" ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:556 ../src/jarabe/view/palettes.py:110 ++msgid "Stop" ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:561 ++msgid "Continue" ++msgstr "" ++ ++#: ../src/jarabe/journal/palettes.py:598 ++#, python-format ++msgid "%(index)d of %(total)d : %(object_title)s" ++msgstr "" ++ ++#: ../src/jarabe/journal/volumestoolbar.py:386 ++#: ../src/jarabe/view/palettes.py:225 ../src/jarabe/view/palettes.py:292 ++#, python-format ++msgid "%(free_space)d MB Free" ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:214 ++msgid "The reason for the device state change is unknown." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:216 ++msgid "The state change is normal." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:218 ++msgid "The device is now managed." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:220 ++msgid "The device is no longer managed." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:222 ++msgid "The device could not be readied for configuration." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:224 ++msgid "" ++"IP configuration could not be reserved (no available address, timeout, etc)." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:227 ++msgid "The IP configuration is no longer valid." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:229 ++msgid "Secrets were required, but not provided." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:231 ++msgid "" ++"The 802.1X supplicant disconnected from the access point or authentication " ++"server." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:234 ++msgid "Configuration of the 802.1X supplicant failed." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:236 ++msgid "The 802.1X supplicant quit or failed unexpectedly." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:238 ++msgid "The 802.1X supplicant took too long to authenticate." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:240 ++msgid "The PPP service failed to start within the allowed time." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:242 ++msgid "The PPP service disconnected unexpectedly." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:244 ++msgid "The PPP service quit or failed unexpectedly." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:246 ++msgid "The DHCP service failed to start within the allowed time." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:248 ++msgid "The DHCP service reported an unexpected error." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:250 ++msgid "The DHCP service quit or failed unexpectedly." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:252 ++msgid "The shared connection service failed to start." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:254 ++msgid "The shared connection service quit or failed unexpectedly." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:257 ++msgid "The AutoIP service failed to start." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:259 ++msgid "The AutoIP service reported an unexpected error." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:261 ++msgid "The AutoIP service quit or failed unexpectedly." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:263 ++msgid "Dialing failed because the line was busy." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:265 ++msgid "Dialing failed because there was no dial tone." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:267 ++msgid "Dialing failed because there was no carrier." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:269 ++msgid "Dialing timed out." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:271 ++msgid "Dialing failed." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:273 ++msgid "Modem initialization failed." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:275 ++msgid "Failed to select the specified GSM APN" ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:277 ++msgid "Not searching for networks." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:279 ++msgid "Network registration was denied." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:281 ++msgid "Network registration timed out." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:283 ++msgid "Failed to register with the requested GSM network." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:285 ++msgid "PIN check failed." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:287 ++msgid "Necessary firmware for the device may be missing." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:289 ++msgid "The device was removed." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:291 ++msgid "NetworkManager went to sleep." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:293 ++msgid "The device's active connection was removed or disappeared." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:296 ++msgid "A user or client requested the disconnection." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:298 ++msgid "The device's carrier/link changed." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:300 ++msgid "The device's existing connection was assumed." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:302 ++msgid "The supplicant is now available." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:304 ++msgid "The modem could not be found." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:306 ++msgid "The Bluetooth connection failed or timed out." ++msgstr "" ++ ++#: ../src/jarabe/model/network.py:308 ++msgid "Unused." ++msgstr "" ++ ++#: ../src/jarabe/view/buddymenu.py:72 ++msgid "Remove friend" ++msgstr "" ++ ++#: ../src/jarabe/view/buddymenu.py:75 ++msgid "Make friend" ++msgstr "" ++ ++#: ../src/jarabe/view/buddymenu.py:91 ++msgid "Shutdown" ++msgstr "" ++ ++#: ../src/jarabe/view/buddymenu.py:98 ++msgid "Restart" ++msgstr "" ++ ++#: ../src/jarabe/view/buddymenu.py:104 ++msgid "Logout" ++msgstr "" ++ ++#: ../src/jarabe/view/buddymenu.py:109 ++msgid "My Settings" ++msgstr "" ++ ++#: ../src/jarabe/view/buddymenu.py:149 ++#, python-format ++msgid "Invite to %s" ++msgstr "" ++ ++#: ../src/jarabe/view/launcher.py:144 ++#, python-format ++msgid "<b>%s</b> failed to start." ++msgstr "" ++ ++#: ../src/jarabe/view/palettes.py:51 ++msgid "Starting..." ++msgstr "" ++ ++#: ../src/jarabe/view/palettes.py:61 ++msgid "Activity failed to start" ++msgstr "" ++ ++#. TODO: share-with, keep ++#: ../src/jarabe/view/palettes.py:102 ++msgid "View Source" ++msgstr "" ++ ++#: ../src/jarabe/view/palettes.py:153 ++msgid "Start new" ++msgstr "" ++ ++#: ../src/jarabe/view/palettes.py:241 ++msgctxt "Volume" ++msgid "Remove" ++msgstr "" ++ ++#: ../src/jarabe/view/viewsource.py:271 ++msgid "Instance Source" ++msgstr "" ++ ++#: ../src/jarabe/view/viewsource.py:320 ++msgid "Source" ++msgstr "" ++ ++#: ../src/jarabe/view/viewsource.py:382 ++msgid "Activity Bundle Source" ++msgstr "" ++ ++#: ../src/jarabe/view/viewsource.py:401 ++msgid "Sugar Toolkit Source" ++msgstr "" ++ ++#: ../src/jarabe/view/viewsource.py:408 ++#, python-format ++msgid "View source: %s" ++msgstr "" ++ ++#: ../src/jarabe/view/viewsource.py:409 ++#, python-format ++msgid "View source: %r" ++msgstr "" +diff --git b/po/sugar.pot a/po/sugar.pot +new file mode 100644 +index 0000000..3b96607 +--- /dev/null ++++ a/po/sugar.pot +@@ -0,0 +1,1998 @@ ++# SOME DESCRIPTIVE TITLE. ++# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER ++# This file is distributed under the same license as the PACKAGE package. ++# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. ++# ++#, fuzzy ++msgid "" ++msgstr "" ++"Project-Id-Version: PACKAGE VERSION\n" ++"Report-Msgid-Bugs-To: \n" ++"POT-Creation-Date: 2019-03-13 14:29+1100\n" ++"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" ++"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" ++"Language-Team: LANGUAGE <LL@li.org>\n" ++"Language: \n" ++"MIME-Version: 1.0\n" ++"Content-Type: text/plain; charset=CHARSET\n" ++"Content-Transfer-Encoding: 8bit\n" ++"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" ++ ++#: extensions/cpsection/aboutcomputer/__init__.py:20 ++msgid "About my Computer" ++msgstr "" ++ ++#: extensions/cpsection/aboutcomputer/model.py:36 ++msgid "Not available" ++msgstr "" ++ ++#: extensions/cpsection/aboutcomputer/view.py:76 ++msgid "Identity" ++msgstr "" ++ ++#: extensions/cpsection/aboutcomputer/view.py:87 ++msgid "Model:" ++msgstr "" ++ ++#: extensions/cpsection/aboutcomputer/view.py:91 ++msgid "Serial Number:" ++msgstr "" ++ ++#: extensions/cpsection/aboutcomputer/view.py:103 ++msgid "Software" ++msgstr "" ++ ++#: extensions/cpsection/aboutcomputer/view.py:112 ++msgid "Build:" ++msgstr "" ++ ++#: extensions/cpsection/aboutcomputer/view.py:117 ++msgid "Sugar:" ++msgstr "" ++ ++#: extensions/cpsection/aboutcomputer/view.py:122 ++msgid "Firmware:" ++msgstr "" ++ ++#: extensions/cpsection/aboutcomputer/view.py:127 ++msgid "Wireless Firmware:" ++msgstr "" ++ ++#: extensions/cpsection/aboutcomputer/view.py:134 ++#, python-format ++msgid "%d days ago" ++msgstr "" ++ ++#: extensions/cpsection/aboutcomputer/view.py:136 ++#: src/jarabe/journal/journaltoolbox.py:178 ++msgid "Today" ++msgstr "" ++ ++#: extensions/cpsection/aboutcomputer/view.py:139 ++msgid "Last system update:" ++msgstr "" ++ ++#: extensions/cpsection/aboutcomputer/view.py:150 ++msgid "Copyright and License" ++msgstr "" ++ ++#. TRANS: The word "Sugar" should not be translated. ++#: extensions/cpsection/aboutcomputer/view.py:169 ++msgid "" ++"Sugar is the graphical user interface that you are looking at. Sugar is free " ++"software, covered by the GNU General Public License, and you are welcome to " ++"change it and/or distribute copies of it under certain conditions described " ++"therein." ++msgstr "" ++ ++#: extensions/cpsection/aboutcomputer/view.py:182 ++msgid "Full license:" ++msgstr "" ++ ++#: extensions/cpsection/aboutme/__init__.py:23 ++msgid "About Me" ++msgstr "" ++ ++#: extensions/cpsection/aboutme/model.py:50 ++msgid "You must enter a name." ++msgstr "" ++ ++#: extensions/cpsection/aboutme/model.py:96 ++msgid "Error in specified color modifiers." ++msgstr "" ++ ++#: extensions/cpsection/aboutme/model.py:99 ++msgid "Error in specified colors." ++msgstr "" ++ ++#: extensions/cpsection/aboutme/view.py:244 ++msgid "Click to change your color:" ++msgstr "" ++ ++#: extensions/cpsection/aboutme/view.py:295 src/jarabe/intro/window.py:195 ++msgid "Select gender:" ++msgstr "" ++ ++#: extensions/cpsection/background/__init__.py:21 ++msgid "Background" ++msgstr "" ++ ++#: extensions/cpsection/background/view.py:48 ++msgid "Select a background:" ++msgstr "" ++ ++#: extensions/cpsection/background/view.py:57 ++msgid "Clear background" ++msgstr "" ++ ++#: extensions/cpsection/backup/backends/volume.py:60 ++#: extensions/cpsection/backup/backends/volume.py:170 ++msgid "Please connect a device to continue" ++msgstr "" ++ ++#: extensions/cpsection/backup/backends/volume.py:68 ++#: extensions/cpsection/backup/backends/volume.py:177 ++msgid "Select your volume" ++msgstr "" ++ ++#: extensions/cpsection/backup/backends/volume.py:77 ++msgid "Not enough space in volume" ++msgstr "" ++ ++#: extensions/cpsection/backup/backends/volume.py:121 ++#, python-format ++msgid "Backup from user %s" ++msgstr "" ++ ++#: extensions/cpsection/backup/backends/volume.py:190 ++msgid "No checkpoints found in the device" ++msgstr "" ++ ++#: extensions/cpsection/backup/backends/volume.py:198 ++msgid "Select your checkpoint" ++msgstr "" ++ ++#: extensions/cpsection/backup/backends/volume.py:209 ++msgid "Not enough space in disk" ++msgstr "" ++ ++#: extensions/cpsection/backup/backends/volume.py:328 ++msgid "Local Device Backup" ++msgstr "" ++ ++#: extensions/cpsection/backup/__init__.py:21 ++msgid "Backup" ++msgstr "" ++ ++#: extensions/cpsection/backup/view.py:132 ++msgid "Save the contents of your Journal" ++msgstr "" ++ ++#: extensions/cpsection/backup/view.py:140 ++msgid "Restore the contents of your Journal" ++msgstr "" ++ ++#: extensions/cpsection/backup/view.py:211 ++#: extensions/cpsection/backup/view.py:264 src/jarabe/journal/palettes.py:615 ++msgid "Continue" ++msgstr "" ++ ++#: extensions/cpsection/backup/view.py:222 ++msgid "Please close all the activities, and start again" ++msgstr "" ++ ++#: extensions/cpsection/backup/view.py:228 ++msgid "Select where you want create your backup" ++msgstr "" ++ ++#: extensions/cpsection/backup/view.py:230 ++msgid "Select where you want retrieve your restore" ++msgstr "" ++ ++#: extensions/cpsection/backup/view.py:270 ++msgid "Retry" ++msgstr "" ++ ++#: extensions/cpsection/backup/view.py:289 ++msgid "Starting backup..." ++msgstr "" ++ ++#: extensions/cpsection/backup/view.py:293 ++msgid "Starting restore..." ++msgstr "" ++ ++#: extensions/cpsection/backup/view.py:320 ++msgid "" ++"I want to restore the content of my Journal. In order to do this, my Journal " ++"will first be emptied of all its content; then the restored content will be " ++"added." ++msgstr "" ++ ++#: extensions/cpsection/backup/view.py:323 ++#: src/jarabe/frame/activitiestray.py:657 ++msgid "Accept" ++msgstr "" ++ ++#: extensions/cpsection/backup/view.py:326 ++msgid "Confirm" ++msgstr "" ++ ++#: extensions/cpsection/backup/view.py:364 ++msgid "Operation started" ++msgstr "" ++ ++#: extensions/cpsection/backup/view.py:376 ++msgid "Backup finished successfully" ++msgstr "" ++ ++#: extensions/cpsection/backup/view.py:378 ++msgid "Restore realized successfully." ++msgstr "" ++ ++#: extensions/cpsection/datetime/__init__.py:21 ++msgid "Date & Time" ++msgstr "" ++ ++#: extensions/cpsection/datetime/model.py:99 ++msgid "Error: timezone does not exist." ++msgstr "" ++ ++#: extensions/cpsection/datetime/view.py:67 ++msgid "Timezone" ++msgstr "" ++ ++#: extensions/cpsection/frame/__init__.py:21 ++msgid "Frame" ++msgstr "" ++ ++#: extensions/cpsection/frame/view.py:26 ++msgid "never" ++msgstr "" ++ ++#: extensions/cpsection/frame/view.py:27 ++msgid "instantaneous" ++msgstr "" ++ ++#: extensions/cpsection/frame/view.py:28 ++#, python-format ++msgid "%s seconds" ++msgstr "" ++ ++#: extensions/cpsection/frame/view.py:52 ++msgid "Activation Delay" ++msgstr "" ++ ++#: extensions/cpsection/frame/view.py:68 ++msgid "Activation Area" ++msgstr "" ++ ++#: extensions/cpsection/frame/view.py:85 ++msgid "Corner" ++msgstr "" ++ ++#: extensions/cpsection/frame/view.py:104 ++msgid "Edge" ++msgstr "" ++ ++#: extensions/cpsection/frame/view.py:123 ++msgid "Size" ++msgstr "" ++ ++#: extensions/cpsection/frame/view.py:221 ++msgid "toolbar size" ++msgstr "" ++ ++#: extensions/cpsection/frame/view.py:226 ++msgid "exact corner or edge" ++msgstr "" ++ ++#: extensions/cpsection/frame/view.py:228 ++msgid "exact corner" ++msgstr "" ++ ++#: extensions/cpsection/frame/view.py:230 ++msgid "exact edge" ++msgstr "" ++ ++#: extensions/cpsection/frame/view.py:232 ++msgid "ignored" ++msgstr "" ++ ++#. TRANS: px as in pixels ++#: extensions/cpsection/frame/view.py:235 ++msgid "{}px" ++msgstr "" ++ ++#: extensions/cpsection/keyboard/__init__.py:21 ++#: extensions/cpsection/keyboard/view.py:39 ++msgid "Keyboard" ++msgstr "" ++ ++#: extensions/cpsection/keyboard/view.py:241 ++msgid "Keyboard Model" ++msgstr "" ++ ++#: extensions/cpsection/keyboard/view.py:302 ++msgid "Key(s) to change layout" ++msgstr "" ++ ++#: extensions/cpsection/keyboard/view.py:370 ++msgid "Keyboard Layout(s)" ++msgstr "" ++ ++#: extensions/cpsection/language/__init__.py:21 ++#: extensions/cpsection/language/view.py:44 ++msgid "Language" ++msgstr "" ++ ++#: extensions/cpsection/language/model.py:28 ++msgid "Could not access ~/.i18n. Create standard settings." ++msgstr "" ++ ++#: extensions/cpsection/language/model.py:150 ++#, python-format ++msgid "Language for code=%s could not be determined." ++msgstr "" ++ ++#: extensions/cpsection/language/model.py:173 ++#, python-format ++msgid "Sorry I do not speak '%s'." ++msgstr "" ++ ++#: extensions/cpsection/language/view.py:81 ++msgid "" ++"Add languages in the order you prefer. If a translation is not available, " ++"the next in the list will be used." ++msgstr "" ++ ++#: extensions/cpsection/language/view.py:400 ++#, python-format ++msgid "Error writing language configuration (%s)" ++msgstr "" ++ ++#: extensions/cpsection/modemconfiguration/__init__.py:20 ++msgid "Modem" ++msgstr "" ++ ++#: extensions/cpsection/modemconfiguration/model.py:161 ++#, python-format ++msgid "Plan #%s" ++msgstr "" ++ ++#: extensions/cpsection/modemconfiguration/model.py:291 ++#, python-format ++msgid "Provider %s" ++msgstr "" ++ ++#: extensions/cpsection/modemconfiguration/view.py:93 ++msgid "" ++"You will need to provide the following information to set up a mobile " ++"broadband connection to a cellular (3G) network." ++msgstr "" ++ ++#: extensions/cpsection/modemconfiguration/view.py:116 ++msgid "Country:" ++msgstr "" ++ ++#: extensions/cpsection/modemconfiguration/view.py:117 ++msgid "Provider:" ++msgstr "" ++ ++#: extensions/cpsection/modemconfiguration/view.py:118 ++msgid "Plan:" ++msgstr "" ++ ++#: extensions/cpsection/modemconfiguration/view.py:159 ++#: extensions/cpsection/network/view.py:548 ++msgid "Username:" ++msgstr "" ++ ++#: extensions/cpsection/modemconfiguration/view.py:166 ++#: extensions/cpsection/network/view.py:554 ++msgid "Password:" ++msgstr "" ++ ++#: extensions/cpsection/modemconfiguration/view.py:173 ++msgid "Number:" ++msgstr "" ++ ++#: extensions/cpsection/modemconfiguration/view.py:180 ++msgid "Access Point Name (APN):" ++msgstr "" ++ ++#: extensions/cpsection/modemconfiguration/view.py:187 ++msgid "Personal Identity Number (PIN):" ++msgstr "" ++ ++#: extensions/cpsection/network/__init__.py:20 ++#: extensions/cpsection/network/view.py:36 ++msgid "Network" ++msgstr "" ++ ++#: extensions/cpsection/network/model.py:81 ++msgid "State is unknown." ++msgstr "" ++ ++#: extensions/cpsection/network/model.py:96 ++msgid "Error in specified radio argument. Use on/off." ++msgstr "" ++ ++#: extensions/cpsection/network/model.py:133 ++msgid "Error in specified argument. Use 0/1." ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:321 ++msgid "Wireless" ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:329 ++msgid "The wireless radio may be turned off to save battery life." ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:342 ++msgid "Radio" ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:359 ++msgid "" ++"Discard wireless connections if you have trouble connecting to the network" ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:369 ++msgid "Discard wireless connections" ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:385 ++msgid "Collaboration" ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:393 ++msgid "" ++"The server is the equivalent of what room you are in; people on the same " ++"server will be able to see each other, even when they aren't on the same " ++"network." ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:403 ++msgid "Server:" ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:419 ++msgid "" ++"Social Help is a forum that lets you connect with developers and discuss " ++"Sugar Activities. Changing servers means discussions will happen in a " ++"different place with different people." ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:429 ++msgid "Social Help Server:" ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:458 ++msgid "Proxy" ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:470 ++#: src/jarabe/journal/journaltoolbox.py:604 src/jarabe/journal/palettes.py:183 ++#: src/jarabe/journal/palettes.py:404 src/jarabe/journal/volumestoolbar.py:312 ++msgid "Error" ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:471 ++msgid "Proxy settings cannot be verified" ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:507 ++msgid "Method:" ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:514 ++msgid "Configuration URL:" ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:522 ++msgid "" ++"Web Proxy Autodiscovery is used when a Configuration URL is not provided. " ++"This is not recommended for untrusted public networks." ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:534 ++msgid "HTTP Proxy:" ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:540 ++msgid "Use authentication" ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:563 ++msgid "HTTPS Proxy:" ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:572 ++msgid "FTP Proxy:" ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:581 ++msgid "SOCKS Proxy:" ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:588 ++msgid "Ignore Hosts:" ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:645 ++msgid "Please Wait!" ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:646 ++msgid "Proxy settings are being verified." ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:663 ++msgid "Error!" ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:664 ++msgid "" ++"The following setting(s) seems to be incorrect and may break your internet " ++"connection" ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:670 ++msgid "Break my internet" ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:674 ++msgid "Reset" ++msgstr "" ++ ++#: extensions/cpsection/network/view.py:692 ++msgid "Proxy changes require restart" ++msgstr "" ++ ++#: extensions/cpsection/power/__init__.py:24 ++msgid "Power" ++msgstr "" ++ ++#: extensions/cpsection/power/model.py:89 ++msgid "Error in automatic pm argument, use on/off." ++msgstr "" ++ ++#: extensions/cpsection/power/view.py:45 ++msgid "Power management" ++msgstr "" ++ ++#: extensions/cpsection/power/view.py:55 ++msgid "Automatic power management (increases battery life)" ++msgstr "" ++ ++#: extensions/cpsection/updater/__init__.py:21 ++msgid "Software Update" ++msgstr "" ++ ++#: extensions/cpsection/updater/view.py:70 ++msgid "" ++"Software updates correct errors, eliminate security vulnerabilities, and " ++"provide new features." ++msgstr "" ++ ++#: extensions/cpsection/updater/view.py:84 ++msgid "Update in progress..." ++msgstr "" ++ ++#: extensions/cpsection/updater/view.py:119 ++msgid "Checking for updates..." ++msgstr "" ++ ++#: extensions/cpsection/updater/view.py:121 ++msgid "Installing updates..." ++msgstr "" ++ ++#: extensions/cpsection/updater/view.py:150 ++#, python-format ++msgid "Checking %s..." ++msgstr "" ++ ++#: extensions/cpsection/updater/view.py:152 ++msgid "Looking for updates..." ++msgstr "" ++ ++#: extensions/cpsection/updater/view.py:154 ++#, python-format ++msgid "Downloading %s..." ++msgstr "" ++ ++#: extensions/cpsection/updater/view.py:156 ++#, python-format ++msgid "Updating %s..." ++msgstr "" ++ ++#: extensions/cpsection/updater/view.py:166 ++msgid "Your software is up-to-date" ++msgstr "" ++ ++#: extensions/cpsection/updater/view.py:168 ++#, python-format ++msgid "You can install %s update" ++msgid_plural "You can install %s updates" ++msgstr[0] "" ++msgstr[1] "" ++ ++#: extensions/cpsection/updater/view.py:183 ++msgid "Can't connect to the activity server" ++msgstr "" ++ ++#: extensions/cpsection/updater/view.py:186 ++msgid "Verify your connection to internet and try again, or try again later" ++msgstr "" ++ ++#: extensions/cpsection/updater/view.py:206 ++#, python-format ++msgid "%s update was installed" ++msgid_plural "%s updates were installed" ++msgstr[0] "" ++msgstr[1] "" ++ ++#: extensions/cpsection/updater/view.py:288 ++msgid "Install selected" ++msgstr "" ++ ++#: extensions/cpsection/updater/view.py:307 ++#, python-format ++msgid "Download size: %s" ++msgstr "" ++ ++#: extensions/cpsection/updater/view.py:399 ++#, python-format ++msgid "From version %(current)s to %(new)s (Size: %(size)s)" ++msgstr "" ++ ++#: extensions/cpsection/updater/view.py:406 ++#, python-format ++msgid "Version %(version)s (Size: %(size)s)" ++msgstr "" ++ ++#. TRANS: download size is 0 ++#: extensions/cpsection/updater/view.py:423 ++msgid "None" ++msgstr "" ++ ++#. TRANS: download size of very small updates ++#: extensions/cpsection/updater/view.py:426 ++msgid "1 KiB" ++msgstr "" ++ ++#. TRANS: download size of small updates, e.g. '250 KiB' ++#: extensions/cpsection/updater/view.py:429 ++#, python-format ++msgid "%.0f KiB" ++msgstr "" ++ ++#. TRANS: download size of updates, e.g. '2.3 MiB' ++#: extensions/cpsection/updater/view.py:432 ++#, python-format ++msgid "%.1f MiB" ++msgstr "" ++ ++#: extensions/cpsection/webaccount/__init__.py:24 ++msgid "Web Services" ++msgstr "" ++ ++#: extensions/cpsection/webaccount/view.py:65 ++#, python-format ++msgid "" ++"No web services are installed.\n" ++"Please visit %s for more details." ++msgstr "" ++ ++#: extensions/deviceicon/audio.py:68 ++msgid "My Audio" ++msgstr "" ++ ++#: extensions/deviceicon/audio.py:330 ++msgid "Speaker" ++msgstr "" ++ ++#: extensions/deviceicon/audio.py:331 ++msgid "Microphone" ++msgstr "" ++ ++#: extensions/deviceicon/battery.py:78 ++msgid "My Battery" ++msgstr "" ++ ++#: extensions/deviceicon/battery.py:161 ++msgid "Removed" ++msgstr "" ++ ++#: extensions/deviceicon/battery.py:164 ++msgid "Charging" ++msgstr "" ++ ++#: extensions/deviceicon/battery.py:167 ++msgid "Very little power remaining" ++msgstr "" ++ ++#. TRANS: do not translate %(hour)d:%(min).2d it is a variable, ++#. only translate the word "remaining" ++#: extensions/deviceicon/battery.py:174 ++#, python-format ++msgid "%(hour)d:%(min).2d remaining" ++msgstr "" ++ ++#: extensions/deviceicon/battery.py:177 ++msgid "Charged" ++msgstr "" ++ ++#: extensions/deviceicon/display.py:185 ++msgid "My Display" ++msgstr "" ++ ++#: extensions/deviceicon/display.py:187 ++msgid "Take a screenshot" ++msgstr "" ++ ++#: extensions/deviceicon/display.py:209 ++msgid "Brightness" ++msgstr "" ++ ++#: extensions/deviceicon/display.py:237 ++msgid "Display" ++msgstr "" ++ ++#: extensions/deviceicon/frame.py:53 ++msgid "Show my keyboard" ++msgstr "" ++ ++#: extensions/deviceicon/network.py:47 ++#, python-format ++msgid "IP address: %s" ++msgstr "" ++ ++#: extensions/deviceicon/network.py:96 extensions/deviceicon/network.py:311 ++#: src/jarabe/desktop/networkviews.py:135 ++#: src/jarabe/desktop/networkviews.py:538 ++msgid "Disconnect" ++msgstr "" ++ ++#: extensions/deviceicon/network.py:122 extensions/deviceicon/network.py:304 ++#: src/jarabe/desktop/networkviews.py:275 ++#: src/jarabe/desktop/networkviews.py:580 ++#: src/jarabe/desktop/networkviews.py:725 ++msgid "Connecting..." ++msgstr "" ++ ++#: extensions/deviceicon/network.py:126 extensions/deviceicon/network.py:196 ++#: src/jarabe/desktop/networkviews.py:282 ++#: src/jarabe/desktop/networkviews.py:586 ++#: src/jarabe/desktop/networkviews.py:731 ++msgid "Connected" ++msgstr "" ++ ++#: extensions/deviceicon/network.py:139 ++msgid "No wireless connection" ++msgstr "" ++ ++#: extensions/deviceicon/network.py:153 extensions/deviceicon/network.py:156 ++msgid "Channel" ++msgstr "" ++ ++#: extensions/deviceicon/network.py:154 src/jarabe/journal/expandedentry.py:408 ++#: src/jarabe/journal/listmodel.py:189 src/jarabe/journal/listmodel.py:197 ++msgid "Unknown" ++msgstr "" ++ ++#: extensions/deviceicon/network.py:171 ++msgid "Wired Network" ++msgstr "" ++ ++#: extensions/deviceicon/network.py:199 ++msgid "Speed" ++msgstr "" ++ ++#: extensions/deviceicon/network.py:223 ++msgid "Wireless modem" ++msgstr "" ++ ++#: extensions/deviceicon/network.py:292 ++msgid "Please wait..." ++msgstr "" ++ ++#: extensions/deviceicon/network.py:296 src/jarabe/desktop/networkviews.py:129 ++#: src/jarabe/desktop/networkviews.py:532 ++#: src/jarabe/desktop/networkviews.py:676 ++msgid "Connect" ++msgstr "" ++ ++#: extensions/deviceicon/network.py:297 ++msgid "Disconnected" ++msgstr "" ++ ++#: extensions/deviceicon/network.py:303 src/jarabe/controlpanel/toolbar.py:122 ++#: src/jarabe/frame/activitiestray.py:702 ++#: src/jarabe/frame/activitiestray.py:824 ++#: src/jarabe/frame/activitiestray.py:857 ++#: src/jarabe/journal/expandedentry.py:160 ++#: src/jarabe/journal/journaltoolbox.py:613 src/jarabe/journal/palettes.py:192 ++msgid "Cancel" ++msgstr "" ++ ++#: extensions/deviceicon/network.py:341 ++msgid "Try connection again" ++msgstr "" ++ ++#: extensions/deviceicon/network.py:344 ++#, python-format ++msgid "Error: %s" ++msgstr "" ++ ++#: extensions/deviceicon/network.py:348 ++#, python-format ++msgid "Suggestion: %s" ++msgstr "" ++ ++#: extensions/deviceicon/network.py:358 ++#, python-format ++msgid "Connected for %s" ++msgstr "" ++ ++#: extensions/deviceicon/network.py:361 extensions/deviceicon/network.py:362 ++#: src/jarabe/frame/activitiestray.py:607 ++#, python-format ++msgid "%d KiB" ++msgstr "" ++ ++#: extensions/deviceicon/network.py:367 ++msgid "Check your PIN/PUK configuration." ++msgstr "" ++ ++#: extensions/deviceicon/network.py:370 ++msgid "Check your Access Point Name (APN) configuration" ++msgstr "" ++ ++#: extensions/deviceicon/network.py:374 ++msgid "Check the Number configuration." ++msgstr "" ++ ++#: extensions/deviceicon/network.py:376 ++msgid "Check your configuration." ++msgstr "" ++ ++#: extensions/deviceicon/network.py:633 ++msgid "Mesh Network" ++msgstr "" ++ ++#: extensions/deviceicon/network.py:679 ++#, python-format ++msgid "Mesh Network %s" ++msgstr "" ++ ++#: extensions/deviceicon/network.py:799 ++msgid "No GSM connection available." ++msgstr "" ++ ++#: extensions/deviceicon/network.py:800 ++msgid "Create a connection in My Settings." ++msgstr "" ++ ++#: extensions/deviceicon/speech.py:48 ++msgid "Speech" ++msgstr "" ++ ++#: extensions/deviceicon/speech.py:71 extensions/deviceicon/speech.py:146 ++#: extensions/deviceicon/speech.py:151 ++msgid "Say selected text" ++msgstr "" ++ ++#: extensions/deviceicon/speech.py:79 ++msgid "Stop playback" ++msgstr "" ++ ++#: extensions/deviceicon/speech.py:88 ++msgid "Pitch" ++msgstr "" ++ ++#: extensions/deviceicon/speech.py:103 ++msgid "Rate" ++msgstr "" ++ ++#: extensions/deviceicon/speech.py:141 ++msgid "Pause playback" ++msgstr "" ++ ++#: extensions/deviceicon/touchpad.py:35 ++msgid "finger" ++msgstr "" ++ ++#: extensions/deviceicon/touchpad.py:35 ++msgid "stylus" ++msgstr "" ++ ++#: extensions/deviceicon/touchpad.py:60 ++msgid "My touchpad" ++msgstr "" ++ ++#: extensions/deviceicon/volume.py:61 src/jarabe/view/palettes.py:222 ++msgid "Show contents" ++msgstr "" ++ ++#: src/jarabe/controlpanel/cmd.py:27 ++#, python-format ++msgid "" ++"sugar-control-panel: WARNING, found more than one option with the same name: " ++"%(key)s module: %(module)r" ++msgstr "" ++ ++#: src/jarabe/controlpanel/cmd.py:30 ++#, python-format ++msgid "sugar-control-panel: key=%s not an available option" ++msgstr "" ++ ++#. TRANS: Translators, there's a empty line at the end of this string, ++#. which must appear in the translated string (msgstr) as well. ++#: src/jarabe/controlpanel/cmd.py:38 ++msgid "" ++"Usage: sugar-control-panel [ option ] key [ args ... ] \n" ++" Control for the sugar environment. \n" ++" Options: \n" ++" -h show this help message and exit \n" ++" -l list all the available options \n" ++" -h key show information about this key \n" ++" -g key get the current value of the key \n" ++" -s key set the current value for the key \n" ++" -c key clear the current value for the key \n" ++" " ++msgstr "" ++ ++#: src/jarabe/controlpanel/cmd.py:52 ++msgid "" ++"To apply your changes you have to restart Sugar.\n" ++"Hit ctrl+alt+erase on the keyboard to trigger a restart." ++msgstr "" ++ ++#: src/jarabe/controlpanel/gui.py:397 src/jarabe/journal/palettes.py:224 ++#: src/jarabe/journal/palettes.py:393 src/jarabe/journal/palettes.py:453 ++#: src/jarabe/journal/volumestoolbar.py:303 ++msgid "Warning" ++msgstr "" ++ ++#: src/jarabe/controlpanel/gui.py:403 ++msgid "Cancel changes" ++msgstr "" ++ ++#: src/jarabe/controlpanel/gui.py:408 ++msgid "Later" ++msgstr "" ++ ++#: src/jarabe/controlpanel/gui.py:412 ++msgid "Restart now" ++msgstr "" ++ ++#: src/jarabe/controlpanel/gui.py:441 src/jarabe/view/buddymenu.py:138 ++msgid "An activity is not responding." ++msgstr "" ++ ++#: src/jarabe/controlpanel/gui.py:442 src/jarabe/view/buddymenu.py:139 ++msgid "You may lose unsaved work if you continue." ++msgstr "" ++ ++#: src/jarabe/controlpanel/sectionview.py:50 ++msgid "Changes require restart" ++msgstr "" ++ ++#: src/jarabe/controlpanel/toolbar.py:57 src/jarabe/desktop/viewtoolbar.py:129 ++#: src/jarabe/journal/journaltoolbox.py:95 ++#, python-format ++msgid "Search in %s" ++msgstr "" ++ ++#: src/jarabe/controlpanel/toolbar.py:57 ++msgid "Settings" ++msgstr "" ++ ++#: src/jarabe/controlpanel/toolbar.py:66 src/jarabe/intro/window.py:349 ++msgid "Done" ++msgstr "" ++ ++#: src/jarabe/controlpanel/toolbar.py:128 ++msgid "Ok" ++msgstr "" ++ ++#: src/jarabe/desktop/activitieslist.py:413 ++#, python-format ++msgid "Version %s" ++msgstr "" ++ ++#: src/jarabe/desktop/activitieslist.py:498 src/jarabe/journal/iconview.py:300 ++#: src/jarabe/journal/listview.py:610 ++msgid "Clear search" ++msgstr "" ++ ++#: src/jarabe/desktop/activitieslist.py:585 ++msgid "No matching activities" ++msgstr "" ++ ++#: src/jarabe/desktop/activitieslist.py:621 ++msgid "Confirm erase" ++msgstr "" ++ ++#: src/jarabe/desktop/activitieslist.py:623 ++#, python-format ++msgid "Confirm erase: Do you want to permanently erase %s?" ++msgstr "" ++ ++#: src/jarabe/desktop/activitieslist.py:627 ++#: src/jarabe/frame/clipboardmenu.py:64 src/jarabe/view/viewsource.py:386 ++msgid "Keep" ++msgstr "" ++ ++#: src/jarabe/desktop/activitieslist.py:630 ++#: src/jarabe/desktop/activitieslist.py:700 ++#: src/jarabe/journal/expandedentry.py:154 ++#: src/jarabe/journal/journaltoolbox.py:571 ++#: src/jarabe/journal/journaltoolbox.py:608 ++#: src/jarabe/journal/journaltoolbox.py:838 ++#: src/jarabe/journal/journaltoolbox.py:844 src/jarabe/journal/palettes.py:155 ++#: src/jarabe/journal/palettes.py:187 ++msgid "Erase" ++msgstr "" ++ ++#: src/jarabe/desktop/activitieslist.py:716 ++msgid "Remove favorite" ++msgstr "" ++ ++#: src/jarabe/desktop/activitieslist.py:720 ++msgid "Make favorite" ++msgstr "" ++ ++#. TRANS: label for the freeform layout in the favorites view ++#: src/jarabe/desktop/favoriteslayout.py:211 ++msgid "Freeform" ++msgstr "" ++ ++#. TRANS: label for the ring layout in the favorites view ++#: src/jarabe/desktop/favoriteslayout.py:305 ++msgid "Ring" ++msgstr "" ++ ++#. TRANS: label for the spiral layout in the favorites view ++#: src/jarabe/desktop/favoriteslayout.py:471 ++msgid "Spiral" ++msgstr "" ++ ++#. TRANS: label for the box layout in the favorites view ++#: src/jarabe/desktop/favoriteslayout.py:539 ++msgid "Box" ++msgstr "" ++ ++#. TRANS: label for the box layout in the favorites view ++#: src/jarabe/desktop/favoriteslayout.py:585 ++msgid "Triangle" ++msgstr "" ++ ++#: src/jarabe/desktop/favoritesview.py:381 ++msgid "Registration" ++msgstr "" ++ ++#: src/jarabe/desktop/favoritesview.py:382 ++msgid "Please wait, searching for your school server." ++msgstr "" ++ ++#: src/jarabe/desktop/favoritesview.py:392 ++msgid "Registration Failed" ++msgstr "" ++ ++#: src/jarabe/desktop/favoritesview.py:395 ++msgid "Registration Successful" ++msgstr "" ++ ++#: src/jarabe/desktop/favoritesview.py:396 ++msgid "You are now registered with your school server." ++msgstr "" ++ ++#: src/jarabe/desktop/favoritesview.py:688 ++msgid "Register" ++msgstr "" ++ ++#: src/jarabe/desktop/favoritesview.py:690 ++msgid "Register again" ++msgstr "" ++ ++#: src/jarabe/desktop/homewindow.py:277 src/jarabe/desktop/viewtoolbar.py:73 ++#: src/jarabe/frame/zoomtoolbar.py:56 src/jarabe/model/screenshot.py:62 ++#: src/jarabe/view/viewhelp.py:89 ++msgid "Home" ++msgstr "" ++ ++#: src/jarabe/desktop/homewindow.py:283 src/jarabe/frame/zoomtoolbar.py:52 ++#: src/jarabe/model/screenshot.py:60 src/jarabe/view/viewhelp.py:86 ++msgid "Group" ++msgstr "" ++ ++#: src/jarabe/desktop/homewindow.py:289 src/jarabe/frame/zoomtoolbar.py:48 ++msgid "Neighborhood" ++msgstr "" ++ ++#: src/jarabe/desktop/keydialog.py:93 ++#, python-format ++msgid "" ++"A wireless encryption key is required for\n" ++" the wireless network '%s'." ++msgstr "" ++ ++#: src/jarabe/desktop/keydialog.py:109 ++msgid "Show Password" ++msgstr "" ++ ++#: src/jarabe/desktop/keydialog.py:153 ++msgid "Key Type:" ++msgstr "" ++ ++#: src/jarabe/desktop/keydialog.py:173 ++msgid "Authentication Type:" ++msgstr "" ++ ++#: src/jarabe/desktop/keydialog.py:237 ++msgid "WPA & WPA2 Personal" ++msgstr "" ++ ++#: src/jarabe/desktop/keydialog.py:246 ++msgid "Wireless Security:" ++msgstr "" ++ ++#. TRANS: Action label for resuming an activity. ++#: src/jarabe/desktop/meshbox.py:82 src/jarabe/journal/journaltoolbox.py:685 ++#: src/jarabe/journal/palettes.py:87 src/jarabe/view/palettes.py:100 ++msgid "Resume" ++msgstr "" ++ ++#: src/jarabe/desktop/meshbox.py:89 src/jarabe/frame/activitiestray.py:208 ++msgid "Join" ++msgstr "" ++ ++#: src/jarabe/desktop/networkviews.py:142 ++msgid "Forget" ++msgstr "" ++ ++#: src/jarabe/desktop/networkviews.py:527 ++#, python-format ++msgid "Ad-hoc Network %d" ++msgstr "" ++ ++#: src/jarabe/desktop/networkviews.py:672 ++#, python-format ++msgid "Mesh Network %d" ++msgstr "" ++ ++#: src/jarabe/desktop/schoolserver.py:143 ++msgid "Cannot connect to the server." ++msgstr "" ++ ++#: src/jarabe/desktop/schoolserver.py:150 ++msgid "The server could not complete the request." ++msgstr "" ++ ++#: src/jarabe/desktop/viewtoolbar.py:95 ++msgid "List view" ++msgstr "" ++ ++#: src/jarabe/desktop/viewtoolbar.py:97 src/jarabe/desktop/viewtoolbar.py:196 ++#: src/jarabe/desktop/viewtoolbar.py:210 ++#, python-format ++msgid "<Ctrl>%d" ++msgstr "" ++ ++#: src/jarabe/frame/activitiestray.py:213 ++#: src/jarabe/frame/activitiestray.py:666 ++msgid "Decline" ++msgstr "" ++ ++#: src/jarabe/frame/activitiestray.py:605 ++#, python-format ++msgid "%d B" ++msgstr "" ++ ++#: src/jarabe/frame/activitiestray.py:609 ++#, python-format ++msgid "%d MiB" ++msgstr "" ++ ++#. TRANS: file transfer, bytes transferred, e.g. 128 of 1024 ++#: src/jarabe/frame/activitiestray.py:628 ++#, python-format ++msgid "%(transferred)s of %(total)s" ++msgstr "" ++ ++#: src/jarabe/frame/activitiestray.py:643 ++#, python-format ++msgid "Transfer from %s" ++msgstr "" ++ ++#: src/jarabe/frame/activitiestray.py:731 ++#: src/jarabe/frame/activitiestray.py:745 ++#: src/jarabe/frame/activitiestray.py:887 ++msgid "Dismiss" ++msgstr "" ++ ++#: src/jarabe/frame/activitiestray.py:759 ++msgid "The other participant canceled the file transfer" ++msgstr "" ++ ++#: src/jarabe/frame/activitiestray.py:809 ++#, python-format ++msgid "Transfer to %s" ++msgstr "" ++ ++#: src/jarabe/frame/clipboardmenu.py:59 src/jarabe/frame/clipboardmenu.py:82 ++#: src/jarabe/journal/palettes.py:104 ++msgid "Open" ++msgstr "" ++ ++#: src/jarabe/frame/clipboardmenu.py:87 ++msgid "Open with" ++msgstr "" ++ ++#: src/jarabe/frame/clipboardobject.py:49 ++#, python-format ++msgid "%s clipping" ++msgstr "" ++ ++#: src/jarabe/frame/notification.py:62 ++msgid "Clear notifications" ++msgstr "" ++ ++#: src/jarabe/frame/zoomtoolbar.py:49 ++msgid "F1" ++msgstr "" ++ ++#: src/jarabe/frame/zoomtoolbar.py:53 ++msgid "F2" ++msgstr "" ++ ++#: src/jarabe/frame/zoomtoolbar.py:57 ++msgid "F3" ++msgstr "" ++ ++#: src/jarabe/frame/zoomtoolbar.py:61 src/jarabe/model/screenshot.py:68 ++msgid "Activity" ++msgstr "" ++ ++#: src/jarabe/frame/zoomtoolbar.py:62 ++msgid "F4" ++msgstr "" ++ ++#: src/jarabe/intro/agepicker.py:38 ++msgid "Select grade:" ++msgstr "" ++ ++#: src/jarabe/intro/agepicker.py:39 ++msgid "Preschool" ++msgstr "" ++ ++#: src/jarabe/intro/agepicker.py:39 ++msgid "Kindergarten" ++msgstr "" ++ ++#: src/jarabe/intro/agepicker.py:39 ++msgid "1st Grade" ++msgstr "" ++ ++#: src/jarabe/intro/agepicker.py:40 ++msgid "2nd Grade" ++msgstr "" ++ ++#: src/jarabe/intro/agepicker.py:40 ++msgid "3rd Grade" ++msgstr "" ++ ++#: src/jarabe/intro/agepicker.py:40 ++msgid "4th Grade" ++msgstr "" ++ ++#: src/jarabe/intro/agepicker.py:41 ++msgid "5th Grade" ++msgstr "" ++ ++#: src/jarabe/intro/agepicker.py:41 ++msgid "6th Grade" ++msgstr "" ++ ++#: src/jarabe/intro/agepicker.py:41 ++msgid "7th Grade" ++msgstr "" ++ ++#: src/jarabe/intro/agepicker.py:42 ++msgid "High School" ++msgstr "" ++ ++#: src/jarabe/intro/agepicker.py:42 ++msgid "Adult" ++msgstr "" ++ ++#: src/jarabe/intro/window.py:125 ++msgid "Name:" ++msgstr "" ++ ++#: src/jarabe/intro/window.py:165 ++msgid "Click to change color:" ++msgstr "" ++ ++#: src/jarabe/intro/window.py:337 src/jarabe/journal/detailview.py:95 ++#: src/jarabe/view/viewhelp.py:305 ++msgid "Back" ++msgstr "" ++ ++#: src/jarabe/intro/window.py:352 ++msgid "Next" ++msgstr "" ++ ++#: src/jarabe/journal/expandedentry.py:156 ++#: src/jarabe/journal/journaltoolbox.py:610 src/jarabe/journal/palettes.py:189 ++#, python-format ++msgid "Do you want to permanently erase \"%s\"?" ++msgstr "" ++ ++#: src/jarabe/journal/expandedentry.py:332 src/jarabe/journal/iconmodel.py:109 ++#: src/jarabe/journal/listmodel.py:183 src/jarabe/journal/model.py:797 ++#: src/jarabe/journal/palettes.py:76 src/jarabe/journal/palettes.py:644 ++#: src/jarabe/journal/volumestoolbar.py:133 ++msgid "Untitled" ++msgstr "" ++ ++#: src/jarabe/journal/expandedentry.py:388 ++msgid "No preview" ++msgstr "" ++ ++#: src/jarabe/journal/expandedentry.py:408 ++#, python-format ++msgid "Kind: %s" ++msgstr "" ++ ++#: src/jarabe/journal/expandedentry.py:409 ++#, python-format ++msgid "Date: %s" ++msgstr "" ++ ++#: src/jarabe/journal/expandedentry.py:410 ++#, python-format ++msgid "Size: %s" ++msgstr "" ++ ++#: src/jarabe/journal/expandedentry.py:434 src/jarabe/journal/misc.py:139 ++msgid "No date" ++msgstr "" ++ ++#: src/jarabe/journal/expandedentry.py:443 ++msgid "Participants:" ++msgstr "" ++ ++#: src/jarabe/journal/expandedentry.py:481 ++#: src/jarabe/journal/projectview.py:110 ++msgid "Description:" ++msgstr "" ++ ++#: src/jarabe/journal/expandedentry.py:487 ++msgid "Tags:" ++msgstr "" ++ ++#: src/jarabe/journal/expandedentry.py:492 ++msgid "Comments:" ++msgstr "" ++ ++#: src/jarabe/journal/iconview.py:211 src/jarabe/journal/listview.py:512 ++msgid "Your Journal is empty" ++msgstr "" ++ ++#: src/jarabe/journal/iconview.py:214 src/jarabe/journal/listview.py:515 ++msgid "Your documents folder is empty" ++msgstr "" ++ ++#: src/jarabe/journal/iconview.py:216 src/jarabe/journal/listview.py:517 ++msgid "The device is empty" ++msgstr "" ++ ++#: src/jarabe/journal/iconview.py:219 src/jarabe/journal/listview.py:519 ++msgid "No matching entries" ++msgstr "" ++ ++#: src/jarabe/journal/journalactivity.py:197 ++#: src/jarabe/journal/journaltoolbox.py:95 ++#: src/jarabe/journal/journalwindow.py:32 src/jarabe/journal/palettes.py:289 ++#: src/jarabe/journal/volumestoolbar.py:350 src/jarabe/view/viewhelp.py:92 ++msgid "Journal" ++msgstr "" ++ ++#: src/jarabe/journal/journalactivity.py:285 ++msgid "Add new project" ++msgstr "" ++ ++#: src/jarabe/journal/journalactivity.py:364 ++#, python-format ++msgid "Choose an activity to start '%s' with" ++msgstr "" ++ ++#: src/jarabe/journal/journaltoolbox.py:104 ++msgid "Favorite entries" ++msgstr "" ++ ++#: src/jarabe/journal/journaltoolbox.py:111 ++msgid "Projects" ++msgstr "" ++ ++#. TRANS: Item on a palette that filters by entry type. ++#: src/jarabe/journal/journaltoolbox.py:121 ++#: src/jarabe/journal/journaltoolbox.py:415 ++#: src/jarabe/journal/journaltoolbox.py:500 ++msgid "Anything" ++msgstr "" ++ ++#: src/jarabe/journal/journaltoolbox.py:127 ++#: src/jarabe/journal/journaltoolbox.py:174 ++#: src/jarabe/journal/journaltoolbox.py:504 ++msgid "Anytime" ++msgstr "" ++ ++#: src/jarabe/journal/journaltoolbox.py:181 ++msgid "Since yesterday" ++msgstr "" ++ ++#: src/jarabe/journal/journaltoolbox.py:184 ++msgid "Past week" ++msgstr "" ++ ++#: src/jarabe/journal/journaltoolbox.py:187 ++msgid "Past month" ++msgstr "" ++ ++#: src/jarabe/journal/journaltoolbox.py:190 ++msgid "Past year" ++msgstr "" ++ ++#: src/jarabe/journal/journaltoolbox.py:547 src/jarabe/journal/palettes.py:116 ++msgid "Copy to" ++msgstr "" ++ ++#: src/jarabe/journal/journaltoolbox.py:555 src/jarabe/journal/palettes.py:133 ++#: src/jarabe/view/viewsource.py:382 ++msgid "Duplicate" ++msgstr "" ++ ++#: src/jarabe/journal/journaltoolbox.py:561 ++msgid "Refresh" ++msgstr "" ++ ++#: src/jarabe/journal/journaltoolbox.py:603 src/jarabe/journal/palettes.py:182 ++#: src/jarabe/journal/palettes.py:403 src/jarabe/journal/volumestoolbar.py:311 ++#, python-format ++msgid "Error while copying the entry. %s" ++msgstr "" ++ ++#. TRANS: Action label for starting an entry. ++#: src/jarabe/journal/journaltoolbox.py:688 src/jarabe/journal/palettes.py:90 ++msgid "Start" ++msgstr "" ++ ++#: src/jarabe/journal/journaltoolbox.py:708 src/jarabe/journal/palettes.py:111 ++#: src/jarabe/journal/palettes.py:542 ++msgid "No activity to start entry" ++msgstr "" ++ ++#: src/jarabe/journal/journaltoolbox.py:726 ++msgid "Sort view" ++msgstr "" ++ ++#: src/jarabe/journal/journaltoolbox.py:737 ++msgid "Sort by date modified" ++msgstr "" ++ ++#: src/jarabe/journal/journaltoolbox.py:738 ++msgid "Sort by date created" ++msgstr "" ++ ++#: src/jarabe/journal/journaltoolbox.py:739 ++msgid "Sort by size" ++msgstr "" ++ ++#: src/jarabe/journal/journaltoolbox.py:810 ++msgid "Deselect all" ++msgstr "" ++ ++#: src/jarabe/journal/journaltoolbox.py:823 ++msgid "Select all" ++msgstr "" ++ ++#: src/jarabe/journal/journaltoolbox.py:849 ++#, python-format ++msgid "Do you want to erase %d entry?" ++msgid_plural "Do you want to erase %d entries?" ++msgstr[0] "" ++msgstr[1] "" ++ ++#: src/jarabe/journal/journaltoolbox.py:863 src/jarabe/journal/palettes.py:407 ++msgid "Copy" ++msgstr "" ++ ++#. TRANS: Do not translate %(selected)d and %(total)d. ++#: src/jarabe/journal/journaltoolbox.py:914 ++#, python-format ++msgid "Selected %(selected)d of %(total)d" ++msgstr "" ++ ++#: src/jarabe/journal/journaltoolbox.py:949 ++msgid "Select filter" ++msgstr "" ++ ++#: src/jarabe/journal/journaltoolbox.py:1105 ++msgid "Add New" ++msgstr "" ++ ++#: src/jarabe/journal/journaltoolbox.py:1112 ++msgid "Add new entry" ++msgstr "" ++ ++#: src/jarabe/journal/listview.py:507 ++msgid "Your project is empty" ++msgstr "" ++ ++#: src/jarabe/journal/listview.py:521 ++msgid "No Projects" ++msgstr "" ++ ++#: src/jarabe/journal/misc.py:321 ++#, python-format ++msgid "Older Version Of %s Activity" ++msgstr "" ++ ++#: src/jarabe/journal/misc.py:322 ++#, python-format ++msgid "Do you want to downgrade to version %s?" ++msgstr "" ++ ++#: src/jarabe/journal/modalalert.py:62 ++msgid "Your Journal is full" ++msgstr "" ++ ++#: src/jarabe/journal/modalalert.py:67 ++msgid "Please delete some old Journal entries to make space for new ones." ++msgstr "" ++ ++#: src/jarabe/journal/modalalert.py:81 ++msgid "Show Journal" ++msgstr "" ++ ++#: src/jarabe/journal/objectchooser.py:170 ++msgid "Choose an object" ++msgstr "" ++ ++#: src/jarabe/journal/objectchooser.py:175 ++#, python-format ++msgid "Choose an object to open with %s activity" ++msgstr "" ++ ++#: src/jarabe/journal/objectchooser.py:183 src/jarabe/view/viewhelp.py:324 ++#: src/jarabe/view/viewsource.py:582 ++msgid "Close" ++msgstr "" ++ ++#: src/jarabe/journal/palettes.py:88 ++msgid "Resume with" ++msgstr "" ++ ++#: src/jarabe/journal/palettes.py:91 ++msgid "Start with" ++msgstr "" ++ ++#: src/jarabe/journal/palettes.py:127 ++msgid "Send to project..." ++msgstr "" ++ ++#: src/jarabe/journal/palettes.py:141 ++msgid "Send to" ++msgstr "" ++ ++#: src/jarabe/journal/palettes.py:150 ++msgid "View Details" ++msgstr "" ++ ++#: src/jarabe/journal/palettes.py:223 ++msgid "Entries without a file cannot be sent." ++msgstr "" ++ ++#: src/jarabe/journal/palettes.py:301 src/jarabe/journal/volumestoolbar.py:213 ++msgid "Documents" ++msgstr "" ++ ++#: src/jarabe/journal/palettes.py:392 src/jarabe/journal/palettes.py:452 ++#: src/jarabe/journal/volumestoolbar.py:302 ++msgid "Entries without a file cannot be copied." ++msgstr "" ++ ++#: src/jarabe/journal/palettes.py:412 ++#, python-format ++msgid "Do you want to copy %d entry?" ++msgid_plural "Do you want to copy %d entries?" ++msgstr[0] "" ++msgstr[1] "" ++ ++#: src/jarabe/journal/palettes.py:437 ++msgid "Clipboard" ++msgstr "" ++ ++#: src/jarabe/journal/palettes.py:507 ++msgid "No friends present" ++msgstr "" ++ ++#: src/jarabe/journal/palettes.py:512 ++msgid "No valid connection found" ++msgstr "" ++ ++#: src/jarabe/journal/palettes.py:540 ++msgid "No activity to resume entry" ++msgstr "" ++ ++#: src/jarabe/journal/palettes.py:610 src/jarabe/view/palettes.py:135 ++msgid "Stop" ++msgstr "" ++ ++#: src/jarabe/journal/palettes.py:645 ++#, python-format ++msgid "%(index)d of %(total)d : %(object_title)s" ++msgstr "" ++ ++#: src/jarabe/journal/volumestoolbar.py:376 src/jarabe/view/palettes.py:263 ++#: src/jarabe/view/palettes.py:330 ++#, python-format ++msgid "%(free_space)d MiB Free" ++msgstr "" ++ ++#: src/jarabe/model/desktop.py:84 ++#, python-format ++msgid "Favorites view %d" ++msgstr "" ++ ++#: src/jarabe/model/network.py:216 ++msgid "The reason for the device state change is unknown." ++msgstr "" ++ ++#: src/jarabe/model/network.py:218 ++msgid "The state change is normal." ++msgstr "" ++ ++#: src/jarabe/model/network.py:220 ++msgid "The device is now managed." ++msgstr "" ++ ++#: src/jarabe/model/network.py:222 ++msgid "The device is no longer managed." ++msgstr "" ++ ++#: src/jarabe/model/network.py:224 ++msgid "The device could not be readied for configuration." ++msgstr "" ++ ++#: src/jarabe/model/network.py:226 ++msgid "" ++"IP configuration could not be reserved (no available address, timeout, etc)." ++msgstr "" ++ ++#: src/jarabe/model/network.py:229 ++msgid "The IP configuration is no longer valid." ++msgstr "" ++ ++#: src/jarabe/model/network.py:231 ++msgid "Secrets were required, but not provided." ++msgstr "" ++ ++#: src/jarabe/model/network.py:233 ++msgid "" ++"The 802.1X supplicant disconnected from the access point or authentication " ++"server." ++msgstr "" ++ ++#: src/jarabe/model/network.py:236 ++msgid "Configuration of the 802.1X supplicant failed." ++msgstr "" ++ ++#: src/jarabe/model/network.py:238 ++msgid "The 802.1X supplicant quit or failed unexpectedly." ++msgstr "" ++ ++#: src/jarabe/model/network.py:240 ++msgid "The 802.1X supplicant took too long to authenticate." ++msgstr "" ++ ++#: src/jarabe/model/network.py:242 ++msgid "The PPP service failed to start within the allowed time." ++msgstr "" ++ ++#: src/jarabe/model/network.py:244 ++msgid "The PPP service disconnected unexpectedly." ++msgstr "" ++ ++#: src/jarabe/model/network.py:246 ++msgid "The PPP service quit or failed unexpectedly." ++msgstr "" ++ ++#: src/jarabe/model/network.py:248 ++msgid "The DHCP service failed to start within the allowed time." ++msgstr "" ++ ++#: src/jarabe/model/network.py:250 ++msgid "The DHCP service reported an unexpected error." ++msgstr "" ++ ++#: src/jarabe/model/network.py:252 ++msgid "The DHCP service quit or failed unexpectedly." ++msgstr "" ++ ++#: src/jarabe/model/network.py:254 ++msgid "The shared connection service failed to start." ++msgstr "" ++ ++#: src/jarabe/model/network.py:256 ++msgid "The shared connection service quit or failed unexpectedly." ++msgstr "" ++ ++#: src/jarabe/model/network.py:259 ++msgid "The AutoIP service failed to start." ++msgstr "" ++ ++#: src/jarabe/model/network.py:261 ++msgid "The AutoIP service reported an unexpected error." ++msgstr "" ++ ++#: src/jarabe/model/network.py:263 ++msgid "The AutoIP service quit or failed unexpectedly." ++msgstr "" ++ ++#: src/jarabe/model/network.py:265 ++msgid "Dialing failed because the line was busy." ++msgstr "" ++ ++#: src/jarabe/model/network.py:267 ++msgid "Dialing failed because there was no dial tone." ++msgstr "" ++ ++#: src/jarabe/model/network.py:269 ++msgid "Dialing failed because there was no carrier." ++msgstr "" ++ ++#: src/jarabe/model/network.py:271 ++msgid "Dialing timed out." ++msgstr "" ++ ++#: src/jarabe/model/network.py:273 ++msgid "Dialing failed." ++msgstr "" ++ ++#: src/jarabe/model/network.py:275 ++msgid "Modem initialization failed." ++msgstr "" ++ ++#: src/jarabe/model/network.py:277 ++msgid "Failed to select the specified GSM APN" ++msgstr "" ++ ++#: src/jarabe/model/network.py:279 ++msgid "Not searching for networks." ++msgstr "" ++ ++#: src/jarabe/model/network.py:281 ++msgid "Network registration was denied." ++msgstr "" ++ ++#: src/jarabe/model/network.py:283 ++msgid "Network registration timed out." ++msgstr "" ++ ++#: src/jarabe/model/network.py:285 ++msgid "Failed to register with the requested GSM network." ++msgstr "" ++ ++#: src/jarabe/model/network.py:287 ++msgid "PIN check failed." ++msgstr "" ++ ++#: src/jarabe/model/network.py:289 ++msgid "Necessary firmware for the device may be missing." ++msgstr "" ++ ++#: src/jarabe/model/network.py:291 ++msgid "The device was removed." ++msgstr "" ++ ++#: src/jarabe/model/network.py:293 ++msgid "NetworkManager went to sleep." ++msgstr "" ++ ++#: src/jarabe/model/network.py:295 ++msgid "The device's active connection was removed or disappeared." ++msgstr "" ++ ++#: src/jarabe/model/network.py:298 ++msgid "A user or client requested the disconnection." ++msgstr "" ++ ++#: src/jarabe/model/network.py:300 ++msgid "The device's carrier/link changed." ++msgstr "" ++ ++#: src/jarabe/model/network.py:302 ++msgid "The device's existing connection was assumed." ++msgstr "" ++ ++#: src/jarabe/model/network.py:304 ++msgid "The supplicant is now available." ++msgstr "" ++ ++#: src/jarabe/model/network.py:306 ++msgid "The modem could not be found." ++msgstr "" ++ ++#: src/jarabe/model/network.py:308 ++msgid "The Bluetooth connection failed or timed out." ++msgstr "" ++ ++#: src/jarabe/model/network.py:310 ++msgid "Unused." ++msgstr "" ++ ++#: src/jarabe/model/screenshot.py:58 src/jarabe/view/viewhelp.py:83 ++msgid "Mesh" ++msgstr "" ++ ++#: src/jarabe/model/screenshot.py:71 ++msgid "Screenshot" ++msgstr "" ++ ++#: src/jarabe/model/screenshot.py:73 ++#, python-format ++msgid "Screenshot of \"%s\"" ++msgstr "" ++ ++#: src/jarabe/view/alerts.py:37 src/jarabe/view/alerts.py:47 ++msgid "Activity launcher" ++msgstr "" ++ ++#: src/jarabe/view/alerts.py:38 ++#, python-format ++msgid "" ++"%(activity)s is already running. Please stop %(activity)s before launching " ++"it again." ++msgstr "" ++ ++#: src/jarabe/view/alerts.py:48 ++msgid "" ++"The maximum number of open activities has been reached. Please close an " ++"activity before launching a new one." ++msgstr "" ++ ++#: src/jarabe/view/buddymenu.py:74 ++msgid "Remove friend" ++msgstr "" ++ ++#: src/jarabe/view/buddymenu.py:77 ++msgid "Make friend" ++msgstr "" ++ ++#: src/jarabe/view/buddymenu.py:109 ++msgid "Shutdown" ++msgstr "" ++ ++#: src/jarabe/view/buddymenu.py:114 ++msgid "Restart" ++msgstr "" ++ ++#: src/jarabe/view/buddymenu.py:120 ++msgid "Logout" ++msgstr "" ++ ++#: src/jarabe/view/buddymenu.py:125 ++msgid "My Settings" ++msgstr "" ++ ++#: src/jarabe/view/buddymenu.py:188 ++#, python-format ++msgid "Invite to %s" ++msgstr "" ++ ++#: src/jarabe/view/launcher.py:158 ++#, python-format ++msgid "<b>%s</b> failed to start." ++msgstr "" ++ ++#: src/jarabe/view/palettes.py:55 ++msgid "Starting..." ++msgstr "" ++ ++#: src/jarabe/view/palettes.py:65 ++msgid "Activity failed to start" ++msgstr "" ++ ++#: src/jarabe/view/palettes.py:107 ++msgid "View Source" ++msgstr "" ++ ++#: src/jarabe/view/palettes.py:114 ++msgid "View Help" ++msgstr "" ++ ++#: src/jarabe/view/palettes.py:190 ++msgid "Start new" ++msgstr "" ++ ++#: src/jarabe/view/viewhelp.py:282 ++msgid "Help Manual" ++msgstr "" ++ ++#: src/jarabe/view/viewhelp.py:296 ++msgid "Social Help" ++msgstr "" ++ ++#: src/jarabe/view/viewhelp.py:310 ++msgid "Forward" ++msgstr "" ++ ++#: src/jarabe/view/viewhelp.py:315 ++#, python-format ++msgid "Help: %s" ++msgstr "" ++ ++#: src/jarabe/view/viewsource.py:367 ++msgid "Instance Source" ++msgstr "" ++ ++#: src/jarabe/view/viewsource.py:395 ++#, python-format ++msgid "Do you want to duplicate %s Activity?" ++msgstr "" ++ ++#: src/jarabe/view/viewsource.py:397 ++msgid "This may take a few minutes" ++msgstr "" ++ ++#: src/jarabe/view/viewsource.py:411 ++msgid "Duplicating activity..." ++msgstr "" ++ ++#: src/jarabe/view/viewsource.py:450 ++msgid "Duplicated" ++msgstr "" ++ ++#: src/jarabe/view/viewsource.py:451 ++msgid "The activity has been duplicated" ++msgstr "" ++ ++#: src/jarabe/view/viewsource.py:465 ++msgid "Duplicated activity already exists" ++msgstr "" ++ ++#: src/jarabe/view/viewsource.py:466 ++msgid "Delete your copy before trying to duplicate the activity again" ++msgstr "" ++ ++#: src/jarabe/view/viewsource.py:481 ++msgid "Source" ++msgstr "" ++ ++#: src/jarabe/view/viewsource.py:545 ++msgid "Activity Bundle Source" ++msgstr "" ++ ++#: src/jarabe/view/viewsource.py:564 ++msgid "Sugar Toolkit Source" ++msgstr "" ++ ++#: src/jarabe/view/viewsource.py:571 ++#, python-format ++msgid "View source: %s" ++msgstr "" ++ ++#: src/jarabe/view/viewsource.py:572 ++#, python-format ++msgid "View source: %r" ++msgstr "" ++ ++#: src/jarabe/view/viewsource.py:813 ++msgid "Please select a file in the left panel." ++msgstr "" +diff --git b/src/jarabe/.gitignore a/src/jarabe/.gitignore +new file mode 100644 +index 0000000..4acd06b +--- /dev/null ++++ a/src/jarabe/.gitignore +@@ -0,0 +1 @@ ++config.py +diff --git b/src/jarabe/desktop/favoriteslayout.py a/src/jarabe/desktop/favoriteslayout.py +index 2d3e998..aaaf513 100644 +--- b/src/jarabe/desktop/favoriteslayout.py ++++ a/src/jarabe/desktop/favoriteslayout.py +@@ -247,7 +247,7 @@ class RandomLayout(SpreadLayout): + x = min(x, allocation.width - child_requisition.width) + y = min(y, allocation.height - child_requisition.height) + elif hasattr(child, 'get_bundle_id'): +- name_hash = hashlib.md5(child.get_bundle_id().decode()) ++ name_hash = hashlib.md5(child.get_bundle_id().encode('utf-8')) + x = int(name_hash.hexdigest()[:5], 16) % \ + (allocation.width - child_requisition.width) + y = int(name_hash.hexdigest()[-5:], 16) % \ +diff --git b/src/jarabe/desktop/meshbox.py a/src/jarabe/desktop/meshbox.py +index da0a775..0127492 100644 +--- b/src/jarabe/desktop/meshbox.py ++++ a/src/jarabe/desktop/meshbox.py +@@ -486,7 +486,7 @@ class MeshBox(ViewContainer): + # if we have mesh hardware, ignore OLPC mesh networks that appear as + # normal wifi networks + if len(self._mesh) > 0 and ap.mode == network.NM_802_11_MODE_ADHOC \ +- and ap.ssid == 'olpc-mesh': ++ and ap.ssid == b'olpc-mesh': + logging.debug('ignoring OLPC mesh IBSS') + ap.disconnect() + return +diff --git b/src/jarabe/desktop/networkviews.py a/src/jarabe/desktop/networkviews.py +index d63cf01..1bf6cc3 100644 +--- b/src/jarabe/desktop/networkviews.py ++++ a/src/jarabe/desktop/networkviews.py +@@ -454,7 +454,7 @@ class WirelessNetworkView(EventPulsingIcon): + + def is_olpc_mesh(self): + return self._mode == network.NM_802_11_MODE_ADHOC \ +- and self._ssid == 'olpc-mesh' ++ and self._ssid == b'olpc-mesh' + + def remove_all_aps(self): + for ap in list(self._access_points.values()): +diff --git b/src/jarabe/journal/journalentrybundle.py a/src/jarabe/journal/journalentrybundle.py +index 0656b6a..233c899 100644 +--- b/src/jarabe/journal/journalentrybundle.py ++++ a/src/jarabe/journal/journalentrybundle.py +@@ -87,7 +87,7 @@ class JournalEntryBundle(Bundle): + preview_path = os.path.join(bundle_dir, 'preview', uid) + if not os.path.exists(preview_path): + return '' +- f = open(preview_path, 'r') ++ f = open(preview_path, 'rb') + try: + preview_data = f.read() + finally: +diff --git b/src/jarabe/model/buddy.py a/src/jarabe/model/buddy.py +index 6683a52..179d67e 100644 +--- b/src/jarabe/model/buddy.py ++++ a/src/jarabe/model/buddy.py +@@ -57,6 +57,9 @@ class BaseBuddyModel(GObject.GObject): + return self._key + + def set_key(self, key): ++ if isinstance(key, bytes): ++ key = key.decode('utf-8') ++ + self._key = key + + key = GObject.Property(type=object, getter=get_key, setter=set_key) +@@ -160,9 +163,8 @@ class OwnerBuddyModel(BaseBuddyModel): + if CONNECTION_INTERFACE_BUDDY_INFO in connection: + properties = {} + if self.props.key is not None: +- if isinstance(self.props.key, str): +- self.props.key = self.props.key.encode() +- properties['key'] = dbus.ByteArray(self.props.key) ++ properties['key'] = dbus.ByteArray( ++ self.props.key.encode('utf-8')) + if self.props.color is not None: + properties['color'] = self.props.color.to_string() + +diff --git b/src/jarabe/model/network.py a/src/jarabe/model/network.py +index a26b62d..edb6758 100644 +--- b/src/jarabe/model/network.py ++++ a/src/jarabe/model/network.py +@@ -429,7 +429,7 @@ class OlpcMesh(object): + + def get_dict(self): + ret = { +- 'ssid': dbus.ByteArray('olpc-mesh'), ++ 'ssid': dbus.ByteArray(b'olpc-mesh'), + 'channel': self.channel, + } + +@@ -647,7 +647,7 @@ class AccessPoint(GObject.GObject): + self._initialized = False + self._bus = dbus.SystemBus() + +- self.ssid = '' ++ self.ssid = b'' + self.strength = 0 + self.flags = 0 + self.wpa_flags = 0 +@@ -970,7 +970,7 @@ def _migrate_old_wifi_connections(): + try: + settings = Settings() + settings.connection.id = section +- ssid = config.get(section, 'ssid') ++ ssid = config.get(section, 'ssid').encode() + settings.wireless.ssid = dbus.ByteArray(ssid) + config_uuid = config.get(section, 'uuid') + settings.connection.uuid = config_uuid +diff --git b/src/jarabe/view/Makefile.am a/src/jarabe/view/Makefile.am +index da7fe1d..3aea66f 100644 +--- b/src/jarabe/view/Makefile.am ++++ a/src/jarabe/view/Makefile.am +@@ -15,5 +15,4 @@ sugar_PYTHON = \ + tabbinghandler.py \ + viewsource.py \ + viewhelp.py \ +- viewhelp_webkit1.py \ + viewhelp_webkit2.py +diff --git b/src/jarabe/view/viewhelp.py a/src/jarabe/view/viewhelp.py +index baf8af0..0cd9498 100644 +--- b/src/jarabe/view/viewhelp.py ++++ a/src/jarabe/view/viewhelp.py +@@ -33,17 +33,7 @@ from sugar3.graphics.toolbutton import ToolButton + from sugar3.graphics.radiotoolbutton import RadioToolButton + from sugar3.bundle.activitybundle import get_bundle_instance + from jarabe.model import shell +- +- +-try: +- olpc_build = open('/boot/olpc_build', 'r').readline() +-except: +- olpc_build = '' +- +-if olpc_build.startswith('13'): +- from jarabe.view.viewhelp_webkit1 import Browser +-else: +- from jarabe.view.viewhelp_webkit2 import Browser ++from jarabe.view.viewhelp_webkit2 import Browser + + + _logger = logging.getLogger('ViewHelp') +diff --git b/tests/data/activity-1.xo a/tests/data/activity-1.xo +new file mode 100644 +index 0000000..f7ae005 +Binary files /dev/null and a/tests/data/activity-1.xo differ +diff --git b/tests/data/activity.svg a/tests/data/activity.svg +new file mode 100644 +index 0000000..8da7c63 +--- /dev/null ++++ a/tests/data/activity.svg +@@ -0,0 +1,26 @@ ++<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [ ++ <!ENTITY stroke_color "#010101"> ++ <!ENTITY fill_color "#FFFFFF"> ++]> ++<svg enable-background="new 0 0 55 55" height="55px" version="1.1" viewBox="0 0 55 55" width="55px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"> ++ <g display="block" id="activity-helloworld"> ++ <path d="M9.263,48.396c0.682,1.152,6.027,0.059,8.246-1.463 c2.102-1.432,3.207-2.596,4.336-2.596c1.133,0,12.54,0.92,20.935-5.715c7.225-5.707,9.773-13.788,4.52-21.437 c-5.252-7.644-13.832-9.08-20.878-8.56C16.806,9.342,4.224,16.91,4.677,28.313c0.264,6.711,3.357,9.143,4.922,10.703 c1.562,1.566,4.545,1.566,2.992,5.588C11.981,46.183,8.753,47.522,9.263,48.396z" display="inline" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5"/> ++ </g> ++ <circle cx="27.375" cy="27.5" r="19.903" ++ transform="matrix(0.6,0,0,0.6,10.95,11)" ++ id="circle4" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" display="inline" /> ++ <g transform="matrix(0.6,0,0,0.6,10.95,11)" id="g6" style="display:inline"> ++ <path d="m 27.376,7.598 c 0,0 -11.205,8.394 -11.205,19.976 0,11.583 11.205,19.829 11.205,19.829" ++ id="path8" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" /> ++ <path d="m 27.376,7.598 c 0,0 11.066,9.141 11.066,19.976 0,10.839 -11.066,19.829 -11.066,19.829" ++ id="path10" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" /> ++ <line x1="27.375999" x2="27.375999" y1="7.598" y2="47.402" ++ id="line12" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" /> ++ <line x1="27.375999" x2="27.375999" y1="7.598" y2="47.402" ++ id="line14" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" /> ++ <line x1="27.375999" x2="27.375999" y1="7.598" y2="47.402" ++ id="line16" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" /> ++ <line x1="7.4720001" x2="47.278" y1="27.5" y2="27.5" ++ id="line18" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" /> ++ </g> ++</svg> +diff --git b/tests/data/microformat.html a/tests/data/microformat.html +new file mode 100644 +index 0000000..6fea175 +--- /dev/null ++++ a/tests/data/microformat.html +@@ -0,0 +1,19 @@ ++<span id="olpc-activity-group-name">activities</span> ++ ++<div class="olpc-activity-info"> ++<span class="olpc-activity-id" style="display:none;">org.sugarlabs.AbacusActivity</span> ++<span class="olpc-activity-url"><a href="http://download.sugarlabs.org/abacus-43.xo">Abacus</a></span> ++<span class="olpc-activity-version">43</span> ++</div> ++ ++<div class="olpc-activity-info"> ++<span class="olpc-activity-id" style="display:none;">org.sugarlabs.AbacusActivity</span> ++<span class="olpc-activity-url"><a href="http://download.sugarlabs.org/activities/4293/abacus-41.1.xo">Abacus</a></span> ++<span class="olpc-activity-version">41.1</span> ++</div> ++ ++<div class="olpc-activity-info"> ++<span class="olpc-activity-id" style="display:none;">org.laptop.WebActivity</span> ++<span class="olpc-activity-url"><a href="browse-149.xo">Browse</a></span> ++<span class="olpc-activity-version">149</span> ++</div> +diff --git b/tests/data/sample-1.xol a/tests/data/sample-1.xol +new file mode 100644 +index 0000000..52f384d +Binary files /dev/null and a/tests/data/sample-1.xol differ +diff --git b/tests/data/test.txt a/tests/data/test.txt +new file mode 100644 +index 0000000..ce01362 +--- /dev/null ++++ a/tests/data/test.txt +@@ -0,0 +1 @@ ++hello +diff --git b/tests/extensions/cpsection/__init__.py a/tests/extensions/cpsection/__init__.py +new file mode 100644 +index 0000000..3ad9513 +--- /dev/null ++++ a/tests/extensions/cpsection/__init__.py +@@ -0,0 +1,2 @@ ++from pkgutil import extend_path ++__path__ = extend_path(__path__, __name__) +diff --git b/tests/extensions/cpsection/webaccount/__init__.py a/tests/extensions/cpsection/webaccount/__init__.py +new file mode 100644 +index 0000000..3ad9513 +--- /dev/null ++++ a/tests/extensions/cpsection/webaccount/__init__.py +@@ -0,0 +1,2 @@ ++from pkgutil import extend_path ++__path__ = extend_path(__path__, __name__) +diff --git b/tests/extensions/cpsection/webaccount/services/__init__.py a/tests/extensions/cpsection/webaccount/services/__init__.py +new file mode 100644 +index 0000000..3ad9513 +--- /dev/null ++++ a/tests/extensions/cpsection/webaccount/services/__init__.py +@@ -0,0 +1,2 @@ ++from pkgutil import extend_path ++__path__ = extend_path(__path__, __name__) +diff --git b/tests/extensions/cpsection/webaccount/services/mock/__init__.py a/tests/extensions/cpsection/webaccount/services/mock/__init__.py +new file mode 100644 +index 0000000..3ad9513 +--- /dev/null ++++ a/tests/extensions/cpsection/webaccount/services/mock/__init__.py +@@ -0,0 +1,2 @@ ++from pkgutil import extend_path ++__path__ = extend_path(__path__, __name__) +diff --git b/tests/extensions/cpsection/webaccount/services/mock/service.py a/tests/extensions/cpsection/webaccount/services/mock/service.py +new file mode 100644 +index 0000000..bd29dab +--- /dev/null ++++ a/tests/extensions/cpsection/webaccount/services/mock/service.py +@@ -0,0 +1,45 @@ ++# Copyright (C) 2013, Walter Bender - Raul Gutierrez Segales ++# ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see <http://www.gnu.org/licenses/>. ++ ++ ++from gi.repository import Gtk ++ ++from jarabe.webservice import accountsmanager ++ ++from cpsection.webaccount.web_service import WebService ++ ++_SERVICE_NAME = 'mock' ++ ++ ++class WebService(WebService): ++ ++ def __init__(self): ++ self._account = accountsmanager.get_account(_SERVICE_NAME) ++ ++ def get_icon_name(self): ++ return _SERVICE_NAME ++ ++ def config_service_cb(self, widget, event, container): ++ label = Gtk.Label(_SERVICE_NAME) ++ ++ for c in container.get_children(): ++ container.remove(c) ++ ++ container.add(label) ++ container.show_all() ++ ++ ++def get_service(): ++ return WebService() +diff --git b/tests/extensions/cpsection/webaccount/web_service.py a/tests/extensions/cpsection/webaccount/web_service.py +new file mode 100644 +index 0000000..998acb1 +--- /dev/null ++++ a/tests/extensions/cpsection/webaccount/web_service.py +@@ -0,0 +1,22 @@ ++# Copyright (C) 2013, Walter Bender - Raul Gutierrez Segales ++# ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see <http://www.gnu.org/licenses/>. ++ ++ ++class WebService(): ++ def get_icon_name(self): ++ raise "Not implemented" ++ ++ def config_service_cb(self, widget, event, container): ++ raise "Not implemented" +diff --git b/tests/extensions/webservice/__init__.py a/tests/extensions/webservice/__init__.py +new file mode 100644 +index 0000000..3ad9513 +--- /dev/null ++++ a/tests/extensions/webservice/__init__.py +@@ -0,0 +1,2 @@ ++from pkgutil import extend_path ++__path__ = extend_path(__path__, __name__) +diff --git b/tests/extensions/webservice/mock/__init__.py a/tests/extensions/webservice/mock/__init__.py +new file mode 100644 +index 0000000..3ad9513 +--- /dev/null ++++ a/tests/extensions/webservice/mock/__init__.py +@@ -0,0 +1,2 @@ ++from pkgutil import extend_path ++__path__ = extend_path(__path__, __name__) +diff --git b/tests/extensions/webservice/mock/account.py a/tests/extensions/webservice/mock/account.py +new file mode 100644 +index 0000000..3f4520d +--- /dev/null ++++ a/tests/extensions/webservice/mock/account.py +@@ -0,0 +1,72 @@ ++# Copyright (c) 2013 Walter Bender ++ ++# Permission is hereby granted, free of charge, to any person obtaining a copy ++# of this software and associated documentation files (the "Software"), to deal ++# in the Software without restriction, including without limitation the rights ++# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++# copies of the Software, and to permit persons to whom the Software is ++# furnished to do so, subject to the following conditions: ++ ++# The above copyright notice and this permission notice shall be included in ++# all copies or substantial portions of the Software. ++ ++# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++# THE SOFTWARE. ++ ++import os ++ ++from sugar3.graphics.menuitem import MenuItem ++from jarabe.webservice import account ++ ++ACCOUNT_NAME = 'mock' ++ ++ ++class MockAccount(account.Account): ++ def __init__(self): ++ return ++ ++ def get_description(self): ++ return ACCOUNT_NAME ++ ++ def get_shared_journal_entry(self): ++ return MockSharedJournalEntry() ++ ++ def get_token_state(self): ++ return int(os.environ["MOCK_ACCOUNT_STATE"]) ++ ++ ++class MockSharedJournalEntry(account.SharedJournalEntry): ++ def __init__(self): ++ return ++ ++ def get_share_menu(self, metadata): ++ share_menu = ShareMenu(metadata) ++ return share_menu ++ ++ def get_refresh_menu(self): ++ refresh_menu = RefreshMenu() ++ return refresh_menu ++ ++ ++class ShareMenu(MenuItem): ++ def __init__(self, metadata): ++ MenuItem.__init__(self, text_label=ACCOUNT_NAME) ++ self.show() ++ ++ ++class RefreshMenu(MenuItem): ++ def __init__(self): ++ MenuItem.__init__(self, text_label=ACCOUNT_NAME) ++ self.show() ++ ++ def set_metadata(self, metadata): ++ return ++ ++ ++def get_account(): ++ return MockAccount() +diff --git b/tests/extensions/webservice/mock/icons/mock.svg a/tests/extensions/webservice/mock/icons/mock.svg +new file mode 100644 +index 0000000..7a9434c +--- /dev/null ++++ a/tests/extensions/webservice/mock/icons/mock.svg +@@ -0,0 +1,25 @@ ++<?xml version="1.0" ?><!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) --><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [ ++ <!ENTITY stroke_color "#A0A0A0"> ++ <!ENTITY fill_color "#282828"> ++]><svg enable-background="new 0 0 55.125 55" height="55px" id="Layer_1" version="1.1" viewBox="0 0 55 55" width="55px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"> ++ <rect ++ width="54" ++ height="54" ++ ry="3.5" ++ x="0.5" ++ y="0.5" ++ style="fill:&fill_color;;fill-opacity:1;fill-rule:nonzero;stroke:#FFFFFF;stroke-width:1.0;stroke-opacity:1" /> ++ <rect ++ width="46.25" ++ height="7.75" ++ ry="0" ++ x="4.5" ++ y="42" ++ style="fill:&stroke_color;;fill-opacity:1;fill-rule:nonzero;stroke:none" /> ++<text> ++ <tspan ++ x="6" ++ y="45" ++ id="tspan2839" ++ style="font-size:44px;font-style:normal;font-variant:normal;font-weight:bold;fill:#ffffff;font-family:DejaVu Sans;">M</tspan></text> ++</svg> +diff --git b/tests/extensions/webservice/mock/mock/__init__.py a/tests/extensions/webservice/mock/mock/__init__.py +new file mode 100644 +index 0000000..3ad9513 +--- /dev/null ++++ a/tests/extensions/webservice/mock/mock/__init__.py +@@ -0,0 +1,2 @@ ++from pkgutil import extend_path ++__path__ = extend_path(__path__, __name__) +diff --git b/tests/extensions/webservice/mock/mock/mock.py a/tests/extensions/webservice/mock/mock/mock.py +new file mode 100644 +index 0000000..e69de29 +diff --git b/tests/test_activitieslist.py a/tests/test_activitieslist.py +new file mode 100644 +index 0000000..722424f +--- /dev/null ++++ a/tests/test_activitieslist.py +@@ -0,0 +1,27 @@ ++# Copyright (C) 2013, Daniel Narvaez ++# ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see <http://www.gnu.org/licenses/>. ++ ++from sugar3.test import unittest ++from sugar3.test import uitree ++ ++ ++class TestActivitiesList(unittest.UITestCase): ++ def test_activity_list_palette(self): ++ with self.run_view("activitieslist"): ++ root = uitree.get_root() ++ ++ for name in ["Make favorite", "Erase", "Start new"]: ++ node = root.find_child(name=name, role_name="label") ++ self.assertIsNotNone(node) +diff --git b/tests/test_backup.py a/tests/test_backup.py +new file mode 100644 +index 0000000..0fe832c +--- /dev/null ++++ a/tests/test_backup.py +@@ -0,0 +1,47 @@ ++# Copyright (C) 2014, Gonzalo Odiard ++# ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see <http://www.gnu.org/licenses/>. ++ ++import unittest ++import sys ++ ++from jarabe import config ++ ++# we need import from the extensions path ++sys.path.append(config.ext_path) ++ ++from cpsection.backup.backupmanager import BackupManager ++from cpsection.backup.backends.backend_tools import Backend ++ ++ ++class TestBackup(unittest.TestCase): ++ ++ def setUp(self): ++ self.manager = BackupManager() ++ self._backends = self.manager.get_backends() ++ ++ def test_get_backend(self): ++ self.assertTrue(len(self._backends) > 0) ++ ++ def test_backend_backup_restore(self): ++ for backend in self._backends: ++ # verify the backend have the methods needed ++ self.assertIsInstance(backend.get_name(), str) ++ ++ self.assertIsInstance(backend.get_backup(), Backend) ++ ++ self.assertIsInstance(backend.get_restore(), Backend) ++ ++ def test_need_stop_activities(self): ++ self.assertFalse(self.manager.need_stop_activities()) +diff --git b/tests/test_bundleregistry.py a/tests/test_bundleregistry.py +new file mode 100644 +index 0000000..743d40c +--- /dev/null ++++ a/tests/test_bundleregistry.py +@@ -0,0 +1,60 @@ ++# Copyright (C) 2013, One Laptop per Child ++# ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see <http://www.gnu.org/licenses/>. ++ ++import shutil ++import tempfile ++import unittest ++import os ++ ++from jarabe.model import bundleregistry ++from sugar3.bundle.helpers import bundle_from_archive ++ ++tests_dir = os.getcwd() ++data_dir = os.path.join(tests_dir, "data") ++base_dir = os.path.dirname(tests_dir) ++ ++os.environ["SUGAR_MIME_DEFAULTS"] = \ ++ os.path.join(base_dir, "data", "mime.defaults") ++ ++ ++class TestBundleRegistry(unittest.TestCase): ++ def setUp(self): ++ activities_path = tempfile.mkdtemp() ++ library_path = tempfile.mkdtemp() ++ os.environ['SUGAR_ACTIVITIES_PATH'] = activities_path ++ os.environ['SUGAR_LIBRARY_PATH'] = library_path ++ ++ def tearDown(self): ++ activities_path = os.environ.pop('SUGAR_ACTIVITIES_PATH', None) ++ if activities_path: ++ shutil.rmtree(activities_path) ++ ++ library_path = os.environ.pop('SUGAR_LIBRARY_PATH', None) ++ if library_path: ++ shutil.rmtree(library_path) ++ ++ def test_install_content(self): ++ registry = bundleregistry.get_registry() ++ bundle = bundle_from_archive(os.path.join(data_dir, 'sample-1.xol')) ++ registry.install(bundle) ++ installed_bundle = registry.get_bundle("org.sugarlabs.samplecontent") ++ self.assertIsNotNone(installed_bundle) ++ ++ def test_install_activity(self): ++ registry = bundleregistry.get_registry() ++ bundle = bundle_from_archive(os.path.join(data_dir, 'activity-1.xo')) ++ registry.install(bundle) ++ installed_bundle = registry.get_bundle("org.sugarlabs.MyActivity") ++ self.assertIsNotNone(installed_bundle) +diff --git b/tests/test_desktop_config.py a/tests/test_desktop_config.py +new file mode 100644 +index 0000000..d561262 +--- /dev/null ++++ a/tests/test_desktop_config.py +@@ -0,0 +1,77 @@ ++# Copyright (C) 2013, Walter Bender ++# ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see <http://www.gnu.org/licenses/>. ++ ++from sugar3.test import unittest ++ ++from gi.repository import Gio ++from gi.repository import GLib ++ ++from jarabe.model import desktop ++ ++_DESKTOP_CONF_DIR = 'org.sugarlabs.desktop' ++_HOMEVIEWS_KEY = 'homeviews' ++ ++_VIEW_ICONS = [{'layout': 'box-layout', 'view-icon': 'view-radial', ++ 'favorite-icon': 'emblem-locked'}] ++_MOCK_LIST = [{'layout': 'box-layout', 'view-icon': 'view-radial', ++ 'favorite-icon': 'emblem-locked'}, ++ {'layout': 'ring-layout', 'view-icon': 'view-box', ++ 'favorite-icon': 'emblem-favorite'}] ++ ++ ++class TestDesktopConfig(unittest.UITestCase): ++ ++ def setUp(self): ++ self.target = [] ++ ++ settings = Gio.Settings.new(_DESKTOP_CONF_DIR) ++ self._save_homeviews = settings.get_value(_HOMEVIEWS_KEY) ++ ++ self.model = desktop.get_model() ++ self.model.connect('desktop-view-icons-changed', ++ self.__desktop_view_icons_changed_cb) ++ ++ def __desktop_view_icons_changed_cb(self, model): ++ number_of_views = desktop.get_number_of_views() ++ self.assertTrue(number_of_views == len(self.target)) ++ ++ view_icons = desktop.get_view_icons() ++ self.assertTrue(len(view_icons) == len(self.target)) ++ ++ right_view_icons = [view['view-icon'] for view in self.target] ++ for i in range(len(view_icons)): ++ self.assertTrue(view_icons[i] in right_view_icons) ++ ++ favorite_icons = desktop.get_favorite_icons() ++ self.assertTrue(len(favorite_icons) >= len(self.target)) ++ ++ def test_unset_views(self): ++ self.target = _VIEW_ICONS ++ with self.run_view("gtk_main"): ++ settings = Gio.Settings.new(_DESKTOP_CONF_DIR) ++ variant = GLib.Variant('aa{ss}', self.target) ++ settings.set_value(_HOMEVIEWS_KEY, variant) ++ ++ def test_set_views(self): ++ self.target = _MOCK_LIST ++ with self.run_view("gtk_main"): ++ settings = Gio.Settings.new(_DESKTOP_CONF_DIR) ++ variant = GLib.Variant('aa{ss}', self.target) ++ settings.set_value(_HOMEVIEWS_KEY, variant) ++ ++ def tearDown(self): ++ self.target = self._save_homeviews.unpack() ++ settings = Gio.Settings.new(_DESKTOP_CONF_DIR) ++ settings.set_value(_HOMEVIEWS_KEY, self._save_homeviews) +diff --git b/tests/test_downloader.py a/tests/test_downloader.py +new file mode 100644 +index 0000000..7e661ce +--- /dev/null ++++ a/tests/test_downloader.py +@@ -0,0 +1,89 @@ ++# Copyright (C) 2013, One Laptop per Child ++# ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see <http://www.gnu.org/licenses/>. ++ ++import os ++import unittest ++import threading ++import http.server ++import socketserver ++ ++from gi.repository import Gtk ++ ++from sugar3 import env ++from jarabe.util.downloader import Downloader ++ ++profile_data_dir = os.path.join(env.get_profile_path(), 'data') ++if not os.path.isdir(profile_data_dir): ++ os.makedirs(profile_data_dir) ++ ++tests_dir = os.getcwd() ++data_dir = os.path.join(tests_dir, "data") ++ ++ ++class TestDownloader(unittest.TestCase): ++ def setUp(self): ++ handler = http.server.SimpleHTTPRequestHandler ++ self._server = socketserver.TCPServer(("", 0), handler) ++ self._port = self._server.server_address[1] ++ self._server_thread = threading.Thread(target=self._run_http_server) ++ self._server_thread.daemon = True ++ self._server_thread.start() ++ ++ def tearDown(self): ++ self._server.shutdown() ++ self._server_thread.join() ++ ++ def _run_http_server(self): ++ self._server.serve_forever() ++ ++ def download_complete_cb(self, downloader, result): ++ self._complete = True ++ self._result = result ++ ++ def test_download_to_temp(self): ++ downloader = Downloader("http://0.0.0.0:%d/data/test.txt" % self._port) ++ self._complete = False ++ downloader.connect('complete', self.download_complete_cb) ++ downloader.download_to_temp() ++ ++ while not self._complete: ++ Gtk.main_iteration() ++ ++ self.assertIsNone(self._result) ++ path = downloader.get_local_file_path() ++ text = open(path, "r").read() ++ self.assertEqual("hello\n", text) ++ ++ def test_download(self): ++ downloader = Downloader("http://0.0.0.0:%d/data/test.txt" % self._port) ++ self._complete = False ++ downloader.connect('complete', self.download_complete_cb) ++ downloader.download() ++ ++ while not self._complete: ++ Gtk.main_iteration() ++ ++ self.assertEqual("hello\n", self._result.get_data()) ++ ++ def test_get_size(self): ++ downloader = Downloader("http://0.0.0.0:%d/data/test.txt" % self._port) ++ self._complete = False ++ downloader.connect('complete', self.download_complete_cb) ++ downloader.get_size() ++ ++ while not self._complete: ++ Gtk.main_iteration() ++ ++ self.assertEqual(6, self._result) +diff --git b/tests/test_journaltoolbox.py a/tests/test_journaltoolbox.py +new file mode 100644 +index 0000000..3631638 +--- /dev/null ++++ a/tests/test_journaltoolbox.py +@@ -0,0 +1,31 @@ ++# Copyright (C) 2012, Daniel Narvaez ++# Copyright (C) 2013, Walter Bender ++# ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see <http://www.gnu.org/licenses/>. ++ ++from sugar3.test import unittest ++from sugar3.test import uitree ++ ++ACCOUNT_NAME = 'mock' ++ ++ ++class TestDetailToolBox(unittest.UITestCase): ++ ++ def test_detail_toolbox(self): ++ with self.run_view("journal_detailstoolbox"): ++ root = uitree.get_root() ++ ++ for name in ['Clipboard', ACCOUNT_NAME]: ++ node = root.find_child(name=name, role_name='menu item') ++ self.assertIsNotNone(node) +diff --git b/tests/test_microformat.py a/tests/test_microformat.py +new file mode 100644 +index 0000000..4ce3ebe +--- /dev/null ++++ a/tests/test_microformat.py +@@ -0,0 +1,52 @@ ++# Copyright (C) 2013, One Laptop per Child ++# ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see <http://www.gnu.org/licenses/>. ++ ++import unittest ++import os ++ ++from sugar3.bundle.bundleversion import NormalizedVersion ++ ++from jarabe.model.update.microformat import _UpdateHTMLParser ++from jarabe.model.update.microformat import MetadataLookup ++ ++tests_dir = os.getcwd() ++data_dir = os.path.join(tests_dir, "data") ++ ++ ++class TestMicroformat(unittest.TestCase): ++ def test_html_parser(self): ++ parser = _UpdateHTMLParser("http://www.sugarlabs.org") ++ fd = open(os.path.join(data_dir, "microformat.html"), "r") ++ parser.feed(fd.read()) ++ parser.close() ++ ++ results = parser.results ++ self.assertIn('org.sugarlabs.AbacusActivity', list(results.keys())) ++ self.assertIn('org.laptop.WebActivity', list(results.keys())) ++ ++ # test that we picked the newest version ++ version, url = results['org.sugarlabs.AbacusActivity'] ++ self.assertEqual(NormalizedVersion("43"), version) ++ self.assertEqual("http://download.sugarlabs.org/abacus-43.xo", url) ++ ++ # test resolve relative url ++ version, url = results['org.laptop.WebActivity'] ++ self.assertEqual("http://www.sugarlabs.org/browse-149.xo", url) ++ ++ def test_zip_name_lookup(self): ++ fd = open(os.path.join(data_dir, "activity-1.xo")) ++ lookup = MetadataLookup(None) ++ name = lookup._name_from_fd(fd) ++ self.assertEqual("My Activity", name) +diff --git b/tests/test_modemconfiguration.py a/tests/test_modemconfiguration.py +new file mode 100644 +index 0000000..b8b61e5 +--- /dev/null ++++ a/tests/test_modemconfiguration.py +@@ -0,0 +1,188 @@ ++# -*- encoding: utf-8 -*- ++# Copyright (C) 2013, Miguel González ++# ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see <http://www.gnu.org/licenses/>. ++ ++import unittest ++from xml.etree.cElementTree import ElementTree ++ ++from mock import patch ++ ++from cpsection.modemconfiguration.model import CountryCodeParser, \ ++ ServiceProvidersParser, ServiceProviders, PROVIDERS_PATH ++from cpsection.modemconfiguration.model import CONF_SP_COUNTRY, \ ++ CONF_SP_PROVIDER, CONF_SP_PLAN ++ ++ ++class CountryCodeParserTest(unittest.TestCase): ++ def test_get_country(self): ++ self.assertEqual(CountryCodeParser().get('ad'), 'Andorra') ++ self.assertEqual(CountryCodeParser().get('es'), 'Spain') ++ self.assertEqual(CountryCodeParser().get('zw'), 'Zimbabwe') ++ ++ def test_raise_if_not_found(self): ++ with self.assertRaises(KeyError): ++ CountryCodeParser().get('xx') ++ ++ ++class ServiceProvidersParserTest(unittest.TestCase): ++ def setUp(self): ++ self.tree = ElementTree(file=PROVIDERS_PATH) ++ self.countries_from_xml = self.tree.findall('country') ++ self.db = ServiceProvidersParser() ++ self.countries_from_class = self.db.get_countries() ++ ++ def test_get_countries(self): ++ for country in self.countries_from_class: ++ self.assertEqual(country.tag, 'country') ++ ++ def test_get_country_idx_by_code(self): ++ for idx, country in enumerate(self.countries_from_class): ++ country_code = country.attrib['code'] ++ country_idx = self.db.get_country_idx_by_code(country_code) ++ self.assertEqual(idx, country_idx) ++ ++ def test_get_country_name_by_idx(self): ++ for idx, country in enumerate(self.countries_from_class): ++ country_code = country.attrib['code'] ++ self.assertEqual( ++ CountryCodeParser().get(country_code), ++ self.db.get_country_name_by_idx(idx) ++ ) ++ ++ def test_get_providers(self): ++ for country_idx, country in enumerate(self.countries_from_class): ++ providers = self.db.get_providers(country_idx) ++ for provider in providers: ++ self.assertEqual(provider.tag, 'provider') ++ self.assertIsNotNone(provider.find('.//gsm')) ++ ++ def test_get_plans(self): ++ for country_idx, country in enumerate(self.countries_from_class): ++ providers = self.db.get_providers(country_idx) ++ for provider_idx, provider in enumerate(providers): ++ plans = self.db.get_plans(country_idx, provider_idx) ++ for plan in plans: ++ self.assertEqual(plan.tag, 'apn') ++ ++ def get_providers(self, country_xml): ++ """Given a country element find all provider with a gsm tag.""" ++ idx = 0 ++ for provider in country_xml.findall('provider'): ++ if provider.find('.//gsm'): ++ yield idx, provider ++ idx = idx + 1 ++ ++ def get_plans(self, provider_xml): ++ """Given a provider element find all apn elements.""" ++ for idx, plan in enumerate(provider_xml.findall('.//apn')): ++ yield idx, plan ++ ++ def test_get_some_specific_values(self): ++ for country in self.countries_from_xml: ++ country_code = country.attrib['code'] ++ country_idx = self.db.get_country_idx_by_code(country_code) ++ ++ for provider_idx, provider in self.get_providers(country): ++ plans_from_class = self.db.get_plans(country_idx, ++ provider_idx) ++ ++ for plan_idx, plan in self.get_plans(provider): ++ plan_from_class = plans_from_class[plan_idx] ++ self.assertEqual(plan.attrib['value'], ++ plan_from_class.attrib['value']) ++ ++ ++class ServiceProvidersTest(unittest.TestCase): ++ def setUp(self): ++ self.db = ServiceProviders() ++ self.countries = self.db.get_countries() ++ ++ def test_go_trough_all_combo_options(self): ++ # Traverse countries ++ for country in self.countries: ++ # Check if country is stored ++ self.db.set_country(country.idx) ++ new_country = self.db.get_country() ++ self.assertEqual(country.code, new_country.code) ++ ++ # Traverse providers for country ++ providers = self.db.get_providers() ++ for provider in providers: ++ # Check if provider is stored ++ self.db.set_provider(provider.idx) ++ new_provider = self.db.get_provider() ++ self.assertEqual(provider.name, new_provider.name) ++ ++ # Traverse plans for provider ++ plans = self.db.get_plans() ++ for plan in plans: ++ # Check if plan is stored ++ self.db.set_plan(plan.idx) ++ new_plan = self.db.get_plan() ++ self.assertEqual(plan.name, new_plan.name) ++ ++ # Check if selection is permanently stored ++ db2 = ServiceProviders() ++ country2 = db2.get_country() ++ provider2 = db2.get_provider() ++ plan2 = db2.get_plan() ++ self.assertEqual(country2.idx, country.idx) ++ self.assertEqual(provider2.idx, provider.idx) ++ self.assertEqual(plan2.idx, plan.idx) ++ ++ ++class FakeConfClient(object): ++ ++ def __init__(self, **kwargs): ++ self.store = { ++ CONF_SP_COUNTRY: None, ++ CONF_SP_PROVIDER: None, ++ CONF_SP_PLAN: None, ++ } ++ self.store.update(kwargs) ++ ++ def get_string(self, key): ++ return self.store[key] ++ ++ def set_string(self, key, value): ++ self.store[key] = value ++ return ++ ++ def get_int(self, key): ++ return self.store[key] ++ ++ def set_int(self, key, value): ++ self.store[key] = value ++ return ++ ++ ++class ServiceProvidersGuessCountryTest(unittest.TestCase): ++ def setUp(self): ++ # patch Gio.Settings to use a fake client ++ conf_patcher = patch('gi.repository.Gio.Settings') ++ conf_mock = conf_patcher.start() ++ conf_mock.return_value = FakeConfClient(CONF_SP_COUNTRY=None) ++ self.addCleanup(conf_patcher.stop) ++ ++ def test_guess_country(self): ++ LOCALE = ('hi_IN', 'UTF-8') ++ default_country_code = LOCALE[0][3:5].lower() ++ ++ with patch('locale.getdefaultlocale') as locale_mock: ++ locale_mock.return_value = LOCALE ++ ++ db = ServiceProviders() ++ country = db.get_country() ++ self.assertEqual(country.code, default_country_code) +diff --git b/tests/test_user_profile.py a/tests/test_user_profile.py +new file mode 100644 +index 0000000..f9950de +--- /dev/null ++++ a/tests/test_user_profile.py +@@ -0,0 +1,62 @@ ++# -*- coding: utf-8 -*- ++# Copyright (C) 2014, Ignacio Rodriguez ++# ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see <http://www.gnu.org/licenses/>. ++ ++import unittest ++ ++from cpsection.aboutme import model ++from jarabe.intro.agepicker import AGES ++from jarabe.intro.genderpicker import GENDERS ++ ++TEST_NICKS = ['Ajay Garg', 'Aleksey Lim', ++ 'Bernie H. Innocenti', 'Daniel Narvaez', ++ 'Emil Dudev', 'Gonzalo Odiard', ++ 'Ignacio RodrÃguez', 'Jorge Alberto Gómez López', ++ 'Sai Vineet', 'Sam Parkinson', ++ 'Sascha Silbe', 'Walter Bender'] ++ ++TEST_COLORS = [['#FF8F00', '#FF2B34'], ++ ['#00A0FF', '#008009'], ++ ['#BCCEFF', '#F8E800'], ++ ['#FF2B34', '#7F00BF'], ++ ['#FF2B34', '#5E008C'], ++ ['#BCCDFF', '#AC32FF'], ++ ['#00EA11', '#9A5200'], ++ ['#A700FF', '#FF8F00'], ++ ['#00EA11', '#7F00BF'], ++ ['#8BFF7A', '#F8E800'], ++ ['#00A0FF', '#5E008C'], ++ ['#7F00BF', '#AC32FF']] ++ ++ ++class TestUserProfile(unittest.TestCase): ++ def test_user_gender_age(self): ++ for gender in GENDERS: ++ for age in AGES: ++ model.set_gender(gender) ++ model.set_age(age) ++ self.assertEqual(model.get_age(), age) ++ self.assertEqual(model.get_gender(), gender) ++ ++ def test_user_nick(self): ++ for nick in TEST_NICKS: ++ model.set_nick(nick) ++ self.assertEqual(model.get_nick(), nick) ++ ++ def test_user_color(self): ++ for new_color in TEST_COLORS: ++ new_color = "%s,%s" % (new_color[0], new_color[1]) ++ model.set_color_xo(new_color) ++ self.assertEqual(model.get_color(), new_color) +diff --git b/tests/test_webaccount.py a/tests/test_webaccount.py +new file mode 100644 +index 0000000..7c4681a +--- /dev/null ++++ a/tests/test_webaccount.py +@@ -0,0 +1,31 @@ ++# Copyright (C) 2012, Daniel Narvaez ++# Copyright (C) 2013, Walter Bender ++# ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see <http://www.gnu.org/licenses/>. ++ ++from sugar3.test import unittest ++from sugar3.test import uitree ++ ++ACCOUNT_NAME = 'mock' ++ ++ ++class TestWebAccount(unittest.UITestCase): ++ ++ def test_webaccount(self): ++ with self.run_view("webaccount"): ++ root = uitree.get_root() ++ ++ for name in [ACCOUNT_NAME]: ++ node = root.find_child(name=name, role_name='label') ++ self.assertIsNotNone(node) +diff --git b/tests/test_webservice.py a/tests/test_webservice.py +new file mode 100644 +index 0000000..56de599 +--- /dev/null ++++ a/tests/test_webservice.py +@@ -0,0 +1,114 @@ ++# Copyright (C) 2013, Walter Bender ++# ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see <http://www.gnu.org/licenses/>. ++ ++import os ++import sys ++import unittest ++ ++from gi.repository import Gtk ++ ++from jarabe import config ++from jarabe.webservice.account import Account ++from jarabe.webservice import accountsmanager ++ ++ACCOUNT_NAME = 'mock' ++ ++tests_dir = os.getcwd() ++extension_dir = os.path.join(tests_dir, 'extensions') ++web_extension_dir = os.path.join(extension_dir, 'webservice') ++ ++ ++class TestWebAccounts(unittest.TestCase): ++ def setUp(self): ++ os.environ["MOCK_ACCOUNT_STATE"] = str(Account.STATE_NONE) ++ self.save_ext_path = config.ext_path ++ config.ext_path = extension_dir ++ sys.path.append(config.ext_path) ++ ++ def test_get_description(self): ++ accounts = accountsmanager.get_all_accounts() ++ found_mock_account = False ++ for account in accounts: ++ if account.get_description() == ACCOUNT_NAME: ++ found_mock_account = True ++ break ++ self.assertTrue(found_mock_account) ++ ++ def test_icon_theme(self): ++ icon_theme = Gtk.IconTheme.get_default() ++ icon_search_path = icon_theme.get_search_path() ++ icon_path = os.path.join(web_extension_dir, ACCOUNT_NAME, 'icons') ++ self.assertTrue(icon_path in icon_search_path) ++ ++ def test_get_webaccount_services(self): ++ services = accountsmanager.get_webaccount_services() ++ self.assertTrue(len(services) > 0) ++ ++ def test_get_all_accounts(self): ++ accounts = accountsmanager.get_all_accounts() ++ self.assertTrue(len(accounts) > 0) ++ ++ def test_get_account(self): ++ account = accountsmanager.get_account('mock') ++ self.assertIsNotNone(account) ++ ++ def test_get_service(self): ++ account = accountsmanager.get_service('mock') ++ self.assertIsNotNone(account) ++ ++ def test_get_configured_accounts(self): ++ os.environ["MOCK_ACCOUNT_STATE"] = str(Account.STATE_VALID) ++ accounts = accountsmanager.get_configured_accounts() ++ count = len(accounts) ++ self.assertTrue(count > 0) ++ ++ self.assertTrue(accountsmanager.has_configured_accounts()) ++ ++ os.environ["MOCK_ACCOUNT_STATE"] = str(Account.STATE_NONE) ++ accounts = accountsmanager.get_configured_accounts() ++ self.assertTrue(len(accounts) == count - 1) ++ ++ os.environ["MOCK_ACCOUNT_STATE"] = str(Account.STATE_EXPIRED) ++ accounts = accountsmanager.get_configured_accounts() ++ self.assertTrue(len(accounts) == count) ++ ++ def test_get_active_accounts(self): ++ os.environ["MOCK_ACCOUNT_STATE"] = str(Account.STATE_VALID) ++ accounts = accountsmanager.get_active_accounts() ++ count = len(accounts) ++ self.assertTrue(count > 0) ++ ++ os.environ["MOCK_ACCOUNT_STATE"] = str(Account.STATE_EXPIRED) ++ accounts = accountsmanager.get_active_accounts() ++ self.assertTrue(len(accounts) == count - 1) ++ ++ def test_share_menu(self): ++ accounts = accountsmanager.get_all_accounts() ++ for account in accounts: ++ shared_journal_entry = account.get_shared_journal_entry() ++ share_menu = shared_journal_entry.get_share_menu( ++ {'account': 'mock'}) ++ self.assertIsNotNone(share_menu) ++ ++ def test_refresh_menu(self): ++ accounts = accountsmanager.get_all_accounts() ++ for account in accounts: ++ shared_journal_entry = account.get_shared_journal_entry() ++ refresh_menu = shared_journal_entry.get_refresh_menu() ++ self.assertIsNotNone(refresh_menu) ++ ++ def tearDown(self): ++ sys.path.remove(config.ext_path) ++ config.ext_path = self.save_ext_path +diff --git b/tests/views/activitieslist.py a/tests/views/activitieslist.py +new file mode 100644 +index 0000000..e954b47 +--- /dev/null ++++ a/tests/views/activitieslist.py +@@ -0,0 +1,59 @@ ++# Copyright (C) 2013, Daniel Narvaez ++# ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see <http://www.gnu.org/licenses/>. ++ ++import os ++ ++from gi.repository import Gtk ++from dbus.mainloop.glib import DBusGMainLoop ++DBusGMainLoop(set_as_default=True) ++ ++from jarabe.desktop.activitieslist import ActivityListPalette ++ ++ ++tests_dir = os.getcwd() ++base_dir = os.path.dirname(tests_dir) ++data_dir = os.path.join(tests_dir, "data") ++ ++ ++class MockActivityInfo: ++ def get_bundle_id(self): ++ return "mock" ++ ++ def get_activity_version(self): ++ return 1 ++ ++ def get_is_favorite(self): ++ return False ++ ++ def get_icon(self): ++ return os.path.join(data_dir, "activity.svg") ++ ++ def get_name(self): ++ return "mock" ++ ++ def get_path(self): ++ return "mock" ++ ++ def is_user_activity(self): ++ return True ++ ++ ++os.environ["SUGAR_MIME_DEFAULTS"] = \ ++ os.path.join(base_dir, "data", "mime.defaults") ++ ++palette = ActivityListPalette(MockActivityInfo()) ++palette.popup() ++ ++Gtk.main() +diff --git b/tests/views/gtk_main.py a/tests/views/gtk_main.py +new file mode 100644 +index 0000000..2dc088d +--- /dev/null ++++ a/tests/views/gtk_main.py +@@ -0,0 +1,18 @@ ++# Copyright (C) 2013, Walter Bender ++# ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see <http://www.gnu.org/licenses/>. ++ ++from gi.repository import Gtk ++ ++Gtk.main() +diff --git b/tests/views/journal_detailstoolbox.py a/tests/views/journal_detailstoolbox.py +new file mode 100644 +index 0000000..77e4fee +--- /dev/null ++++ a/tests/views/journal_detailstoolbox.py +@@ -0,0 +1,54 @@ ++# Copyright (C) 2013, Walter Bender ++# ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see <http://www.gnu.org/licenses/>. ++ ++import os ++import sys ++ ++from gi.repository import Gtk ++from dbus.mainloop.glib import DBusGMainLoop ++DBusGMainLoop(set_as_default=True) ++ ++from jarabe import config ++from jarabe.journal.journaltoolbox import DetailToolbox ++from jarabe.journal.journalwindow import JournalWindow ++from jarabe.webservice.account import Account ++ ++ACCOUNT_NAME = 'mock' ++ ++ ++class JournalMock(JournalWindow): ++ def get_mount_point(self): ++ return '/' ++ ++ ++tests_dir = os.getcwd() ++extension_dir = os.path.join(tests_dir, 'extensions') ++ ++os.environ["MOCK_ACCOUNT_STATE"] = str(Account.STATE_VALID) ++config.ext_path = extension_dir ++sys.path.append(config.ext_path) ++ ++window = Gtk.Window() ++ ++toolbox = DetailToolbox(JournalMock()) ++toolbox.show() ++ ++window.add(toolbox) ++window.show() ++ ++toolbox.set_metadata({'mountpoint': '/', 'uid': '', 'title': 'mock'}) ++toolbox._copy.palette.popup(immediate=True) ++ ++Gtk.main() +diff --git b/tests/views/webaccount.py a/tests/views/webaccount.py +new file mode 100644 +index 0000000..f40ebb6 +--- /dev/null ++++ a/tests/views/webaccount.py +@@ -0,0 +1,46 @@ ++# Copyright (C) 2013, Walter Bender ++# ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see <http://www.gnu.org/licenses/>. ++ ++import os ++import sys ++ ++from gi.repository import Gtk ++ ++from jarabe import config ++from jarabe.webservice.account import Account ++from jarabe.webservice import accountsmanager ++ ++ACCOUNT_NAME = 'mock' ++ ++tests_dir = os.getcwd() ++extension_dir = os.path.join(tests_dir, 'extensions') ++ ++os.environ["MOCK_ACCOUNT_STATE"] = str(Account.STATE_VALID) ++config.ext_path = extension_dir ++sys.path.append(config.ext_path) ++ ++window = Gtk.Window() ++box = Gtk.HBox() ++box.show() ++window.add(box) ++ ++services = accountsmanager.get_webaccount_services() ++for service in services: ++ if service.get_icon_name() == ACCOUNT_NAME: ++ service.config_service_cb(None, None, box) ++ ++window.show() ++ ++Gtk.main()