i18n-js 4.0.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module I18nJS
4
+ class CLI
5
+ class PluginsCommand < Command
6
+ command_name "plugins"
7
+ description "List plugins that will be activated"
8
+
9
+ parse do |opts|
10
+ opts.banner = "Usage: i18n #{name} [options]"
11
+
12
+ opts.on(
13
+ "-rREQUIRE_FILE",
14
+ "--require=REQUIRE_FILE",
15
+ "A Ruby file that must be loaded"
16
+ ) do |require_file|
17
+ options[:require_file] = require_file
18
+ end
19
+
20
+ opts.on("-h", "--help", "Prints this help") do
21
+ ui.exit_with opts.to_s
22
+ end
23
+ end
24
+
25
+ command do
26
+ set_defaults!
27
+ ui.colored = options[:colored]
28
+
29
+ if options[:require_file]
30
+ ui.stdout_print("=> Require file:", options[:require_file].inspect)
31
+ require_file = File.expand_path(options[:require_file])
32
+ end
33
+
34
+ if require_file && !File.file?(require_file)
35
+ ui.fail_with(
36
+ "=> ERROR: require file doesn't exist at",
37
+ require_file.inspect
38
+ )
39
+ end
40
+
41
+ load_require_file!(require_file) if require_file
42
+
43
+ files = I18nJS.plugin_files
44
+
45
+ if files.empty?
46
+ ui.stdout_print("=> No plugins have been detected.")
47
+ else
48
+ ui.stdout_print("=> Plugins that will be activated:")
49
+
50
+ files.each do |file|
51
+ file = file.gsub("#{Dir.home}/", "~/")
52
+
53
+ ui.stdout_print(" * #{file}")
54
+ end
55
+ end
56
+ end
57
+
58
+ private def set_defaults!
59
+ config_file = "./config/i18n.yml"
60
+ require_file = "./config/environment.rb"
61
+
62
+ options[:config_file] ||= config_file if File.file?(config_file)
63
+ options[:require_file] ||= require_file if File.file?(require_file)
64
+ end
65
+ end
66
+ end
67
+ end
data/lib/i18n-js/cli.rb CHANGED
@@ -6,6 +6,9 @@ require_relative "cli/ui"
6
6
  require_relative "cli/init_command"
7
7
  require_relative "cli/version_command"
8
8
  require_relative "cli/export_command"
9
+ require_relative "cli/plugins_command"
10
+ require_relative "cli/lint_translations_command"
11
+ require_relative "cli/lint_scripts_command"
9
12
  require_relative "cli/check_command"
10
13
 
11
14
  module I18nJS
@@ -27,7 +30,15 @@ module I18nJS
27
30
  end
28
31
 
29
32
  private def command_classes
30
- [InitCommand, ExportCommand, VersionCommand, CheckCommand]
33
+ [
34
+ InitCommand,
35
+ ExportCommand,
36
+ VersionCommand,
37
+ PluginsCommand,
38
+ LintTranslationsCommand,
39
+ LintScriptsCommand,
40
+ CheckCommand
41
+ ]
31
42
  end
32
43
 
33
44
  private def commands
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module I18nJS
4
+ require "i18n-js/plugin"
5
+
6
+ class EmbedFallbackTranslationsPlugin < I18nJS::Plugin
7
+ CONFIG_KEY = :embed_fallback_translations
8
+
9
+ # This method must set up the basic plugin configuration, like adding the
10
+ # config's root key in case your plugin accepts configuration (defined via
11
+ # the config file).
12
+ #
13
+ # If you don't add this key, the linter will prevent non-default keys from
14
+ # being added to the configuration file.
15
+ def self.setup
16
+ I18nJS::Schema.root_keys << CONFIG_KEY
17
+ end
18
+
19
+ # In case your plugin accepts configuration, this is where you must validate
20
+ # the configuration, making sure only valid keys and type is provided.
21
+ # If the configuration contains invalid data, then you must raise an
22
+ # exception using something like
23
+ # `raise I18nJS::Schema::InvalidError, error_message`.
24
+ def self.validate_schema(config:)
25
+ return unless config.key?(CONFIG_KEY)
26
+
27
+ plugin_config = config[CONFIG_KEY]
28
+ valid_keys = %i[enabled]
29
+ schema = I18nJS::Schema.new(config)
30
+
31
+ schema.expect_required_keys(valid_keys, plugin_config)
32
+ schema.reject_extraneous_keys(valid_keys, plugin_config)
33
+ schema.expect_enabled_config(CONFIG_KEY, plugin_config[:enabled])
34
+ end
35
+
36
+ # This method is responsible for transforming the translations. The
37
+ # translations you'll receive may be already be filtered by other plugins
38
+ # and by the default filtering itself. If you need to access the original
39
+ # translations, use `I18nJS.translations`.
40
+ #
41
+ # Make sure you always check whether your plugin is active before
42
+ # transforming translations; otherwise, opting out transformation won't be
43
+ # possible.
44
+ def self.transform(translations:, config:)
45
+ return translations unless config.dig(CONFIG_KEY, :enabled)
46
+
47
+ translations_glob = Glob.new(translations)
48
+ translations_glob << "*"
49
+
50
+ mapping = translations.keys.each_with_object({}) do |locale, buffer|
51
+ buffer[locale] = Glob.new(translations[locale]).tap do |glob|
52
+ glob << "*"
53
+ end
54
+ end
55
+
56
+ default_locale = I18n.default_locale
57
+ default_locale_glob = mapping.delete(default_locale)
58
+ default_locale_paths = default_locale_glob.paths
59
+
60
+ mapping.each do |locale, glob|
61
+ missing_keys = default_locale_paths - glob.paths
62
+
63
+ missing_keys.each do |key|
64
+ components = key.split(".").map(&:to_sym)
65
+ fallback_translation = translations.dig(default_locale, *components)
66
+
67
+ next unless fallback_translation
68
+
69
+ translations_glob.set([locale, key].join("."), fallback_translation)
70
+ end
71
+ end
72
+
73
+ translations_glob.to_h
74
+ end
75
+ end
76
+
77
+ I18nJS.register_plugin(EmbedFallbackTranslationsPlugin)
78
+ end