Code Monkey home page Code Monkey logo

rails's Introduction

Translation.io client for Ruby on Rails

Software License Build Status Test Coverage Gem Version Downloads

Add this gem to localize your Ruby on Rails application.

Use the official Rails syntax (with YAML files) or use the GetText syntax.

Write only the source text, and keep it synchronized with your translators on Translation.io.

Translation.io interface

Technical Demo (2.5min)

Need help? [email protected]

Table of contents

Localization syntaxes

I18n (YAML)

The default Rails Internationalization API.

# Regular
t('inbox.title')

# Pluralization
t('inbox.message', count: n)

# Interpolation
t('inbox.hello', name: @user.name)

With the source YAML file:

en:
  inbox:
    title:   'Title to be translated'
    message:
      zero:  'no messages'
      one:   'one message'
      other: '%{count} messages'
    hello:   'Hello %{name}'

You can keep your source YAML file automatically updated using i18n-tasks.

GetText

This gem adds the GetText support to Rails. We strongly suggest that you use GetText to translate your application since it allows an easier and more complete syntax.

Moreover, you won't need to create and manage any YAML file since your code will be automatically scanned for any string to translate.

# Regular
_("Text to be translated")

# Pluralization
n_("Singular text", "Plural text", number)

# Regular with context
p_("context", "Text to be translated")

# Pluralization with context
np_("context", "Singular text", "Plural text", number)

# Interpolations
_('%{city1} is bigger than %{city2}') % { city1: "NYC", city2: "BXL" }

More information about GetText syntax here.

Installation

  1. Add the gem to your project's Gemfile:
gem 'translation'
  1. Create a new translation project from the UI.
  2. Copy the initializer into your Rails app (config/initializers/translation.rb)

The initializer looks like this:

TranslationIO.configure do |config|
  config.api_key        = 'abcdefghijklmnopqrstuvwxyz012345'
  config.source_locale  = 'en'
  config.target_locales = ['fr', 'nl', 'de', 'es']
end
  1. Initialize your project and push existing translations to Translation.io with:
bundle exec rake translation:init

If you need to add or remove languages in the future, please read our documentation about that.

Usage

Sync

To send new translatable keys/strings and get new translations from Translation.io, simply run:

bundle exec rake translation:sync

Sync and Show Purgeable

If you need to find out what are the unused keys/strings from Translation.io, using the current branch as reference:

bundle exec rake translation:sync_and_show_purgeable

As the name says, this operation will also perform a sync at the same time.

Sync and Purge

If you need to remove unused keys/strings from Translation.io, using the current branch as reference:

bundle exec rake translation:sync_and_purge

As the name says, this operation will also perform a sync at the same time.

Warning: all keys that are not present in the current local branch will be permanently deleted from Translation.io.

Manage Languages

Add or Remove Language

You can add or remove a language by updating config.target_locales = [] in your config/initializers/translation.rb file, and executing rake translation:sync.

If you want to add a new language with existing translations (ex. if you already have a translated YAML file in your project), you will need to create a new project on Translation.io and run rake translation:init for them to appear.

Edit Language

To edit existing languages while keeping their translations (e.g. changing from en to en-US).

  1. Create a new project on Translation.io with the correct languages.
  2. Adapt config/initializers/translation.rb (new API key and languages)
  3. Adapt language names and root keys of the YAML files in your project (optional: adapt GetText directories and .po headers)
  4. Execute rake translation:init and check that everything went fine.
  5. Invite your collaborators in the new project.
  6. Remove the old project.

Since you created a new project, the translation history and tags will unfortunately be lost.

Custom Languages

Custom languages are convenient if you want to customize translations for a specific customer or another instance of your application.

A custom language is always be derived from an existing language. Its structure should be like:

"#{existing_language_code}-#{custom_text}"

where custom_text can only contain alphabetic characters and -.

Examples: en-microsoft or fr-BE-custom.

Fallbacks

If a translation is missing for a regional (fr-BE) or custom (fr-microsoft) language, then it will fallback to the main language (fr).

Locale fallbacks will work as expected with both I18n (YAML) and GetText syntaxes.

A good way to leverage this feature is to ignore sentences from a regional language that would have the same translation as the main language (usually most of them). It's way easier to maintain the project over time if only 10% of the regional sentences need to be adapted.

Note that fallbacks are chained, so fr-BE-custom will fallback to fr-BE that will fallback to fr.

Just make sure to add config.i18n.fallbacks = true to your config/application.rb file. You can find more information about this here.

Change the current locale

Globally

The easiest way to change the current locale is with set_locale.

class ApplicationController < ActionController::Base
  before_action :set_locale

  [...]
end

First time the user will connect, it will automatically set the locale extracted from the user's browser HTTP_ACCEPT_LANGUAGE value, and keep it in the session between requests.

Update the current locale by redirecting the user to https://yourdomain.com?locale=fr or even https://yourdomain.com/fr if you scoped your routes like this:

scope "/:locale", :constraints => { locale: /[a-z]{2}/ } do
  resources :pages
end

The set_locale code is here, feel free to override it with your own locale management.

Don't forget to define your available locales with I18n.available_locales.

More examples here: https://translation.io/blog/set-current-locale-in-your-rails-app

Locally

This command will change the locale for both I18n (YAML) and GetText:

I18n.locale = 'fr'

You can call it several times in the same page if you want to switch between languages.

More examples here: https://translation.io/blog/rails-i18n-with-locale

Frontend Localization

Using this Gem

