Code Monkey home page Code Monkey logo

translator's Introduction

Translator - i18n tooling for Rails

Translator makes using the internationalization (i18n) facility introduced in Rails 2.2 simpler through:

  • keeping your code DRY using simple conventions

  • make testing easier to catch missing keys

  • supplying a graceful “fallback” mode when a translation is missing in a user’s locale

The Problem

The (very!) helpful I18n library finds keys in locale bundles (and more), but doesn’t know anything about Rails applications. Applications that have a lot of strings need a system of keeping them organized. Translator adds smarts to controllers, views, models & mailers to follow a simple convention when finding keys. Having a convention for the hierarchy of keys within locale bundles that makes it easier to code and maintain, while still using the capabilities of the underlying I18n library. (Note: Translator does not depend on how the actual YAML/Ruby files are stored in the filesystem.)

Quick example - if you follow the key convention of structuring your locale bundle like:

blog_posts: # controller
  show: # action
    title: "My Awesome Blog Post"
    byline: "Written by {{author}}"

Then when writing the BlogPostsController.show action you can just use t('title') to fetch the string (equivalent to I18n.translate('blog_posts.show.title')). Similarly, in the show.erb template you can get use t('byline', :author => "Mike"). This extends to models and mailers as well. As they say, “Look at all the things I’m not doing!”

Installation

To install this plugin into your Rails app (2.2 or 2.3+):

./script/plugin install git://github.com/graysky/translator.git

To install as a gem add the following to config/environment.rb:

config.gem "graysky-translator", :lib => "translator", :source => "http://gems.github.com"

RDocs

The RDocs are online or can be generated via rake rdoc in the translator plugin directory.

Problems or Suggestions

Please file an issue in the Github bug tracker or contact me.

Simple translate Everywhere

Translator adds an enhanced translate (or shorter t) method to:

  • ActionController

  • ActionView

  • ActiveRecord

  • ActionMailer

In the spirit of Rails, the convention for a hierarchy of keys borrows the same layout as the typical “views” directory. A sample Blog application is used as an example.

For controllers/views/mailers it is:

en: # locale
  # the controller name
  blog_posts:
    # the action name
    index:
      key: "Hello World"

    # partials w/o underscore (template "_footer.erb")      
    footer: 
      key: "My Copyright"

  # "layouts" is fixed
  layouts:
    # the layout name (template "main.erb")
    main:
      key: "My App Name"

  # for shared partials called like: render :template => "shared/user"
  # where "shared" is the directory name
  shared:
    # partial name w/o underscore (template "_user.erb")
    user:
      key: "Foo"

  # the full mailer name
  blog_comment_mailer:
    # the method name (does not include "deliver")
    comment_notification:
      subject: "New Comment"

For models it is:

en:
  # The model name
  blog_post:
    key: "Custom validation error"

Key Lookup

When a key is looked up, Translator adds extra scoping to the lookup based on where it is called from. For:

  • Controllers & views the scope includes [:controller_name, :action_name]. (For shared partials it is [:template_path, :partial_name])

  • Mailers the scope includes [:mailer_name, :method_name]

  • Models the scope includes [:model_name]

But what happens if you want to share strings across a controller? Let’s say you have error messages that are set in flash notices and then are shared between actions in a controller defined in the locale bundle like:

blog_posts:
  errors:
    permission_denied: "Permission denied to read this blog post"

If Translator doesn’t find the original key, it will remove a layer of scoping and try again. So if in our Blogs controller show action we want to set a flash[:error] to a permission denied message it can find the string by calling t('errors.permission_denied'). Translator will first look for “blog_posts.show.errors.permission_denied”, which doesn’t exist. So it will then try to find “blog_posts.errors.permission_denied” and return the correct string. This can be used to create greater levels of scoping, or to force finding global strings (e.g. t("global.app_name")).

Graceful Locale Fallback

Let’s say you’ve extracted all your English strings, and even had them translated to Spanish to make your Spanish-speaking users extra happy. Then you have a brilliant idea for a new feature that needs to go live before the new pages are translated into Spanish. You still want your Spanish-speaking users to keep seeing the site in Spanish, but for these new pages to fallback to English. (While not exactly ideal, it is better than having “translation missing” messages or not externalizing strings.) To enable this fallback behavior:

# In the configuration
I18n.default_locale = :en

# Enable the fallback mode to try :es first, then :en
Translator.fallback(true)

# Set in the code based on user's preference, their IP address, etc.
I18n.locale = :es

# Everything else stays the same, but after Translator tries the normal scoping rules
# in Spanish (:es), it will apply the same rules for the default locale (:en)
t('page_title')

