Merge pull request #2193 from opf/feature/webpack-i18n-support

Support plugins extending Webpack build pipeline; Build translations from openproject-translations
pull/2257/head
ulferts 10 years ago
commit b5e3d73b85
  1. 2
      .gitignore
  2. 2
      Gemfile
  3. 3
      Gemfile.lock
  4. 4
      app/assets/javascripts/application.js.erb
  5. 54
      bin/plugin_info
  6. 64
      config/initializers/i18n-js.rb
  7. 72
      config/rails-plugins.conf.js
  8. 93
      doc/DEVELOP_PLUGINS.md
  9. 0
      frontend/app/api/hal-api-resource.js
  10. 0
      frontend/app/api/index.js
  11. 0
      frontend/app/config/configuration-service.js
  12. 0
      frontend/app/helpers/auto-complete-helper.js
  13. 0
      frontend/app/helpers/custom-field-helper.js
  14. 0
      frontend/app/helpers/index.js
  15. 0
      frontend/app/helpers/path-helper.js
  16. 0
      frontend/app/helpers/svg-helper.js
  17. 0
      frontend/app/helpers/url-params-helper.js
  18. 0
      frontend/app/helpers/work-package-loading-helper.js
  19. 0
      frontend/app/layout/controllers/index.js
  20. 0
      frontend/app/layout/controllers/main-menu-controller.js
  21. 0
      frontend/app/layout/index.js
  22. 0
      frontend/app/layout/menu-item-factory.js
  23. 0
      frontend/app/layout/query-menu-item-factory.js
  24. 0
      frontend/app/messages/controllers/index.js
  25. 0
      frontend/app/messages/controllers/messages-controller.js
  26. 0
      frontend/app/messages/index.js
  27. 0
      frontend/app/models/filter.js
  28. 0
      frontend/app/models/index.js
  29. 0
      frontend/app/models/query.js
  30. 0
      frontend/app/models/sortation.js
  31. 12
      frontend/app/openproject-app.js
  32. 0
      frontend/app/routing.js
  33. 0
      frontend/app/services/activity-service.js
  34. 0
      frontend/app/services/authorisation-service.js
  35. 0
      frontend/app/services/group-service.js
  36. 0
      frontend/app/services/hook-service.js
  37. 0
      frontend/app/services/index.js
  38. 0
      frontend/app/services/pagination-service.js
  39. 0
      frontend/app/services/priority-service.js
  40. 0
      frontend/app/services/project-service.js
  41. 0
      frontend/app/services/query-service.js
  42. 0
      frontend/app/services/role-service.js
  43. 0
      frontend/app/services/sort-service.js
  44. 0
      frontend/app/services/status-service.js
  45. 0
      frontend/app/services/textile-service.js
  46. 0
      frontend/app/services/timezone-service.js
  47. 0
      frontend/app/services/type-service.js
  48. 0
      frontend/app/services/user-service.js
  49. 0
      frontend/app/services/version-service.js
  50. 0
      frontend/app/services/work-package-service.js
  51. 0
      frontend/app/time_entries/controllers/index.js
  52. 0
      frontend/app/time_entries/controllers/time-entries-controller.js
  53. 0
      frontend/app/time_entries/index.js
  54. 0
      frontend/app/timelines/controllers/index.js
  55. 0
      frontend/app/timelines/controllers/timeline-selection-controller.js
  56. 0
      frontend/app/timelines/controllers/timelines-controller.js
  57. 0
      frontend/app/timelines/directives/index.js
  58. 0
      frontend/app/timelines/directives/timeline-column-data-directive.js
  59. 0
      frontend/app/timelines/directives/timeline-column-name-directive.js
  60. 0
      frontend/app/timelines/directives/timeline-container-directive.js
  61. 0
      frontend/app/timelines/directives/timeline-grouping-label-directive.js
  62. 0
      frontend/app/timelines/directives/timeline-table-container-directive.js
  63. 0
      frontend/app/timelines/directives/timeline-table-directive.js
  64. 0
      frontend/app/timelines/directives/timeline-table-row-directive.js
  65. 0
      frontend/app/timelines/directives/timeline-toolbar-directive.js
  66. 0
      frontend/app/timelines/helpers/filter-query-string-builder.js
  67. 0
      frontend/app/timelines/helpers/index.js
  68. 0
      frontend/app/timelines/helpers/timeline-table-helper.js
  69. 0
      frontend/app/timelines/index.js
  70. 0
      frontend/app/timelines/models/color.js
  71. 0
      frontend/app/timelines/models/custom-field.js
  72. 0
      frontend/app/timelines/models/historical-planning-element.js
  73. 0
      frontend/app/timelines/models/index.js
  74. 0
      frontend/app/timelines/models/mixins/constants.js
  75. 0
      frontend/app/timelines/models/mixins/ui.js
  76. 0
      frontend/app/timelines/models/planning-element-type.js
  77. 0
      frontend/app/timelines/models/planning-element.js
  78. 0
      frontend/app/timelines/models/project-association.js
  79. 0
      frontend/app/timelines/models/project-type.js
  80. 0
      frontend/app/timelines/models/project.js
  81. 0
      frontend/app/timelines/models/reporting.js
  82. 0
      frontend/app/timelines/models/status.js
  83. 0
      frontend/app/timelines/models/timeline.js
  84. 0
      frontend/app/timelines/models/tree-node.js
  85. 0
      frontend/app/timelines/models/user.js
  86. 0
      frontend/app/timelines/services/index.js
  87. 0
      frontend/app/timelines/services/timeline-loader-service.js
  88. 0
      frontend/app/ui_components/accessible-by-keyboard-directive.js
  89. 0
      frontend/app/ui_components/accessible-checkbox-directive.js
  90. 0
      frontend/app/ui_components/accessible-element-directive.js
  91. 0
      frontend/app/ui_components/activity-comment-directive.js
  92. 0
      frontend/app/ui_components/authoring-directive.js
  93. 0
      frontend/app/ui_components/back-url-directive.js
  94. 0
      frontend/app/ui_components/date/date-directive.js
  95. 0
      frontend/app/ui_components/date/date-time-directive.js
  96. 0
      frontend/app/ui_components/date/time-directive.js
  97. 0
      frontend/app/ui_components/dropdown-directive.js
  98. 0
      frontend/app/ui_components/empty-element-directive.js
  99. 0
      frontend/app/ui_components/execute-on-enter-directive.js
  100. 0
      frontend/app/ui_components/filters/ancestors-expanded-filter.js
  101. Some files were not shown because too many files have changed in this diff Show More