This gem is also able to cover frontend localization (React, Vue, ...).

There are several ways to pass the translation strings from the backend to the frontend: JavaScript serialization, data- HTML attributes, JSON files etc.

The easiest strategy when dealing with React/Vue would be to pass the corresponding translations as props when mounting the components.

Assuming that you use reactjs/react-rails, it would look like this if you want to use I18n (YAML) syntax:

<%= 
react_component("MyComponent", {
  :user_id => current_user.id,
  :i18n    => YAML.load_file("config/locales/#{I18n.locale}.yml")[I18n.locale.to_s]["my_component"]
}) 
%>

Your en.yml should look like this:

en:
  my_component:
    your_name: Your name
    title: Title

You can also directly use the GetText syntax:

<%= 
react_component("MyComponent", {
  :user_id => current_user.id,
  :i18n => {
    :your_name => _('Your name'),
    :title     => _('Title')
  }
}) 
%>

In both case, in your React component, you can simply call this.props.i18n.yourName and your text will be localized with the current locale.

Notes:

  • You can also structure the i18n props with multiple levels of depth and pass the subtree as props to each of your sub-components.
  • It also works great with server-side rendering of your components (:prerender => true).

Using our official React & JavaScript package

As Translation.io is directly integrated in the great Lingui internationalization framework, you can also consider frontend localization as a completely different localization project.

Please read more about this on:

Continuous Integration

If you want fresh translations in your Continuous Integration workflow, you may find yourself calling bundle exec rake translation:sync very frequently.

Since this task can't be concurrently executed (we have a mutex strategy with a queue but it returns an error under heavy load), we implemented this threadsafe readonly task:

bundle exec rake translation:sync_readonly

This task will prevent your CI from failing and still provide new translations. But be aware that it won't send new keys from your code to Translation.io so you still need to call bundle exec rake translation:sync at some point during development.

Advanced Configuration Options

The TranslationIO.configure block in config/initializers/translation.rb can take several optional configuration options.

Some options are described below but for an exhaustive list, please refer to config.rb.

Disable GetText or YAML

If you want to only use YAML files and totally ignore GetText syntax, use:

TranslationIO.configure do |config|
  ...
  config.disable_gettext = true
  ...
end

In contrast, if you only want to synchronize GetText files and leave the YAML files unchanged, use:

TranslationIO.configure do |config|
  ...
  config.disable_yaml = true
  ...
end

Ignored YAML keys

Sometimes you would like to ignore some YAML keys coming from gems or so.

You can use the ignored_key_prefixes array with a mix or strings and regular expressions.

For example:

TranslationIO.configure do |config|
  ...
  config.ignored_key_prefixes = [
    'number.human',
    'admin',
    'errors.messages',
    'activerecord.errors.messages',
    'will_paginate',
    'helpers.page_entries_info',
    'views.pagination',
    'enumerize.visibility',
    /\.code$/
  ]
  ...
end

Custom localization key prefixes

Rails YAML files contain not only translation strings but also localization values (integers, arrays, booleans) in the same place and that's bad. For example: date formats, number separators, default currency or measure units, etc.

A translator is supposed to translate, not localize. That's not his role to choose how you want your dates or numbers to be displayed, right? Moreover, this special keys often contain special constructions (e.g., with percent signs or spaces) that he might break.

We think localization is part of the configuration of the app and it should not reach the translator UI at all. That's why these localization keys are detected and separated on a dedicated YAML file with Translation.io.

We automatically treat known localization keys, but if you would like to add some more, use the localization_key_prefixes option.

For example:

TranslationIO.configure do |config|
  ...
  config.localization_key_prefixes = ['my_gem.date.formats']
  ...
end

Source file formats (for GetText)

If you are using GetText and you want to manage other file formats than:

  • rb, ruby and rabl for Ruby.
  • erb and inky for Ruby templating.
  • haml and mjmlhaml for HAML.
  • slim and mjmlslim for SLIM.

Just add them in your configuration file like this:

TranslationIO.configure do |config|
  ...
  config.source_formats      << 'rb2'
  config.erb_source_formats  << 'erb2'
  config.haml_source_formats << 'haml2'
  config.slim_source_formats << 'slim2'
  ...
end

Gems with GetText strings

Public gems usually don't make use of GetText strings, but if you created and localized your own gems with the GetText syntax, you'll want to be able to synchronize them:

TranslationIO.configure do |config|
  ...
  config.parsed_gems = ['your_gem_name']
  ...
end

Paths where locales are stored (not recommended)

You can specify where your GetText and YAML files are on disk:

TranslationIO.configure do |config|
  ...
  config.locales_path      = 'some/path' # defaults to config/locales/gettext
  config.yaml_locales_path = 'some/path' # defaults to config/locales
  ...
end

GetText Object Class Monkey-Patching

GetText methods (_(''), etc.) are available everywhere in your application. This is made by extending the global Object class.

You can disable the built-in Object monkey-patching if you prefer a more granular approach:

TranslationIO.configure do |config|
  ...
  config.gettext_object_delegate = false
  ...
end

Don't forget to manually include the GetText methods where needed:

class Contact < ApplicationRecord
  extend TranslationIO::Proxy
end

Pure Ruby (without Rails)