Testing Help

  • Translator.strict_mode will cause an exception to be raised for any missing translations. Enabled by default during testing to help find mistyped or accidently forgotten keys. It can be disabled by calling Translator.strict_mode(false) (in test_helper for example).

  • assert_translated takes a block and asserts that all lookups within that block have real translations. It is a more targeted version of strict_mode. Example:

    assert_translated do
      # Will assert that all keys find valid translations inside the block
      get :show
    end
    
  • If you’re trying to avoid hard-coding strings in tests, you can still use the lookup that is added to models and controllers:

    # Inside a test exercising a BlogPostController (@controller created in setup method)
    get :show, :id => 123
    # the byline should be in the body - uses @controller to make lookup easy (automatically knows controller name and action)
    assert_match @controller.t('byline', :name => "Mike"), @response.body
    
  • Pseudo-translation mode. Pseudo-translation wraps all extracted strings with leading and trailing text so that you can spot if you forgot any. It can be enabled by Translator.pseudo_translate (in an environment file or locale.rb for example). It does not change the lookup process (e.g. t('blog_title')) but will transform the returned string from “My Blog” to “[[ My Blog ]]”. The text that is prepended / appended can be set by calling Translator.pseudo_prepend = "@@" (or append). Pro Tip: This can also be used to see how a layout will display in a localized language that is longer than the default. or example, German words tend to be significantly longer than their English equivalents. By padding all strings you can test how a layout will adapt and make changes.

  • Rake task to validate that YAML files are, in fact, valid YAML. Useful when getting back translations from a 3rd party service, this can be a quick way to catch a missing quote. Run like rake i18n:validate_yml and it will check all .yml files below RAILS_ROOT/config/locales.

Changelog

1.0.0 - 4/17/2009 - Declaring 1.0 after successfully using Translator in production.

Bug reports welcome. Patches very welcome.

Copyright © 2009 Mike Champion, released under the MIT license.

translator's People

Contributors

graysky 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

Watchers

 avatar

translator's Issues

Translator does not work with bundler

Hi,

I tried to use translator with bundler 0.8.1 and it install fine. However, I I get the following error, when doing calling rake (bin/rake, that is due to bundler...)
uninitialized constant ActionView::Helpers::TagHelper

And when running gem exec script/server:
/home/sh/evertango/vendor/bundler_gems/ruby/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:440:in `load_missing_constant': uninitialized constant ActionView::Helpers::TagHelper (NameError)

I'd love to fix this, but don't know where the dependency can be resolved. Any help is appreciated!

Scope for helpers?

It may be useful to have a special scope for helpers. For a controller-specific helper (e.g. BlogPostsHelper), it makes sense to just use the view scope, but not for shared helpers like ApplicationHelper.

Not sure how this should work, though.

You can extract the helper scope with something like caller.first[%r{/app/(helpers/.*?)_helper.rb:}, 1].split("/") in translate_with_context.

Maybe each helper should have a scope that is attempted before it falls back to the view scope? So it tries helpers.blog_posts.foo, then blog_posts.index.foo etc.

Thank you

<a href= http://jualanlelonghandphone.comeoufs.info/ >jualan lelong handphone
<a href= http://truyencoithienthai.changeoufs.info/ >truyen coi thien thai
<a href= http://examplesofmetaphor.comeoufs.info/ >examples of metaphor
<a href= http://bankairenjimugendownload.comeoufs.info/ >bankai renji mugen download
<a href= http://silabipservers.changeoufs.info/ >silab ip servers
<a href= http://mileycyrusnude.comeoufs.info/ >miley cyrus nude
<a href= http://kenmore70seriesdryerparts.comeoufs.info/ >kenmore 70 series dryer parts
<a href= http://markherrasscandal.changeoufs.info/ >mark herras scandal
<a href= http://freetoairfilesviewsat.causeoufs.info/ >freetoair files viewsat
<a href= http://casinoharrahslouisst.causeoufs.info/ >casino harrahs louis st
<a href= http://staphinfectionmerc.changeoufs.info/ >staph infection merc
<a href= http://deming4011pumps.causeoufs.info/ >deming 4011 pumps
<a href= http://rhiannabobshairstyle.changeoufs.info/ >rhianna bobs hairstyle
<a href= http://famousstarsandstripesbelt.changeoufs.info/ >famous stars and stripes belt
<a href= http://albagalindofotos.changeoufs.info/ >alba galindo fotos
<a href= http://mediumlonghaircuts.comeoufs.info/ >medium long haircuts
<a href= http://informationonpregancytest.changeoufs.info/ >information on pregancytest
<a href= http://playboykendrawilkinsonimage.comeoufs.info/ >playboy kendra wilkinson image
<a href= http://8teamtournamentbracketseed.causeoufs.info/ >8 team tournament bracket seed
<a href= http://babywingswithfootprintstattoos.changeoufs.info/ >baby wings with footprints tattoos

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.