2
.gitignore vendored

@ -42,7 +42,7 @@
/backup
/.project
/.loadpath
/app/assets/javascripts/openproject-app.bundle.js*
/app/assets/javascripts/bundles/*.js*
/config/additional_environment.rb
/config/configuration.yml
/config/database.yml

@ -105,8 +105,6 @@ gem "prototype-rails"
# replace those with :remote => true
gem 'prototype_legacy_helper', '0.0.0', :git => 'https://github.com/rails/prototype_legacy_helper.git'
gem 'i18n-js', '~> 3.0.0.rc6'
# small wrapper around the command line
gem 'cocaine'

@ -192,8 +192,6 @@ GEM
hooks (0.3.3)
htmldiff (0.0.1)
i18n (0.6.11)
i18n-js (3.0.0.rc6)
i18n (~> 0.6)
ice_nine (0.11.0)
interception (0.3)
iso8601 (0.8.2)
@ -439,7 +437,6 @@ DEPENDENCIES
gravatar_image_tag (~> 1.2.0)
htmldiff
i18n (>= 0.6.8)
i18n-js (~> 3.0.0.rc6)
jruby-openssl
json_spec
launchy (~> 2.3.0)

@ -29,7 +29,6 @@
//= require effects
//= require dragdrop
//= require controls
//= require i18n/translations
//= require lib/jquery.colorcontrast
//= require lib/jquery.trap
@ -55,7 +54,8 @@
//= require versions
//= require_tree ./specific
//= require ./openproject-app.bundle
//= require ./bundles/openproject-app
//= require_tree ./bundles
//source: http://stackoverflow.com/questions/8120065/jquery-and-prototype-dont-work-together-with-array-prototype-reverse
if (typeof []._reverse == 'undefined') {

@ -1,3 +1,5 @@
#!/usr/bin/env ruby
#
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2014 the OpenProject Foundation (OPF)
@ -26,25 +28,33 @@
# See doc/COPYRIGHT.rdoc for more details.
#++
# Only export keys within the js scope, supporting two levels of nesting,
# e.g.:
#
# en:
# js:
# error_message: An error occurred.
# my_plugin_name:
# js:
# welcome_text: Welcome back.
# user:
# js:
# project_name: Project name:
# admin:
# js:
# delete_project: Delete Project!
#
translations:
- file: "public/javascripts/i18n/translations.js"
only:
- '*.js'
- '*.*.js'
- '*.*.*.js'
require 'bundler'
require 'json'
DEFAULT_GROUPS = [:opf_plugins]
DEFAULT_GEMFILE = File.expand_path('../../Gemfile', __FILE__)
def plugin_names(gemfile = DEFAULT_GEMFILE)
bundler_groups = ENV['BUNDLER_GROUPS']
groups = bundler_groups.split(',').each_with_object([]) { |group, l| l << group.to_sym } if bundler_groups
groups = DEFAULT_GROUPS if groups.nil?
gems = Bundler::Dsl.evaluate(gemfile, 'foo', true)
gems.dependencies.each_with_object({}) do |dep, l|
l[dep.name] = dep.inspect if (groups & dep.groups).any?
end
end
def plugin_name_paths
op_dep = plugin_names
Bundler.load.specs.each_with_object({}) do |spec, h|
if op_dep.include?(spec.name)
options = spec.source.options
h[spec.name] = spec.full_gem_path
end
end
end
puts JSON.generate(plugin_name_paths)

@ -1,64 +0,0 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2014 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# 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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See doc/COPYRIGHT.rdoc for more details.
#++
# Note: This monkey patch was written to enable configurations like:
#
# only:
# - '*.js'
# - '*.*.js'
# - '*.*.*.js'
#
# in combination with unevenly nested translations, i.e.
# en:
# foo: Foo
# js:
# foo: Foo
# bar:
# baz: Baz
#
# NB: On some levels, there are String _and_ Hash values.
#
# The original code only expected to see Hashes, while in the above setup, there
# might be other values as well. These may be ignored by `filter`, since these
# values will not contain the relevant translations.
#
# At the moment, we are not posting a pull request including the changes to the
# original author, since s/he is working on a rewrite of i18n-js and s/he does
# not seem to accept even the simplest pull request. We should try again, when
# the `rewrite` branch of i18n-js is released to master.
#
# Written against i18n-js rewrite branch
I18n::JS.module_eval do
class << self
def filter_with_uneven_nesting_fix(translations, scopes)
filter_without_uneven_nesting_fix(translations, scopes) if translations.is_a? Hash
end
alias_method_chain :filter, :uneven_nesting_fix
end
end

@ -0,0 +1,72 @@
//-- copyright
// OpenProject is a project management system.
// Copyright (C) 2012-2014 the OpenProject Foundation (OPF)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 3.
//
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
// Copyright (C) 2006-2013 Jean-Philippe Lang
// Copyright (C) 2010-2013 the ChiliProject Team
//
// 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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See doc/COPYRIGHT.rdoc for more details.
//++
/*global exec */
/*global test */
require('shelljs/global');
var path = require('path'),
_ = require('lodash');
var PLUGIN_INFO_CMD_PATH = path.join(__dirname, '..', 'bin', 'plugin_info');
function runPluginsInfo() {
var fullCmd = exec(PLUGIN_INFO_CMD_PATH, { silent: true });
return fullCmd.code === 0 ? fullCmd.output : '{}';
}
var OpenProjectPlugins = {
allPluginNamesPaths: _.memoize(function() {
return JSON.parse(runPluginsInfo());
}),
pluginNamesPaths: function() {
return _.reduce(this.allPluginNamesPaths(), function(obj, pluginPath, pluginName) {
if (test('-e', path.join(pluginPath, 'package.json'))) {
obj[pluginName] = pluginPath;
} else {
console.info('INFO: plugin "%s" does not provide a package.json', pluginName);
}
return obj;
}, {});
},
findPluginPath: _.memoize(function(name) {
return this.pluginNamesPaths()[name];
}, _.identity),
pluginDirectories: function() {
return _.reduce(this.allPluginNamesPaths(), function(dirList, pluginPath) {
var pluginDir = path.dirname(pluginPath);
return dirList.indexOf(pluginDir) === -1 ? dirList.concat(pluginDir) : dirList;
}, []);
}
};
exports.pluginNamesPaths = OpenProjectPlugins.pluginNamesPaths();
exports.pluginDirectories = OpenProjectPlugins.pluginDirectories();