This gem was created specifically for Rails, but you can also use it in a pure Ruby project by making some arrangements:

  require 'rubygems'
  require 'active_support/all'
  require 'yaml'

  class FakeConfig
    def after_initialize
    end
    def development?
      false
    end
  end

  module Rails
    class Railtie
      def self.rake_tasks
        yield
      end

      def self.initializer(*args)
      end

      def self.config
        ::FakeConfig.new
      end
    end

    def self.env
      ::FakeConfig.new
    end
  end

  task :environment do
  end

  require 'translation'

  I18n.load_path += Dir[File.join('i18n', '**', '*.{yml,yaml}')]

  # Put your configuration here:
  TranslationIO.configure do |config|
    config.yaml_locales_path = 'i18n'
    config.api_key           = ''
    config.source_locale     = 'en'
    config.target_locales    = ['nl', 'de']
    config.metadata_path     = 'i18n/.translation_io'
  end

(Thanks @kubaw for this snippet!)

Testing

To run the specs:

bundle exec rspec

Contributing

Please read the CONTRIBUTING file.

List of clients for Translation.io

The following clients are officially supported by Translation.io and are well documented.

Some of these implementations (and other non-officially supported ones) were started by contributors for their own translation projects. We are thankful to all contributors for their hard work!

Ruby on Rails (Ruby)

Officially supported on https://translation.io/rails

Credits: @aurels, @michaelhoste

Laravel (PHP)

Officially supported on https://translation.io/laravel

Credits: @armandsar, @michaelhoste

React, React Native and JavaScript

Officially supported on https://translation.io/lingui

Translation.io is directly integrated in the great Lingui internationalization project.

Angular

Officially supported on https://translation.io/angular

Credits: @SimonCorellia, @didier-84, @michaelhoste

Others

If you want to create a new client for your favorite language or framework, please read our Create a Translation.io Library guide and use the special init and sync endpoints.

You can also use the more traditional API.

Feel free to contact us on [email protected] if you need some help or if you want to share your library.

License

The translation gem in released under MIT license by Aurélien Malisart and Michaël Hoste (see LICENSE file).

(c) https://translation.io / [email protected]

rails's People

Contributors

didier-84 avatar dombo avatar ghiculescu avatar michael-harrison avatar michaelhoste avatar swiknaba avatar vddgil avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

rails's Issues

Localization files top element

We had this problem a few weeks ago, I think it still applies.

When generating with languages like "da-DK", "de-DE" etc. Then the top element becomes "da", "de" etc.

We just changed it since...

# file: localization.da-DK.yml
...
# You can edit and/or add new localization keys here, they won't be touched by Translation.io.
...

Isn't it possible to only use gettext?

Since I'm using gettext I tried to remove every other yml translation file. Long story short I couldn't.

The closest I got was to add the prefixes of keys on the ignored keys but I ended up with an empty translation.*.yml and a populated localization.*.yml.

Env info:

ruby 2.6.0p0

rails 5.2.1

translation (1.17)
      gettext (~> 3.2, >= 3.2.5)

Need a suggestion on how to keep the source pluralization clean

Hi guys,

I met the following issue today. I have a plural key for a number of students in English (source locale) in which it makes perfect sense:

        students_count:
          one: '1 student'
          other: "%{count} students"

However, in order to have it translated into Arabic, I need to add a few more keys to the English translation file:

        students_count:
          zero: "0 students"
          one: "1 student"
          two: "2 students"
          few: "%{count} students"
          many: "%{count} students"
          other: "%{count} students"

in order to have them appeared in Arabic locale in translations.io.

Could you suggest a way to avoid adding redundant keys to the English translation YML file?

Thanks,
Serhiy

Special characters in translation

If I write the following segments

example_one: It is equal to 3
example_two: It is > 3
example_three: It is too big

then the YAML that gets produced becomes

example_one: It is equal to 3
example_two: It is
  > 3
example_three: It is too big

To get it the created YAML on one line, I can wrap the text in the segment in quotation marks, but then the produced YAML will become:

example_one: It is equal to 3
example_two: '"It is > 3"'
example_three: It is too big

Note the double quation marks. Is there any way to get the produced YAML on one line, like, example_two: It is > 3, without it breaking into a new line?

gettext strings missing after use of case statement in erb

Ruby 2.6.6
Rails 6.1.4.1
translation: 1.27

With this code:

<%= _('jason test 1') %>
<% case 1 %>
<% end %>
<%= _('jason test 2') %>

Only jason test 1 appears in app.pot after a sync.

With this code:

<%= _('jason test 1') %>
<% case 1
end %>
<%= _('jason test 2') %>

Both jason test 1 and jason test 2 appear in app.pot.

Skip gettext steps when disabled

In our repo, we have disabled gettext support. However, running the sync produces:

$ rake translation:sync
* Downloading YAML source editions.
* Applying YAML source editions.
* Updating POT file.
* Generating POT file from YAML files.
* Saving new PO files.
* Creating new MO files.
* Saving new translation YAML files.
* Saving new localization YAML files (with non-string values).
* Collecting YAML localization entries

----------
Use this URL to translate: http://translation.io/david-a-wheeler/cii-best-practices-badge
----------

Shouldn't the middle 4 steps involving POT, PO and MO files be skipped?

Strings not get synced

When I run sync first time, everything looks ok:

* Downloading YAML source editions.
* Applying YAML source editions.
* Updating POT file.
* Generating POT file from YAML files.
* Sending data to server (it may take some time, please be patient).
* Saving new translation YAML files.
* Saving new localization YAML files (with non-string values).
* Collecting YAML localization entries from server.

----------
Use this URL to translate: https://translation.io/...

Then when I run sync again, it founds unused strings:

