Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLionel LASKE <llaske@c2s.fr>2012-12-02 20:30:13 (GMT)
committer Lionel LASKE <llaske@c2s.fr>2012-12-02 20:30:13 (GMT)
commitd945497aae7c2b6aa8e8c5403d23c852c5b7d7b9 (patch)
tree8ce958e0f1ab2f79900be55631697af74fefe25c
parent1a12a4bbc162623abf9ab377d2f44ae8ea1d015a (diff)
Dynamic localization handling via a ComboBox in the activity ToolbarHEADmaster
-rw-r--r--activity.py35
-rw-r--r--html/app.js39
-rw-r--r--html/buildgame.js17
-rw-r--r--html/card.js6
-rw-r--r--html/credits.js18
-rw-r--r--html/index.html1
-rw-r--r--html/learngame.js23
-rw-r--r--html/playgame.js10
-rw-r--r--html/util.js20
-rw-r--r--l10n.py177
10 files changed, 247 insertions, 99 deletions
diff --git a/activity.py b/activity.py
index 047a5ce..06310e7 100644
--- a/activity.py
+++ b/activity.py
@@ -28,8 +28,9 @@ from datetime import date
from enyo import Enyo
-from l10n import _fc_l10n
+from l10n import FoodChainLocalization
+_fc = FoodChainLocalization()
# Init log
_logger = logging.getLogger('roots-activity')
@@ -47,6 +48,7 @@ class FoodChainActivity(activity.Activity):
def __init__(self, handle):
"""Set up the activity."""
self.context = {}
+ self.enyo = None
self.showconsole = False
activity.Activity.__init__(self, handle)
@@ -69,7 +71,9 @@ class FoodChainActivity(activity.Activity):
def init_context(self, args):
"Init Javascript context sending information about localization and saved game"
- self.enyo.send_message("localization", _fc_l10n)
+ self.languages.set_active(int(self.context['lang']));
+ _fc.set_locale(['','en','fr'][self.languages.get_active()])
+ self.enyo.send_message("localization", _fc.strings)
self.enyo.send_message("load-context", self.context)
def make_mainview(self):
@@ -138,6 +142,23 @@ class FoodChainActivity(activity.Activity):
toolbar_box.toolbar.insert(share_button, -1)
share_button.show()
+ liststore = Gtk.ListStore(str)
+ self.languages = languages = Gtk.ComboBox()
+ languages.set_model(liststore)
+ liststore.append(["Default"])
+ liststore.append(["English"])
+ liststore.append(["Français"])
+ cell = Gtk.CellRendererText()
+ languages.pack_end(cell, True)
+ languages.add_attribute(cell, 'text', 0)
+ lang_item = Gtk.ToolItem()
+ lang_item.add(languages)
+ languages.connect('changed', self.language_changed)
+ languages.set_active(0)
+ languages.show()
+ toolbar_box.toolbar.insert(lang_item, -1)
+ lang_item.show()
+
separator = Gtk.SeparatorToolItem()
separator.props.draw = False
separator.set_expand(True)
@@ -152,6 +173,14 @@ class FoodChainActivity(activity.Activity):
toolbar_box.show()
+ def language_changed(self, languages):
+ "Called when language is changed from the toolbar, send localization to Enyo"
+ if self.enyo is None:
+ return
+ _fc.set_locale(['','en','fr'][languages.get_active()])
+ self.enyo.send_message("localization", _fc.strings)
+
+
def write_file(self, file_path):
"Called when activity is saved, get the current context in Enyo"
self.file_path = file_path
@@ -165,6 +194,7 @@ class FoodChainActivity(activity.Activity):
file.write(str(context['score'])+'\n')
file.write(context['game']+'\n')
file.write(str(context['level'])+'\n')
+ file.write(str(self.languages.get_active())+'\n')
finally:
file.close()
@@ -177,6 +207,7 @@ class FoodChainActivity(activity.Activity):
self.context['score'] = file.readline().strip('\n')
self.context['game'] = file.readline().strip('\n')
self.context['level'] = file.readline().strip('\n')
+ self.context['lang'] = file.readline().strip('\n')
finally:
file.close()
diff --git a/html/app.js b/html/app.js
index 8d8937f..0a934b1 100644
--- a/html/app.js
+++ b/html/app.js
@@ -40,14 +40,25 @@ enyo.kind({
// Create game description
this.$.popup.hide();
this.games = [];
- this.games["one"] = { title: __$FC("learn"), description: __$FC("learndesc") };
- this.games["two"] = { title: __$FC("build"), description: __$FC("builddesc") };
- this.games["three"] = { title: __$FC("play"), description: __$FC("playdesc") };
+ this.setLocale();
// Init soundtrack
this.soundtrack = "audio/popcorn";
},
+ // Localization, changed update cards and description
+ setLocale: function() {
+ // Update description
+ this.games["one"] = { title: __$FC("learn"), description: __$FC("learndesc") };
+ this.games["two"] = { title: __$FC("build"), description: __$FC("builddesc") };
+ this.games["three"] = { title: __$FC("play"), description: __$FC("playdesc") };
+
+ // Change card localization if any
+ enyo.forEach(this.$.cardbox.getControls(), function(card) {
+ card.setLocale();
+ });
+ },
+
// Init card stack for the animation
initCardStack: function() {
// Pick randomly N cards
@@ -71,7 +82,7 @@ enyo.kind({
rendered: function() {
// Context not null, resume the game previously stopped
if (FoodChain.context.game != "") {
- enyo.create({
+ FoodChain.context.object = enyo.create({
kind: FoodChain.context.game,
level: FoodChain.context.level
}).renderInto(document.getElementById("body"));
@@ -80,6 +91,7 @@ enyo.kind({
// Update context, no game playing
FoodChain.context.game = "";
+ FoodChain.context.object = this;
// Play soundtrack
FoodChain.sound.play(this.soundtrack);
@@ -104,7 +116,7 @@ enyo.kind({
}
// Display a new card
- var x = Math.floor(Math.random()*1000);
+ var x = Math.floor(Math.random()*(FoodChain.getConfig("screen-width")-FoodChain.getConfig("card-width")));
var y = Math.floor(Math.random()*400);
this.$.cardbox.createComponent({ kind: "FoodChain.Card", cardname: this.cards[this.cardcount], x: x, y: y, z: 0}).render();
this.cardcount = this.cardcount + 1;
@@ -127,7 +139,9 @@ enyo.kind({
// Show credit page
showCredits: function() {
- new FoodChain.Credits().renderInto(document.getElementById("body"));
+ this.$.timer.stop();
+ this.removeComponent(this.$.timer);
+ FoodChain.context.object = new FoodChain.Credits().renderInto(document.getElementById("body"));
},
// Launch a game
@@ -139,22 +153,21 @@ enyo.kind({
this.removeComponent(this.$.timer);
// Launch Learn game
- var game;
if (s.name == "one") {
- game = new FoodChain.LearnGame({level: 1}).renderInto(document.getElementById("body"));
- FoodChain.context.game = game.kindName;
+ FoodChain.context.object = new FoodChain.LearnGame({level: 1}).renderInto(document.getElementById("body"));
+ FoodChain.context.game = FoodChain.context.object.kindName;
}
// Launch Build game
else if (s.name == "two") {
- game = new FoodChain.BuildGame({level: 1}).renderInto(document.getElementById("body"));
- FoodChain.context.game = game.kindName;
+ FoodChain.context.object = new FoodChain.BuildGame({level: 1}).renderInto(document.getElementById("body"));
+ FoodChain.context.game = FoodChain.context.object.kindName;
}
// Launch Play game
else if (s.name == "three") {
- game = new FoodChain.PlayGame({level: 1}).renderInto(document.getElementById("body"));
- FoodChain.context.game = game.kindName;
+ FoodChain.context.object = new FoodChain.PlayGame({level: 1}).renderInto(document.getElementById("body"));
+ FoodChain.context.game = FoodChain.context.object.kindName;
}
}
});
diff --git a/html/buildgame.js b/html/buildgame.js
index acf01dc..01cfe7a 100644
--- a/html/buildgame.js
+++ b/html/buildgame.js
@@ -48,12 +48,23 @@ enyo.kind({
this.previous = null;
this.mixed = null;
this.createComponent({ name: "timer", kind: "Timer", paused: true, onTriggered: "updateTimer" }, {owner: this});
- this.$.textlevel.setContent(__$FC("level"));
- this.$.textscore.setContent(__$FC("score"));
+ this.setLocale();
this.$.score.setContent(String("0000"+FoodChain.context.score).slice(-4));
this.levelChanged();
},
+ // Localization changed, update cards and string resource
+ setLocale: function() {
+ // Update string resources
+ this.$.textlevel.setContent(__$FC("level"));
+ this.$.textscore.setContent(__$FC("score"));
+
+ // Update cards
+ enyo.forEach(this.$.gamebox.getControls(), function(card) {
+ card.setLocale();
+ });
+ },
+
// Level changed, init board then start game
levelChanged: function() {
// Delete current cards on board
@@ -133,7 +144,7 @@ enyo.kind({
// Display next card
for (var i = 0 ; i < this.cards.length ; i++ ) {
- if (this.cards[i] != null && this.cards[i].sound == s) {
+ if (this.cards[i] != null && FoodChain.soundMatch(this.cards[i].sound,s)) {
this.cards[i] = null;
if (i+1 < this.cards.length) {
this.cards[i+1].show();
diff --git a/html/card.js b/html/card.js
index 366596d..a2cebdb 100644
--- a/html/card.js
+++ b/html/card.js
@@ -24,6 +24,12 @@ enyo.kind({
this.inherited(arguments);
},
+ // Localization changed, update card
+ setLocale: function() {
+ this.cardnameChanged();
+ this.render();
+ },
+
// Card setup
cardnameChanged: function() {
var image = "images/cards/"+this.cardname+".png";
diff --git a/html/credits.js b/html/credits.js
index a92d68b..0d1d4f0 100644
--- a/html/credits.js
+++ b/html/credits.js
@@ -7,16 +7,16 @@ enyo.kind({
components: [
{ components: [
{ classes: "two-column-credits", components: [
- { content: __$FC("concept"), classes: "credit-title" },
+ { name: "concept", classes: "credit-title" },
{ content: "Lionel Laské", classes: "credit-name" },
- { content: __$FC("arts"), classes: "credit-title" },
+ { name: "arts", classes: "credit-title" },
{ content: "Art4Apps (learn & build game)", classes: "credit-name" },
{ content: "Vicki Wenderlich (play game)", classes: "credit-name" },
{ content: "Mathafix (icon)", classes: "credit-name" },
{ content: "Ray Larabie (home font)", classes: "credit-name" },
- { content: __$FC("music"), classes: "credit-title" },
+ { name: "music", classes: "credit-title" },
{ content: "part of Popcorn by Gershon Kingsley", classes: "credit-name" },
- { content: __$FC("sound"), classes: "credit-title" },
+ { name: "sound", classes: "credit-title" },
{ content: "Charel Sytze (applause)", classes: "credit-name" },
{ content: "Unchaz (disappointment)", classes: "credit-name" },
{ content: "Esformouse (frog)", classes: "credit-name" },
@@ -40,10 +40,20 @@ enyo.kind({
create: function() {
this.inherited(arguments);
+ this.setLocale();
+
// Init soundtrack
this.soundtrack = "audio/popcorn";
},
+ // Localization changed, update string resource
+ setLocale: function() {
+ this.$.concept.setContent(__$FC("concept"));
+ this.$.arts.setContent(__$FC("arts"));
+ this.$.music.setContent(__$FC("music"));
+ this.$.sound.setContent(__$FC("sound"));
+ },
+
// Image loaded, display elements of play game
initCanvas: function() {
this.ctx = this.$.canvas.node.getContext('2d');
diff --git a/html/index.html b/html/index.html
index f03924a..b6ea126 100644
--- a/html/index.html
+++ b/html/index.html
@@ -11,6 +11,7 @@
<div id="body"></div>
<script src="depends.js" type="text/javascript"></script>
<script type="text/javascript">
+
// Ready to receive Python message
FoodChain.sugar.sendMessage("ready");
diff --git a/html/learngame.js b/html/learngame.js
index 206b53b..46ec867 100644
--- a/html/learngame.js
+++ b/html/learngame.js
@@ -56,12 +56,26 @@ enyo.kind({
this.cardlist = null;
this.nextaction = 0;
this.createComponent({ name: "timer", kind: "Timer", paused: true, onTriggered: "updateTimer" }, {owner: this});
- this.$.textlevel.setContent(__$FC("level"));
- this.$.textscore.setContent(__$FC("score"));
+ this.setLocale();
this.$.score.setContent(String("0000"+FoodChain.context.score).slice(-4));
this.levelChanged();
},
+ // Localization changed, update cards and string resource
+ setLocale: function() {
+ // Update string resources
+ this.$.textlevel.setContent(__$FC("level"));
+ this.$.textscore.setContent(__$FC("score"));
+ this.$.herbname.setContent(__$FC(FoodChain.feedStrategy[0].name));
+ this.$.carnname.setContent(__$FC(FoodChain.feedStrategy[1].name));
+ this.$.omniname.setContent(__$FC(FoodChain.feedStrategy[2].name));
+
+ // Update cards
+ enyo.forEach(this.$.startbox.getControls(), function(card) {
+ card.setLocale();
+ });
+ },
+
// Level changed, init board then start game
levelChanged: function() {
@@ -77,10 +91,7 @@ enyo.kind({
FoodChain.addRemoveClass(this.$.carnbox, "carn-box-three", "carn-box-two");
FoodChain.addRemoveClass(this.$.omnibox, "omni-box-three", "omni-box-two");
this.$.omnibox.show();
- }
- this.$.herbname.setContent(__$FC(FoodChain.feedStrategy[0].name));
- this.$.carnname.setContent(__$FC(FoodChain.feedStrategy[1].name));
- this.$.omniname.setContent(__$FC(FoodChain.feedStrategy[2].name));
+ }
this.dragobject = null;
this.selectedobject = null;
diff --git a/html/playgame.js b/html/playgame.js
index 87cc45e..332594f 100644
--- a/html/playgame.js
+++ b/html/playgame.js
@@ -102,12 +102,18 @@ enyo.kind({
this.nextaction = 0;
this.createComponent({ name: "timer", kind: "Timer", paused: true, onTriggered: "updateTimer" }, {owner: this});
this.createComponent({ name: "timerMonster", kind: "Timer", baseInterval: 500, onTriggered: "monsterEngine" }, {owner: this});
- this.$.textlevel.setContent(__$FC("level"));
- this.$.textscore.setContent(__$FC("score"));
+ this.setLocale();
this.$.score.setContent(String("0000"+FoodChain.context.score).slice(-4));
this.levelChanged();
},
+ // Localization changed, update cards and string resource
+ setLocale: function() {
+ // Update string resources
+ this.$.textlevel.setContent(__$FC("level"));
+ this.$.textscore.setContent(__$FC("score"));
+ },
+
// Level changed, init board then start game
levelChanged: function() {
diff --git a/html/util.js b/html/util.js
index 12f7a24..9347115 100644
--- a/html/util.js
+++ b/html/util.js
@@ -12,7 +12,8 @@ FoodChain = {};
FoodChain.context = {
score: 0,
game: "",
- level: 0
+ level: 0,
+ object: null
};
FoodChain.saveContext = function() {
FoodChain.sugar.sendMessage(
@@ -64,13 +65,19 @@ FoodChain.getConfig = function(name) {
FoodChain.goHome = function() {
if (FoodChain.context.home != null) {
FoodChain.context.game = "";
+ FoodChain.context.home.setLocale()
FoodChain.context.home.renderInto(document.getElementById("body"));
}
};
// Sugar interface
+FoodChain.setLocale = function(dict) {
+ __$FC_l10n_set(dict);
+ if (FoodChain.context.object != null)
+ FoodChain.context.object.setLocale();
+}
FoodChain.sugar = new Sugar();
-FoodChain.sugar.connect("localization", __$FC_l10n_set);
+FoodChain.sugar.connect("localization", FoodChain.setLocale);
FoodChain.sugar.connect("save-context", FoodChain.saveContext);
FoodChain.sugar.connect("load-context", FoodChain.loadContext);
FoodChain.log = function(msg) {
@@ -107,3 +114,12 @@ FoodChain.createWithCondition = function(create, condition, set) {
FoodChain.log("WARNING: out of pre-requisite creating "+newObject.id);
return newObject;
};
+
+// Test if two sound strings matchs ignoring audio directory
+FoodChain.soundMatch = function(s1, s2) {
+ var l1 = s1.length-1;
+ while (l1 > 0 && s1[l1] != '/') l1--;
+ var l2 = s2.length-1;
+ while (l2 > 0 && s2[l2] != '/') l2--;
+ return s1.substring(l1) == s2.substring(l2);
+};
diff --git a/l10n.py b/l10n.py
index 4abbee7..d2fd103 100644
--- a/l10n.py
+++ b/l10n.py
@@ -3,71 +3,114 @@
-from gettext import gettext as _
+from gettext import gettext as igettext
+import gettext
+import os
-_fc_l10n = {
- "sounddir": _("en"),
- "learn": _("Learn"),
- "build": _("Build"),
- "play": _("Play"),
- "learndesc": _("Set cards in the right box to learn what sort of food each animal eat."),
- "builddesc": _("Set cards in the right order to build the right food chain."),
- "playdesc": _("Play the food chain: eat and avoid being eaten."),
- "level": _("Level"),
- "score": _("Score:"),
- "concept": _("concept & code:"),
- "arts": _("arts:"),
- "music": _("music:"),
- "sound": _("sound effects:"),
- "alligator": _("Alligator"),
- "animal": _("Animal"),
- "bat": _("Bat"),
- "bee": _("Bee"),
- "bird": _("Bird"),
- "camel": _("Camel"),
- "cat": _("Cat"),
- "chicken": _("Chicken"),
- "chimp": _("Chimp"),
- "clam": _("Clam"),
- "corn": _("Corn"),
- "cow": _("Cow"),
- "crab": _("Crab"),
- "crocodile": _("Crocodile"),
- "crow": _("Crow"),
- "dog": _("Dog"),
- "duck": _("Duck"),
- "fish": _("Fish"),
- "flies": _("Flies"),
- "fox": _("Fox"),
- "frog": _("Frog"),
- "giraffe": _("Giraffe"),
- "goat": _("Goat"),
- "grass": _("Grass"),
- "hay": _("Hay"),
- "hen": _("Hen"),
- "lamb": _("Lamb"),
- "mice": _("Mice"),
- "mole": _("Mole"),
- "mosquito": _("Mosquito"),
- "mule": _("Mule"),
- "owl": _("Owl"),
- "ox": _("Ox"),
- "pig": _("Pig"),
- "rat": _("Rat"),
- "shark": _("Shark"),
- "shrimp": _("Shrimp"),
- "skunk": _("Skunk"),
- "snail": _("Snail"),
- "snake": _("Snake"),
- "spider": _("Spider"),
- "spike": _("Spike"),
- "squid": _("Squid"),
- "squirrel": _("Squirrel"),
- "starfish": _("Starfish"),
- "swan": _("Swan"),
- "tick": _("Tick"),
- "wheat": _("Wheat"),
- "herbivore": _("Herbivore"),
- "carnivore": _("Carnivore"),
- "omnivore": _("Omnivore")
-} \ No newline at end of file
+
+
+class FoodChainLocalization:
+ "Class for localization, need to allow forcing localization dynamically"
+
+ def __init__(self):
+ "Init strings with default localization"
+ self._ = self.gettext_default
+ self.set_strings()
+ self.lang = None
+
+
+ def set_locale(self, lang):
+ "Force localization"
+ if lang == 'en':
+ self._ = self.gettext_identity
+ self.set_strings()
+ return
+ if lang != 'fr':
+ self._ = self.gettext_default
+ self.set_strings()
+ return
+ self.lang = gettext.translation("org.olpcfrance.FoodChain", localedir=os.path.join(os.getcwd(), 'locale'), languages=[lang])
+ self.lang.install()
+ self._ = self.gettext_lang
+ self.set_strings()
+
+
+ # Gettext function depending of context
+ def gettext_identity(self, s):
+ return s
+
+ def gettext_default(self, s):
+ return igettext(s)
+
+ def gettext_lang(self, s):
+ return self.lang.gettext(s)
+
+
+ def set_strings(self):
+ "Init all strings with the current localization (default or specific)"
+ self.strings = {
+ "sounddir": self._("en"),
+ "learn": self._("Learn"),
+ "build": self._("Build"),
+ "play": self._("Play"),
+ "learndesc": self._("Set cards in the right box to learn what sort of food each animal eat."),
+ "builddesc": self._("Set cards in the right order to build the right food chain."),
+ "playdesc": self._("Play the food chain: eat and avoid being eaten."),
+ "level": self._("Level"),
+ "score": self._("Score:"),
+ "concept": self._("concept & code:"),
+ "arts": self._("arts:"),
+ "music": self._("music:"),
+ "sound": self._("sound effects:"),
+ "alligator": self._("Alligator"),
+ "animal": self._("Animal"),
+ "bat": self._("Bat"),
+ "bee": self._("Bee"),
+ "bird": self._("Bird"),
+ "camel": self._("Camel"),
+ "cat": self._("Cat"),
+ "chicken": self._("Chicken"),
+ "chimp": self._("Chimp"),
+ "clam": self._("Clam"),
+ "corn": self._("Corn"),
+ "cow": self._("Cow"),
+ "crab": self._("Crab"),
+ "crocodile": self._("Crocodile"),
+ "crow": self._("Crow"),
+ "dog": self._("Dog"),
+ "duck": self._("Duck"),
+ "fish": self._("Fish"),
+ "flies": self._("Flies"),
+ "fox": self._("Fox"),
+ "frog": self._("Frog"),
+ "giraffe": self._("Giraffe"),
+ "goat": self._("Goat"),
+ "grass": self._("Grass"),
+ "hay": self._("Hay"),
+ "hen": self._("Hen"),
+ "lamb": self._("Lamb"),
+ "mice": self._("Mice"),
+ "mole": self._("Mole"),
+ "mosquito": self._("Mosquito"),
+ "mule": self._("Mule"),
+ "owl": self._("Owl"),
+ "ox": self._("Ox"),
+ "pig": self._("Pig"),
+ "rat": self._("Rat"),
+ "shark": self._("Shark"),
+ "shrimp": self._("Shrimp"),
+ "skunk": self._("Skunk"),
+ "snail": self._("Snail"),
+ "snake": self._("Snake"),
+ "spider": self._("Spider"),
+ "spike": self._("Spike"),
+ "squid": self._("Squid"),
+ "squirrel": self._("Squirrel"),
+ "starfish": self._("Starfish"),
+ "swan": self._("Swan"),
+ "tick": self._("Tick"),
+ "wheat": self._("Wheat"),
+ "herbivore": self._("Herbivore"),
+ "carnivore": self._("Carnivore"),
+ "omnivore": self._("Omnivore")
+ }