Search code examples
rubyrubygemsgemspecs

How can I use locales in my gem from another gem?


I have a gem that uses another gem. That other gem has translations (I18n). When localization is applied in my library, instead of text I see a value with a missing translation:

Translation missing: en.some_field.a.b.c

Now there is one solution for me - this is to move the config directory from that library to my own.

But I wouldn't want to copy these files, which are essentially useless for my library. Moreover, these files will have to be maintained, updated, etc.

Is it possible to somehow automatically load these files into the current gem from another?


Solution

  • You can load the translation files of another gem in your current gem without copying the files. It can be done by setting up the I18n load path that will add the paths of translation files from another gem. It is going to look like this:

    Add the following code to your Gem's initializer or configuration file.

    1. In your gem's initializer or configuration file, add the following code:
    # config/initializers/load_translations.rb
    I18n.load_path += YourOtherGem.config.i18n.load_path
    

    To load translations from a gem, follow these steps:

    1. Replace YourOtherGem with the actual name of the gem containing the translations.

    2. Ensure that the translation files are properly configured and accessible within the gem. Normally, you can find the translation files in the config/locales directory of the gem.

    3. Configure the I18n.load_path to include the gem's translation files. You may need to do this in the gem's initializer or configuration file. For instance:

    # lib/your_other_gem/config.rb
    module YourOtherGem
      class Config
        attr_accessor :i18n
    
        def initialize
          @i18n = OpenStruct.new(load_path: [])
          @i18n.load_path << File.expand_path("../../config/locales/*.yml", __FILE__)
        end
      end
    
      def self.config
        @config ||= Config.new
      end
    end
    

    This sets up a configuration object for the gem and adds the translation files from the config/locales directory to the I18n.load_path.

    1. Make sure you add all the required dependencies in your gem's gemspec file. Include this line in your gemspec add_runtime_dependency if another gem will be a runtime dependency.

    # your_gem.gemspec
    Gem::Specification.new do |spec|
      # ...
      spec.add_runtime_dependency "your_other_gem"
      # ...
    end
    

    It allows your gem to load and use the translations of another gem. There is no need to copy translation files from others into your gem.

    Replace YourOtherGem and your_other_gem with the actual names of the gem you are using.

    I had to write a shell script to automate the same thing a few weeks ago.

    #!/bin/bash
    
    # Define the names of your gem and the other gem
    your_gem_initializer="path/to/your/gem/config/initializers/your_gem.rb"
    your_gem_gemspec="path/to/your/gem/your_gem.gemspec"
    other_gem_name="your_other_gem"
    
    # Check if the initializer and gemspec files exist
    if [ ! -f "$your_gem_initializer" ] || [ ! -f "$your_gem_gemspec" ]; then
        echo "Error: Gem files not found."
        exit 1
    fi
    
    # Add translation path to initializer
    echo "Adding translation load path to initializer..."
    echo "I18n.load_path += $other_gem_name.config.i18n.load_path" >> "$your_gem_initializer"
    
    # Add dependency to gemspec
    echo "Adding runtime dependency to gemspec..."
    sed -i "/spec.add_runtime_dependency/a \ \ spec.add_runtime_dependency '$other_gem_name'" "$your_gem_gemspec"
    
    echo "Process completed successfully."