* Downloading YAML source editions.
* Applying YAML source editions.
* Updating POT file.
* Generating POT file from YAML files.
* Sending data to server (it may take some time, please be patient).
* Saving new translation YAML files.
* Saving new localization YAML files (with non-string values).
* Collecting YAML localization entries from server.

----------
2 keys/strings are in Translation.io but not in your current branch.
Execute "rake translation:sync_and_show_purgeable" to list these keys/strings.

----------
Use this URL to translate: https://translation.io/

These 2 key/stringsare already presented in my current codebase. But gem does not see them. But when I again run sync - it founds these strings again.

* Downloading YAML source editions.
* Applying YAML source editions.
* Updating POT file.
* Generating POT file from YAML files.
* Sending data to server (it may take some time, please be patient).
* Saving new translation YAML files.
* Saving new localization YAML files (with non-string values).
* Collecting YAML localization entries from server.

----------
Use this URL to translate: https://translation.io/...

Its like a circle (or loop): found/notfound/found/notfound etc...

A way to exclude translation keys

Hi,

I have a file in a project that I do not want by any means to be translated by a person or the auto translate service.
So, I'm wondering if there is a way to exclude translation keys or files so that the keys/files will not be sent to translation.io and/or auto-translated.

Thanks!

Allow some single-quoted HAML coding styles

Currently, using = _('foo') and = _("foo") work, as well as =_ "foo" and = _"foo", but not =_ 'foo' nor = _'foo'. The latter style won't be picked up, and it took a bit of investigation to figure out why.

https://github.com/aurels/translation-gem/blob/master/lib/translation_io/extractor.rb has a regex that, according to https://www.debuggex.com/r/fYSQ-jwQfTjhhE6T omits these cases.

It would be nice to have these fixed, or document their exclusion. For now, I'll be vigilant in using double-quotes and will put it in my own projects' documentation.

Oh, and thanks for a great service! I'm a very happy new user, otherwise :)

Global upload

I need to be able to do a global search and replace on all the locale translations. For example, turning all <i> into <em>. It would be great to support an upload to translation.io, as well as download from.

Ruby 3.1 compatibility (Psych 4 breaking change)

Hello,

rake translation:sync rake task fails with: Psych::BadAlias: Unknown alias: male_first_name under Ruby 3.1.1.

YAML::load calls across sources need to be updated.

Example adjustment (if you want to support older and newer Psych with same gem version):

