From d9eb3274aaa6e1395c86c4dfaa488e493969857b Mon Sep 17 00:00:00 2001 From: mike Date: Mon, 30 Nov 2009 16:51:15 +0000 Subject: LP 448319 : Translation layer tests and automatic generation of pot file (ongoing) --- (limited to 'tutorius') diff --git a/tutorius/localization.py b/tutorius/localization.py new file mode 100644 index 0000000..864d20a --- /dev/null +++ b/tutorius/localization.py @@ -0,0 +1,68 @@ +# Copyright (C) 2009, Tutorius.org +# Copyright (C) 2009, Michael Janelle-Montcalm +# +# 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 + +class LocalizationHelper(object): + + @classmethod + def _write_addon_strings_to_file(cls, addon, output_file): + """ + For a given addon, writes a pot file entry for every string property + it has. + + @param addon The addon from which we want to get the string properties + @param output_file The file in which we should write the strings + @return None + """ + for (prop_name, prop_value) in addon._props.items(): + prop_type = getattr(type(addon), prop_name).type + if prop_type == "string": + prop_value = prop_value.replace("\n", "\\n") + prop_value = prop_value.replace("\r", "\\r") + output_file.write('msgid "%s"\nmsgstr ""\n\n'%(prop_value)) + + @classmethod + def write_translation_file(cls, tutorial, output_file): + """ + Writes the translation file to the given file, according to the .pot + files specifications, for the given tutorial. + + This will generate a pair of line for each TStringProperty in the following + format : + msgid "" + msgstr "" + + This will enable the translator to create a localization for this tutorial. + + @param tutorial The executable reprensentation of the + @param output_file An opened file object to which the strings translation + template will be written + @return Nothing + """ + state_dict = tutorial.get_state_dict() + + for state_name in state_dict.keys(): + actions = tutorial.get_action_dict(state_name) + events = tutorial.get_transition_dict(state_name) + + for action in actions.values(): + cls._write_addon_strings_to_file(action, output_file) + + for (event, next_state) in events.values(): + cls._write_addon_strings_to_file(event, output_file) + diff --git a/tutorius/translator.py b/tutorius/translator.py index bd24f8f..f8a3fd7 100644 --- a/tutorius/translator.py +++ b/tutorius/translator.py @@ -17,6 +17,9 @@ import os import logging import copy as copy_module +import gettext +import os +import locale logger = logging.getLogger("ResourceTranslator") @@ -52,7 +55,47 @@ class ResourceTranslator(object): """ self._probe_manager = probe_manager self._tutorial_id = tutorial_id + + # Pick up the language for the user + langs = [] + language = os.environ.get("LANGUAGE", None) + if language: + langs = language.split(':') + + # Get the default machine language + lc, encoding = locale.getdefaultlocale() + if lc: + langs += [lc] + + l10n_dir = Vault.get_localization_dir(tutorial_id) + logger.debug("ResourceTranslator :: Looking for localization resources for languages %s in folder %s"%(str(langs), l10n_dir)) + if l10n_dir: + try: + trans = gettext.translation('tutorial_text', + l10n_dir, + languages=langs) + self._ = trans.ugettext + except IOError: + self._ = None + else: + self._ = None + def translate_string(self, str_value): + """ + Replaces the TString property by its localized equivalent. + + @param str_value The straing to translate + """ + # If we have a localization folder + if self._: + # Apply the translation + u_string = unicode(self._(str_value)) + + # Encode the string in UTF-8 for it to pass thru DBus + return u_string.encode("utf-8") + # There was no translation + return unicode(str_value).encode("utf-8") + def translate_resource(self, res_value): """ Replace the TResourceProperty in the container by their @@ -62,9 +105,9 @@ class ResourceTranslator(object): to transform the resource identifier into the absolute path for the process to be able to use it properly. - @param res_prop The resource property's value to be translated + @param res_value The resource property's value to be translated @return The TFileProperty corresponding to this resource, containing - an absolute path to the resource + an absolute path to it """ # We need to replace the resource by a file representation filepath = Vault.get_resource_path(self._tutorial_id, res_value) @@ -100,6 +143,12 @@ class ResourceTranslator(object): prop_value = getattr(prop_container, propname) prop_type = getattr(type(prop_container), propname).type + # If the propert is a string, we need to use the localization + # to find it's equivalent + if prop_type == "string": + str_value = self.translate_string(prop_value) + prop_container.replace_property(propname, str_value) + # If the property is a resource, then we need to query the # vault to create its correspondent if prop_type == "resource": diff --git a/tutorius/vault.py b/tutorius/vault.py index 1c1e33c..ef985fa 100644 --- a/tutorius/vault.py +++ b/tutorius/vault.py @@ -32,6 +32,7 @@ from ConfigParser import SafeConfigParser from . import addon from .tutorial import Tutorial, State, AutomaticTransitionEvent +from localization import LocalizationHelper logger = logging.getLogger("tutorius") @@ -60,6 +61,7 @@ INI_CATEGORY_PROPERTY = 'category' INI_FILENAME = "meta.ini" TUTORIAL_FILENAME = "tutorial.xml" RESOURCES_FOLDER = 'resources' +LOCALIZATION_FOLDER = 'localization' ###################################################################### # XML Tag names and attributes @@ -352,6 +354,12 @@ class Vault(object): with open(ini_file_path, 'wb') as configfile: parser.write(configfile) + l10n_path = os.path.join(tutorial_path, LOCALIZATION_FOLDER) + os.mkdir(l10n_path) + # Write the localization template (.pot) file + with open(os.path.join(l10n_path, 'tutorial_text.pot'), "wb") as l10n_file: + LocalizationHelper.write_translation_file(tutorial, l10n_file) + else: # Error, tutorial already exist return False @@ -528,6 +536,25 @@ class Vault(object): else: return None + @staticmethod + def get_localization_dir(tutorial_guid): + """ + Returns the base folder under which all the /LC_MESSAGES/tutorial_text.mo + are stored. These files are used for runtime translations by the Resource + Translator. + + @param tutorial_guid the guid of the tutorial + @returns the directory that stores the translation objects + """ + # Get the tutorial path + bundler = TutorialBundler(tutorial_guid) + tutorial_path = bundler.get_tutorial_path(tutorial_guid) + # Check if the localization directory exists + l10n_dir = os.path.join(tutorial_path, LOCALIZATION_FOLDER) + if os.path.isdir(l10n_dir): + return l10n_dir + else: + return None class Serializer(object): """ -- cgit v0.9.1