diff options
author | Lionel LASKE <llaske@c2s.fr> | 2012-12-02 20:30:13 (GMT) |
---|---|---|
committer | Lionel LASKE <llaske@c2s.fr> | 2012-12-02 20:30:13 (GMT) |
commit | d945497aae7c2b6aa8e8c5403d23c852c5b7d7b9 (patch) | |
tree | 8ce958e0f1ab2f79900be55631697af74fefe25c | |
parent | 1a12a4bbc162623abf9ab377d2f44ae8ea1d015a (diff) |
-rw-r--r-- | activity.py | 35 | ||||
-rw-r--r-- | html/app.js | 39 | ||||
-rw-r--r-- | html/buildgame.js | 17 | ||||
-rw-r--r-- | html/card.js | 6 | ||||
-rw-r--r-- | html/credits.js | 18 | ||||
-rw-r--r-- | html/index.html | 1 | ||||
-rw-r--r-- | html/learngame.js | 23 | ||||
-rw-r--r-- | html/playgame.js | 10 | ||||
-rw-r--r-- | html/util.js | 20 | ||||
-rw-r--r-- | l10n.py | 177 |
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); +}; @@ -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") + } |