Browse Source

Add i18n support for plugins

Peter Justin 7 years ago
parent
commit
d120c9a2a4
5 changed files with 43 additions and 55 deletions
  1. 18 12
      flaskbb/app.py
  2. 1 1
      flaskbb/cli/utils.py
  3. 4 0
      flaskbb/plugins/manager.py
  4. 5 0
      flaskbb/plugins/spec.py
  5. 15 42
      flaskbb/utils/translations.py

+ 18 - 12
flaskbb/app.py

@@ -77,6 +77,7 @@ def create_app(config=None):
     configure_context_processors(app)
     configure_before_handlers(app)
     configure_errorhandlers(app)
+    configure_translations(app)
     configure_logging(app)
     app.pluggy.hook.flaskbb_additional_setup(app=app, pluggy=app.pluggy)
 
@@ -196,18 +197,6 @@ def configure_extensions(app):
 
     login_manager.init_app(app)
 
-    # Flask-BabelEx
-    babel.init_app(app=app, default_domain=FlaskBBDomain(app))
-
-    @babel.localeselector
-    def get_locale():
-        # if a user is logged in, use the locale from the user settings
-        if current_user and \
-                current_user.is_authenticated and current_user.language:
-            return current_user.language
-        # otherwise we will just fallback to the default language
-        return flaskbb_config["DEFAULT_LANGUAGE"]
-
     # Flask-Allows
     allows.init_app(app)
     allows.identity_loader(lambda: current_user)
@@ -304,6 +293,23 @@ def configure_errorhandlers(app):
     app.pluggy.hook.flaskbb_errorhandlers(app=app)
 
 
+def configure_translations(app):
+    """Configure translations."""
+
+    # we have to initialize the extension after we have loaded the plugins
+    # because we of the 'flaskbb_load_translations' hook
+    babel.init_app(app=app, default_domain=FlaskBBDomain(app))
+
+    @babel.localeselector
+    def get_locale():
+        # if a user is logged in, use the locale from the user settings
+        if current_user and \
+                current_user.is_authenticated and current_user.language:
+            return current_user.language
+        # otherwise we will just fallback to the default language
+        return flaskbb_config["DEFAULT_LANGUAGE"]
+
+
 def configure_logging(app):
     """Configures logging."""
 

+ 1 - 1
flaskbb/cli/utils.py

@@ -74,7 +74,7 @@ def validate_plugin(plugin):
           the appcontext can't be found and using with_appcontext doesn't
           help either.
     """
-    if plugin not in current_app.pluggy.get_plugins():
+    if plugin not in current_app.pluggy.list_name():
         raise FlaskBBCLIError("Plugin {} not found.".format(plugin), fg="red")
     return True
 

+ 4 - 0
flaskbb/plugins/manager.py

@@ -55,6 +55,10 @@ class FlaskBBPluginManager(pluggy.PluginManager):
         """Returns the metadata for a given name."""
         return self._plugin_metadata.get(name)
 
+    def list_name(self):
+        """Returns only the enabled plugin names."""
+        return list(self._name2plugin.keys())
+
     def list_plugin_metadata(self):
         """Returns the metadata for all plugins"""
         return self._plugin_metadata

+ 5 - 0
flaskbb/plugins/spec.py

@@ -22,6 +22,11 @@ def flaskbb_extensions(app):
 
 
 @spec
+def flaskbb_load_translations():
+    """
+    Hook for registering translation folders.
+    """
+@spec
 def flaskbb_load_blueprints(app):
     """
     Hook for registering blueprints

+ 15 - 42
flaskbb/utils/translations.py

@@ -22,22 +22,11 @@ class FlaskBBDomain(Domain):
         self.app = app
         super(FlaskBBDomain, self).__init__()
 
-        self.plugins_folder = os.path.join(
-            os.path.join(self.app.root_path, "plugins")
-        )
-
-        # FlaskBB's translations
-        self.flaskbb_translations = os.path.join(
-            self.app.root_path, "translations"
-        )
-
         # Plugin translations
         with self.app.app_context():
-            self.plugin_translations = [
-                os.path.join(plugin.path, "translations")
-                for plugin in self.app.pluggy.get_plugins()
-                if os.path.exists(os.path.join(plugin.path, "translations"))
-            ]
+            self.plugin_translations = \
+                self.app.pluggy.hook.flaskbb_load_translations()
+            print(self.plugin_translations)
 
     def get_translations(self):
         """Returns the correct gettext translations that should be used for
@@ -45,34 +34,18 @@ class FlaskBBDomain(Domain):
         object if used outside of the request or if a translation cannot be
         found.
         """
+        translations = super(FlaskBBDomain, self).get_translations()
         locale = get_locale()
-        cache = self.get_translations_cache()
-
-        translations = cache.get(str(locale))
-        if translations is None:
-            # load flaskbb translations
-            translations = babel.support.Translations.load(
-                dirname=self.flaskbb_translations,
+        # now load and add the plugin translations
+        for plugin in self.plugin_translations:
+            plugin_translation = babel.support.Translations.load(
+                dirname=plugin,
                 locales=locale,
                 domain="messages"
             )
+            translations.add(plugin_translation)
 
-            # If no compiled translations are found, return the
-            # NullTranslations object.
-            if not isinstance(translations, babel.support.Translations):
-                return translations
-
-            # now load and add the plugin translations
-            for plugin in self.plugin_translations:
-                plugin_translation = babel.support.Translations.load(
-                    dirname=plugin,
-                    locales=locale,
-                    domain="messages"
-                )
-                translations.add(plugin_translation)
-
-            cache[str(locale)] = translations
-
+        self.cache[str(locale)] = translations
         return translations
 
 
@@ -91,7 +64,7 @@ def update_translations(include_plugins=False):
                      "-d", translations_folder])
 
     if include_plugins:
-        for plugin in current_app.pluggy.get_plugins():
+        for plugin in current_app.pluggy.list_name():
             update_plugin_translations(plugin)
 
 
@@ -120,7 +93,7 @@ def compile_translations(include_plugins=False):
     subprocess.call(["pybabel", "compile", "-d", translations_folder])
 
     if include_plugins:
-        for plugin in plugin_manager.all_plugins:
+        for plugin in current_app.pluggy.list_name():
             compile_plugin_translations(plugin)
 
 
@@ -131,7 +104,7 @@ def add_plugin_translations(plugin, translation):
     :param translation: The short name of the translation
                         like ``en`` or ``de_AT``.
     """
-    plugin_folder = os.path.join(current_app.config["PLUGINS_FOLDER"], plugin)
+    plugin_folder = current_app.pluggy.get_plugin(plugin).__path__[0]
     translations_folder = os.path.join(plugin_folder, "translations")
     source_file = os.path.join(translations_folder, "messages.pot")
 
@@ -148,7 +121,7 @@ def update_plugin_translations(plugin):
 
     :param plugin: The plugins identifier
     """
-    plugin_folder = os.path.join(current_app.config["PLUGINS_FOLDER"], plugin)
+    plugin_folder = current_app.pluggy.get_plugin(plugin).__path__[0]
     translations_folder = os.path.join(plugin_folder, "translations")
     source_file = os.path.join(translations_folder, "messages.pot")
 
@@ -168,7 +141,7 @@ def compile_plugin_translations(plugin):
 
     :param plugin: The plugins identifier
     """
-    plugin_folder = os.path.join(current_app.config["PLUGINS_FOLDER"], plugin)
+    plugin_folder = current_app.pluggy.get_plugin(plugin).__path__[0]
     translations_folder = os.path.join(plugin_folder, "translations")
 
     if not os.path.exists(translations_folder):