read_options = RUBY_VERSION >= "3.1.0" ? { :aliases => true } : {}
configurations = YAML.load(File.read(file_path, **read_options)

Thank you.

Crash on "rake translation:init"

Hello

Here is my configuration:

TranslationIO.configure do |config|
  config.api_key        = '...'
  config.source_locale  = 'en'
  config.target_locales = %w[en]

  # Uncomment this if you don't want to use gettext
  config.disable_gettext = true

  config.ignored_key_prefixes = %w[
    time.formats demo
  ]
end

So, it's crashed on:

> rake translation:init
...
rake aborted!
JSON::ParserError: Empty input () at line 1, column 1 [parse.c:951] in '<!DOCTYPE html>

The only one place where I have it is:
mailer.html.erb

By the config I thought that it shouldn't go to views at all. So, why it goes? And how to fix?

ignore specific files

Your documentation explain how to ignore specific keys, but what about a config to ignore specific files ?

Error when starting Pushion Passenger

With the last version of this gem (1.33), on rails 6.1.7, ruby 2.7.5, nginx 1.20.2, passenger can't start the web server.

Here are the details of the error found in /var/log/nginx/error.log:

App 23240 output: Error: The application encountered the following error: You have already activated forwardable 1.3.1, but your Gemfile requires forwardable 1.3.2. Since forwardable is a default gem, you can either remove your dependency on it or try updating to a newer version of bundler that supports forwardable as a default gem. (Gem::LoadError)
App 23240 output:     /usr/local/rvm/gems/ruby-2.7.5/gems/bundler-2.3.7/lib/bundler/runtime.rb:309:in `check_for_activated_spec!'
App 23240 output:     /usr/local/rvm/gems/ruby-2.7.5/gems/bundler-2.3.7/lib/bundler/runtime.rb:25:in `block in setup'
App 23240 output:     /usr/local/rvm/gems/ruby-2.7.5/gems/bundler-2.3.7/lib/bundler/spec_set.rb:136:in `each'
App 23240 output:     /usr/local/rvm/gems/ruby-2.7.5/gems/bundler-2.3.7/lib/bundler/spec_set.rb:136:in `each'
App 23240 output:     /usr/local/rvm/gems/ruby-2.7.5/gems/bundler-2.3.7/lib/bundler/runtime.rb:24:in `map'
App 23240 output:     /usr/local/rvm/gems/ruby-2.7.5/gems/bundler-2.3.7/lib/bundler/runtime.rb:24:in `setup'
App 23240 output:     /usr/local/rvm/gems/ruby-2.7.5/gems/bundler-2.3.7/lib/bundler.rb:151:in `setup'
App 23240 output:     /usr/local/rvm/gems/ruby-2.7.5/gems/bundler-2.3.7/lib/bundler/setup.rb:20:in `block in <top (required)>'
App 23240 output:     /usr/local/rvm/gems/ruby-2.7.5/gems/bundler-2.3.7/lib/bundler/ui/shell.rb:136:in `with_level'
App 23240 output:     /usr/local/rvm/gems/ruby-2.7.5/gems/bundler-2.3.7/lib/bundler/ui/shell.rb:88:in `silence'
App 23240 output:     /usr/local/rvm/gems/ruby-2.7.5/gems/bundler-2.3.7/lib/bundler/setup.rb:20:in `<top (required)>'
App 23240 output:     /usr/local/rvm/rubies/ruby-2.7.5/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:85:in `require'
App 23240 output:     /usr/local/rvm/rubies/ruby-2.7.5/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:85:in `require'
App 23240 output:     /usr/local/rvm/gems/current-gems/gems/passenger-version/src/ruby_supportlib/phusion_passenger/loader_shared_helpers.rb:380:in `activate_gem'
App 23240 output:     /usr/local/rvm/gems/current-gems/gems/passenger-version/src/ruby_supportlib/phusion_passenger/loader_shared_helpers.rb:221:in `block in run_load_path_setup_code'
App 23240 output:     /usr/local/rvm/gems/current-gems/gems/passenger-version/src/ruby_supportlib/phusion_passenger/loader_shared_helpers.rb:544:in `running_bundler'
App 23240 output:     /usr/local/rvm/gems/current-gems/gems/passenger-version/src/ruby_supportlib/phusion_passenger/loader_shared_helpers.rb:220:in `run_load_path_setup_code'
App 23240 output:     /usr/local/rvm/gems/current-gems/gems/passenger-version/src/helper-scripts/rack-preloader.rb:91:in `preload_app'
App 23240 output:     /usr/local/rvm/gems/current-gems/gems/passenger-version/src/helper-scripts/rack-preloader.rb:189:in `block in <module:App>'
App 23240 output:     /usr/local/rvm/gems/current-gems/gems/passenger-version/src/ruby_supportlib/phusion_passenger/loader_shared_helpers.rb:397:in `run_block_and_record_step_progress'
App 23240 output:     /usr/local/rvm/gems/current-gems/gems/passenger-version/src/helper-scripts/rack-preloader.rb:188:in `<module:App>'
App 23240 output:     /usr/local/rvm/gems/current-gems/gems/passenger-version/src/helper-scripts/rack-preloader.rb:30:in `<module:PhusionPassenger>'
App 23240 output:     /usr/local/rvm/gems/current-gems/gems/passenger-version/src/helper-scripts/rack-preloader.rb:29:in `<main>'
[ E 2022-11-11 23:11:53.9649 13906/T4q age/Cor/App/Implementation.cpp:221 ]: Could not spawn process for application /var/www/webroot/ROOT: The application encountered the following error: You have already activated forwardable 1.3.1, but your Gemfile requires forwardable 1.3.2. Since forwardable is a default gem, you can either remove your dependency on it or try updating to a newer version of bundler that supports forwardable as a default gem. (Gem::LoadError)
  Error ID: 90d7c365
  Error details saved to: /tmp/passenger-error-YXams6.html

forwardable seems to be a dependence of gettext so I'm uncertain if your gem is responsible for that (please note that I don't
use the gettext gem, so parameter config.disable_gettext is set to true).

Please don't create ending whitespace

By policy our project doesn't allow files with whitespace errors, as determined by "git diff --check".

Unfortunately, "sync" creates .yml files with trailing whitespace. It's possible to fix it, but it's a pain, and I suspect many projects have this rule.

Could sync stop creating trailing whitespace?

Thanks so much! I only just started, but this does look like an interesting service.

FYI, here's the documentation from git diff --check:

       --check
           Warn if changes introduce whitespace errors. What are considered
           whitespace errors is controlled by core.whitespace configuration.
           By default, trailing whitespaces (including lines that solely
           consist of whitespaces) and a space character that is immediately
           followed by a tab character inside the initial indent of the line
           are considered whitespace errors. Exits with non-zero status if
           problems are found. Not compatible with --exit-code.

Do not add methods on Object

Currently , TranslationIO.configure ends with a lot of methods added to Object and delegated to Proxy

It is a code smell to add methods on Object, and may create lots of issues when using multiple translation system or migrating from one to another for example.

I would definitely prefer adding an include TranslationIO::Proxy in my classes than having these methods magically inherited.

Would you consider adding a mechanism similar to disable_gettext which would disable_object_monkey_patching ? Maybe even make that the default in a future major version change ?

Deprecation warning on Rails 6

It seems this gem is using some code that is deprecated in Rails 6. I get this when I ran an rspec with this gem loaded:

DEPRECATION WARNING: Initialization autoloaded the constants ActionText::ContentHelper and ActionText::TagHelper.

Being able to do this is deprecated. Autoloading during initialization is going
to be an error condition in future versions of Rails.

Reloading does not reboot the application, and therefore code executed during
initialization does not run again. So, if you reload ActionText::ContentHelper, for example,
the expected changes won't be reflected in that stale Module object.

These autoloaded constants have been unloaded.

Please, check the "Autoloading and Reloading Constants" guide for solutions.

See rails/rails#36546 for more.

NoMethodError: undefined method `current=' for Locale:Module

I'm getting this error when trying to run bundle exec rake --trace translation:init:

** Invoke translation:init (first_time)
** Invoke environment (first_time)
** Execute environment
rake aborted!
NoMethodError: undefined method `current=' for Locale:Module
/usr/local/opt/rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/gettext-3.2.2/lib/gettext.rb:274:in `set_current_locale'
/usr/local/opt/rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/translation-1.9/lib/translation_io/railtie.rb:28:in `locale='
/usr/local/opt/rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/i18n-0.7.0/lib/i18n.rb:35:in `locale='
/usr/local/opt/rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/translation-1.9/lib/translation_io/railtie.rb:16:in `block in <class:Railtie>'
/usr/local/opt/rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/lazy_load_hooks.rb:36:in `execute_hook'
/usr/local/opt/rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/lazy_load_hooks.rb:45:in `block in run_load_hooks'
/usr/local/opt/rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/lazy_load_hooks.rb:44:in `each'
/usr/local/opt/rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/activesupport-4.2.8/lib/active_support/lazy_load_hooks.rb:44:in `run_load_hooks'
/usr/local/opt/rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/railties-4.2.8/lib/rails/application/finisher.rb:62:in `block in <module:Finisher>'
/usr/local/opt/rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/railties-4.2.8/lib/rails/initializable.rb:30:in `instance_exec'
/usr/local/opt/rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/railties-4.2.8/lib/rails/initializable.rb:30:in `run'
/usr/local/opt/rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/railties-4.2.8/lib/rails/initializable.rb:55:in `block in run_initializers'
...

I tried disabling gettext, but it had no effect.

Ideas?

Ruby: 2.3.3
Rails: 4.2.8

Deprecation warning for #has_rdoc (Rubygems)

NOTE: Gem::Specification#has_rdoc= is deprecated with no replacement. It will be removed on or after 2018-12-01.
Gem::Specification#has_rdoc= called from /Users/eric/.rvm/gems/ruby-2.6.2/bundler/gems/translation-ff98468dc2da/translation.gemspec:13.

https://blog.rubygems.org/2011/03/28/1.7.0-released.html
https://blog.rubygems.org/2009/05/04/1.3.3-released.html

There doesn't seem to be any replacements, so I would suggest only removing the has_rdoc line.

Empty hash in localization.en.yml

After sync, I get empty localization.en.yml (comments only), and as result - rails throws error can not load translations from /usr/src/app/config/locales/localization.en.yml: expects it to return a hash, but does not
Generated file:

# THIS FILE CONTAINS LOCALIZATION KEYS : date and number formats, number precisions,
# number separators and all non-textual values depending on the language.
# These values must not reach the translator, so they are separated in this file.
#
# More info here: https://translation.io/blog/gettext-is-better-than-rails-i18n#localization
#
# You can edit and/or add new localization keys here, they won't be touched by Translation.io.
#
# If you want to add a new localization key prefix, use the option described here:
# https://github.com/translation/rails#custom-localization-key-prefixes
#

Rails expects it to be an empty hash, with locale key.

Wrap YAML

The YAML coming back from translation.io works fine but looks ugly. We're adding a post-processing step to the translation:sync rake task that the loads and resaves the YAML to provide 80-character line wrapping. This both gets rid of most of the white space before closing quotes (') and switches to the more readable YAML folding style. In parallel, as mentioned in #13, we're deleting whitespace at the end of lines. The main code is:

  filenames = Dir[Rails.root.join('config', 'locales', 'translation.*.yml')]
  filenames.each do |filename|
    IO.write(
      filename, YAML.load_file(filename).to_yaml(line_width: 80)
                    .gsub(/ $/, '')
    )
  end

This produces diffs like:

-      may_select_html: 'Sie können eines Ihrer GitHub Repositories <em>ODER</em> Informationen
-        über ein anderes Projekt auswählen.
-
-'
+      may_select_html: >
+        Sie können eines Ihrer GitHub Repositories <em>ODER</em> Informationen über
+        ein anderes Projekt auswählen.
-      url_of_homepage: 'Wie lautet die URL für die Projekt-Homepage (die URL für das
-        Projekt als Ganzes)? Start mit http(s):// (viele Zeichen sind nicht erlaubt,
-        einschließlich "?")
-
-'
+      url_of_homepage: >
+        Wie lautet die URL für die Projekt-Homepage (die URL für das Projekt als Ganzes)?
+        Start mit http(s):// (viele Zeichen sind nicht erlaubt, einschließlich "?")

line_width is a poorly documented feature of the Psych YAML library.

Would you be open to a pull request that converts the 4 uses of to_yaml in this translation gem to instead be to_yaml(line_width: 80)?

Cc @david-a-wheeler

Match I18n fallbacks in GetText

I18n allows for custom fallbacks for each locale. It would be nice if this could be reflected in GetText. I don't think Locale supports multiple defaults or custom fallbacks, however it does support multiple current locales. You could simulate it with the following.

Locale.set_current(*I18n.fallbacks[I18n.locale])

Perhaps do this when overriding the I18n::Config.locale= method in railtie.rb?

Speaking of overriding locale= you could add behavior in its own module and prepend it to avoid duplicating the original method.

module TranslationIO::I18nConfigExtension
  def locale=(*args)
    super
    if defined? Locale
      Locale.set_current(*I18n.fallbacks[I18n.locale])
    end
  end
end

I18n::Config.prepend TranslationIO::I18nConfigExtension

Gettext translations cached after switching locale?

Hi.
I have a problem with translations being cached.
Behaviour in rails console, works fine:

I18n.locale = :en

_('Dashboard')
=> "Dashboard"

I18n.locale = :lv

_('Dashboard')
=> "Sākums"

In controller action (via binding pry):

[1] pry> I18n.locale = "en"
=> "en"
[2] pry)> _('Dashboard')
=> "Dashboard"
[3] pry> I18n.locale = "lv"
=> "lv"
[4] pry> _('Dashboard')
=> "Dashboard"

There is no problem if locale is set only once per request (we do this in before action in base controller).
But in this controller action we need part of code within a block
I18n.with_locale(locale) executed with different locale.
Inspecting I18n.locale and GetText.locale within the block we see that locale is switched correctly, but translations appear cached.
Calling ::GetText::TextDomainManager.clear_caches does not help.

Errantly finding translation keys in markdown

I have markdown in a haml file similar to the following (via my site's Terms of Service):

:markdown
    These Terms of Service (**_“Terms”_**) govern your access to this website [...]

Here, it's finding Terms to be a translation key. A workaround could be to switch the operators: __*"Terms"*__, but I thought I'd bring up the issue so you're aware of it.

Note, we noticed because we translated our TOS into Spanish via terms_of_service.es.html.haml, and it saw Términos from **_"Términos"_**. So, a separate issue might be that the gem should recognize es.html as not being a source for english translation keys. In our case, though, fixing the main issue I'm bringing up would fix the es.html-as-english issue.

Unclear how to use custom locales in project

Hi all,

I'd like to use translation.io to manage copy for A/B tests in my Rails project, and the custom languages feature seems ideal for this.

I've tried using custom locales with the syntax suggested in the README but,

  • the UI for creating a new project doesn't allow you to provide custom locales.
  • it doesn't seem like you can use these custom locales in the initializer either, because GetText doesn't recognize them.

What steps should I be taking to use custom languages?

Thanks,
Nuno

PS: excellent project.

translation:sync_and_purge dry run

A small request for a --dry-run feature on sync_and_purge dry method.
Could be nice to get a list of which keys it wants to purge before actually doing it.

getText method not translating text as supposed to after install and intialization

What do you expect to happen?

Installed translation gem with bundle install.

created a app and added the config/initializers/translation.rb

ran bundle exec rake translation:init and this actually produced a warning saying it could not find most of the translation YAML files (I believe it said) asking is this normal? etc and listed most of the locales I had listed in my initializer but I continued anyway.

Text should get translated to eg es or ru which is listed in my intializer. Also running locale -a seems to list all translation.io locales.

locale -a
  C
C.utf8
POSIX
af_ZA
af_ZA.utf8
am_ET
am_ET.utf8
ar_AE
ar_AE.utf8
ar_BH
...

What actually happened?

Text stays as default locale ie en

Code to reproduce

I18n.with_locale(:ru) do
  puts I18n.locale 
  _('hello everyone, how are you today')
end

ru
hello everybody, how are you today

Version

translation (1.21)
gettext (~> 3.2, >= 3.2.5)
rails 6.0.0.1
ruby 2.6.5

sync is leaving behind yml-e files

Hi, running sync leaves my repo with a bunch of odd files:

$ rake translation:sync
cp -p config/locales/en.yml config/locales/en.yml.ORIG
* Downloading YAML source editions.
* Applying YAML source editions.
* Updating POT file.
* Generating POT file from YAML files.
* Saving new PO files.
* Creating new MO files.
* Saving new translation YAML files.
* Saving new localization YAML files (with non-string values).
* Collecting YAML localization entries

----------
Use this URL to translate: http://translation.io/david-a-wheeler/cii-best-practices-badge
----------
Removing bogus trailing whitespace (bug workaround).
cd config/locales/ && sed -i -e 's/ $//' *.yml && cd ../..
mv config/locales/en.yml.ORIG config/locales/en.yml
Now run: git commit -as -m 'rake translation:sync'
$ git status
 M config/locales/.translation_io
 M config/locales/translation.fr.yml
?? config/locales/en.yml-e
?? config/locales/localization.de.yml-e
?? config/locales/localization.fr.yml-e
?? config/locales/localization.ja.yml-e
?? config/locales/localization.zh-CN.yml-e
?? config/locales/translation.de.yml-e
?? config/locales/translation.fr.yml-e
?? config/locales/translation.ja.yml-e
?? config/locales/translation.zh-CN.yml-e

The first two (modified) files are just what I expect. But then all of the config/locales/*.yml-e files shouldn't be there. Obviously, I delete them and may add an additional sync task to do so automatically.

But I thought I'd report this in case anyone else sees the same thing. I'm on OS X while my colleague on Linux doesn't this issue.

Cc @david-a-wheeler

Gem memory usage

I'm looking for ways to reduce the in-memory usage of our app, and noticed translation is half the memory footprint of Rails itself!

Using https://github.com/schneems/derailed_benchmarks on my app, I found:

translation: 10.9258 MiB
  gettext/tools: 6.9023 MiB
    gettext/tools/msginit: 5.3867 MiB
      locale/info: 4.582 MiB
        locale/info/language: 4.4648 MiB
      gettext/tools/msgmerge: 0.668 MiB (Also required by: gettext/tools)
        text: 0.5313 MiB
    gettext/tools/xgettext: 1.3164 MiB (Also required by: translation_io/railtie)
      gettext/tools/parser/erb: 1.1445 MiB
        gettext/tools/parser/ruby: 1.0977 MiB (Also required by: gettext/tools/xgettext)
          irb/ruby-lex: 1.0039 MiB
            irb/ruby-token: 0.457 MiB
  gettext/po_parser: 2.1328 MiB (Also required by: gettext/tools/msgfmt, gettext/tools/msginit, and 3 others)
  gettext: 0.8828 MiB (Also required by: gettext/tools/xgettext, gettext/tools/parser/glade, and 5 others)
    locale: 0.4336 MiB (Also required by: gettext/tools/xgettext)
      locale/tag: 0.3047 MiB
    gettext/text_domain_manager: 0.4336 MiB (Also required by: translation)
      gettext/text_domain: 0.3867 MiB
  translation_io/client: 0.4961 MiB

For the running app, after it's been translated, is there anything I/we can cut? What is "locale/info/language" (4.4mb) and "gettext/po_parser" (2.1328mb)?

Thanks!

Error while running `translations:sync`: ArgumentError: comparison of Pathname with String failed

I came across an issue while running rails translations:sync recently:

ArgumentError: comparison of Pathname with String failed
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/translation-1.22/lib/translation_io/client/sync_operation/apply_yaml_source_edits_step.rb:65:in `sort'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/translation-1.22/lib/translation_io/client/sync_operation/apply_yaml_source_edits_step.rb:65:in `yaml_sources_reload_needed?'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/translation-1.22/lib/translation_io/client/sync_operation/apply_yaml_source_edits_step.rb:47:in `reload_or_reuse_yaml_sources'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/translation-1.22/lib/translation_io/client/sync_operation/apply_yaml_source_edits_step.rb:23:in `block in run'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/translation-1.22/lib/translation_io/client/sync_operation/apply_yaml_source_edits_step.rb:20:in `each'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/translation-1.22/lib/translation_io/client/sync_operation/apply_yaml_source_edits_step.rb:20:in `run'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/translation-1.22/lib/translation_io/client/sync_operation.rb:26:in `run'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/translation-1.22/lib/translation_io/client.rb:19:in `sync'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/translation-1.22/lib/translation_io/tasks.rb:23:in `block (2 levels) in <top (required)>'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/rake-12.3.3/lib/rake/task.rb:273:in `block in execute'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/rake-12.3.3/lib/rake/task.rb:273:in `each'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/rake-12.3.3/lib/rake/task.rb:273:in `execute'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/bugsnag-6.7.3/lib/bugsnag/integrations/rake.rb:18:in `execute_with_bugsnag'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/rake-12.3.3/lib/rake/task.rb:214:in `block in invoke_with_call_chain'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/2.3.0/monitor.rb:214:in `mon_synchronize'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/rake-12.3.3/lib/rake/task.rb:194:in `invoke_with_call_chain'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/rake-12.3.3/lib/rake/task.rb:183:in `invoke'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/rake-12.3.3/lib/rake/application.rb:160:in `invoke_task'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/rake-12.3.3/lib/rake/application.rb:116:in `block (2 levels) in top_level'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/rake-12.3.3/lib/rake/application.rb:116:in `each'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/rake-12.3.3/lib/rake/application.rb:116:in `block in top_level'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/rake-12.3.3/lib/rake/application.rb:125:in `run_with_threads'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/rake-12.3.3/lib/rake/application.rb:110:in `top_level'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/railties-5.2.4.4/lib/rails/commands/rake/rake_command.rb:23:in `block in perform'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/rake-12.3.3/lib/rake/application.rb:186:in `standard_exception_handling'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/railties-5.2.4.4/lib/rails/commands/rake/rake_command.rb:20:in `perform'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/railties-5.2.4.4/lib/rails/command.rb:48:in `invoke'
/Users/mlow/.rbenv/versions/2.3.7/lib/ruby/gems/2.3.0/gems/railties-5.2.4.4/lib/rails/commands.rb:18:in `<top (required)>'
bin/rails:11:in `require'
bin/rails:11:in `<main>'
Tasks: TOP => translation:sync

I did a little digging and it seems like Pathname objects are being added to the I18n.load_path somehow. In this case there were a couple:

  • a yml file internal to our project, which actually had another entry of type String with the same path
  • a yml entry from an external gem: https://github.com/dry-rb/dry-validation/tree/v0.12.3. The file in question is config/errors.yml from that particular tag/version

These files get added to the load path because File.exist? and File.extname can take in a String or a Pathname, so I'm not entirely sure what the best route is here. Let me know what you think!

Traditional Chinese not being picked up

When translating Spanish, everything seems to be working as expected. When translating to traditional Chinese (zh-Hant), no translations are picked up.

I created a project to repro the issue, but made it private out of general paranoya since the project I extracted it from is private. @aurels has access: https://github.com/InPlay/translation_bug_repro.

Here is the test from the repro project, traditional_chinese_test.rb:

require 'minitest/spec'
require 'minitest/autorun'
require 'rails'
require 'translation'

TranslationIO.configure do |config|
  config.api_key        = ''
  config.source_locale  = 'en'
  config.target_locales = ['zh-Hant', 'es']
  config.locales_path   = 'gettext'
end

describe 'When translating from English' do
  it 'can translate "Sign In" to Spanish' do
    TranslationIO::Proxy.current_locale = 'es'
    TranslationIO::Proxy._("Sign Up").must_equal("Regístrese")
  end

  it 'can translate "Sign In" to Chinese' do
    TranslationIO::Proxy.current_locale = 'zh_Hant'
    TranslationIO::Proxy._("Sign Up").must_equal("報名")
  end
end

Here's the output from running ruby traditional_chisese_test.rb in the repro directory:

# Running:

.F

Finished in 0.007483s, 267.2868 runs/s, 267.2868 assertions/s.

  1) Failure:
When translating from English#test_0002_can translate "Sign In" to Chinese [traditional_chisese_test.rb:24]:
Expected: "報名"
  Actual: "Sign Up"

2 runs, 2 assertions, 1 failures, 0 errors, 0 skips

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.