@ -0,0 +1,93 @@
<!---- copyright
OpenProject is a project management system.
Copyright (C) 2012-2014 the OpenProject Foundation (OPF)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License version 3.
OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
Copyright (C) 2006-2013 Jean-Philippe Lang
Copyright (C) 2010-2013 the ChiliProject Team
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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
See doc/COPYRIGHT.rdoc for more details.
++-->
# Developing OpenProject Plugins
The core functionality of OpenProject may be extended through the use of plugins.
## Rails/backend plugins
Plugins that extend the Rails application are packaged as **Ruby gems**.
These plugins must contain a `Gem::Specification` (typically as a `.gemspec`
file in the root directory of the plugin).
**To use a Rails plugin**
* declare the dependency in `Gemfile.plugins` within the `:opf_plugins` group
using the Bundler DSL.
Example:
```ruby
group :opf_plugins do
gem :openproject_costs, git: 'https://github.com/finnlabs/openproject-backlogs.git', branch: 'dev'
end
```
* run `bundle install`.
## Frontend plugins [WIP]
Plugins that extend the frontend application may be packaged as **npm modules**.
These plugins must contain a `package.json` in the root directory of the plugin.
Plugins are responsible for loading their own assets, including additional
images, styles and I18n translations.
To load translation strings use the provided `I18n.addTranslation` function:
```js
I18n.addTranslations('en', require('../../config/locales/js-en.yml').en);
```
Pure frontend plugins should be considered _a work in progress_. As such, it is
currently recommended to create hybrid plugins (see below).
**To use a frontend plugin:**
* You will currently need to modify the `package.json` of OpenProject core
directly. A more robust solution is currently in planning.
## Hybrid plugins
Plugins that extend both the Rails and frontend applications are possible. They
must contain both a `Gem::Specification` and `package.json`.
_CAVEAT: npm dependencies for hybrid plugins are not yet resolved._
**To use a hybrid plugin:**
* declare the dependency in `Gemfile.plugins` within the `:opf_plugins` group
using the Bundler DSL.
* then run `bundle install`.
You **do not** need to modify the `package.json` of OpenProject core. Provided
Ruby Bundler is aware of these plugins, Webpack (our node-based build pipeline)
will bundle their assets.

@ -27,9 +27,15 @@
//++
var I18n = require('./vendor/i18n');
window.I18n = I18n;
I18n.translations.de = require("json!yaml!./../../../../config/locales/js-de.yml").de;
I18n.translations.en = require("json!yaml!./../../../../config/locales/js-en.yml").en;
// standard locales
I18n.translations.en = require("locales/js-en.yml").en;
I18n.translations.de = require("locales/js-de.yml").de;
I18n.addTranslations = function(locale, translations) {
I18n.translations[locale] = _.merge(I18n.translations[locale], translations);
};
var angular = require('angular');
require('angular-animate');

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save