Ссылки за неделю # 10/02/05

Ruby/Rails

Разное

Permalink | Leave a comment  »

Do you use LiveJournal ?

Every time I visit someone's page on LiveJournal, I see something like this.

It reminds me a Homer Simpson's web page. How people can use that crap ? Duh.

Ссылки за неделю # 10/01/29

Ruby/Rails

JavaScript

Разработка

Разное

Permalink | Leave a comment  »

Javascript I18n for Rails applications

Довольно часто в javascript приходится хранить текстовые данные, используемые, например, для отображения уведомлений, календаря и т.п. Естественно, что в многоязыковом приложении хотелось бы видеть эти данные локализованными. Именно для этого и предназначен rails плагин js_i18n.

Весь javascript код написан без использования каких бы то ни было фреймворков, так что прекрасно работает и с prototype.js, и с jQuery, и с любой другой библиотекой.

После установки плагина стандартным образом, нужно вызвать генератор, передав ему в качестве параметра список локалей:
$script/generate js_locales en ru

После завершения ком анды в приложении появятся файлы public/javascripts/i18n.js и два файла локалей (en.js и ru.js) в каталоге public/javascripts/locales.

Подключить эти скрипты можно при помощи хелпера javascript_i18n_include, просто добавьте следующую строку во вью:
<%= javascript_i18n_include %>

Этот хелпер всего лишь вызывает javascript_include_tag для i18n.js и одного из файлов локали. Какой файл локали подключать определяется исходя из значения I18n.locale.

Файл локали содержит всего одну переменную Translations, которая представляет собой обычный хэш, с обязательным ключом locale. Если ключ locale не существует, то по умолчанию считается, что локаль английская, т.е. locale = "en".

Пример содержимого файла public/javascripts/locales/ru.js:

1
2
3
var Translations = {
  locale: 'ru'
};

Ключ сообщения может быть задан в виде строки или вложенного хеша:

1
2
3
4
5
6
7
8
9
10
11
12
var Translations = {
  locale: 'ru',
  "foo.bar": "baz",
  
  nested: {
    hash: "value"
  },
  
  message: {
    times: "{{count}} times"
  }
};

Получить значение ключа можно аналогично вызову в руби:

1
2
3
I18n.t("foo.bar"); // -> "baz"
I18n.t("nested.hash"); // -> "value"
I18n.t("message.times", {count: 3}); // -> "3 times"

Текущую локаль можно получить используя I18n.locale().

PS. Так называемый "pluralization" я реализовывать не стал, так как, во-первых, на данный момент оно мне не нужно; во-вторых, с русским языком все равно придется извращаться.

Permalink | Leave a comment  »

Ruby NoName Podcast #23

Тви: rubynoname.

RSS и сайт подкаста на RPod.ru


Сегодня в программе, разговоры о:

В подкасте использованы композиции 8 BIT Junkie by George Wood и Мы круче группы Рубль

Rake task for checking missed locale keys

Задача локализации приложения превращается в геморрой, если это приложение чуть более сложное чем "hello world" (ну или "блог за 15 минут" если хотите).
Сразу возникают вопросы "какие ключи, относительно актуальной локали, отсутствуют в остальных?", "какие переводы устарели?", "есть ли в переводах лишние ключи?" и т.п. На данный момент времени я столкнулся только с первым вопросом, который был решен созданием rake задачи:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
namespace :translations do
  desc "Show available locales"
  task :available => :environment do
    puts "Available locales: #{I18n.available_locales.join(', ')}"
  end
 
  desc "Show missed translations depending on default language environment (:#{I18n.default_locale} by default). You can change it providing LOCALE argument"
  task :missed => :environment do
    locale = ENV['LOCALE'] || I18n.default_locale
    puts "Using :#{locale} as default locale"
    
    i18n_backend = I18n.backend
    i18n_backend.send(:init_translations) unless i18n_backend.initialized?
    translations = i18n_backend.send(:translations)
 
    main_translation = translations.delete(locale.to_sym)
    
    translations.each do |key, value|
      print "Checking :#{key} translations:"
      diff = find_keys_diff(main_translation, value)
      if diff.empty?
        puts " is up to date"
      else
        puts " here is list of missed translation keys"
        puts "\t" merge_diff(diff).sort.join("\n\t")
      end
    end
  end
 
  private
  def find_keys_diff(master, in_hash)
    master.inject([]) do |result, value|
      key = value.first
      if !in_hash.has_key?(key)
        result << key.to_s
      elsif value.last.is_a?(Hash)
        diff = find_keys_diff(master[key], in_hash[key])
        result << { key.to_s => diff } unless diff.empty?
      end
      result
    end
  end
 
  def merge_diff(diff, prefix = "")
    prefix << "." unless prefix.blank?
    diff.inject([]) do |result, value|
      if value.is_a?(Hash)
        result = merge_diff(value.first.last, prefix value.first.first)
      else
        result << "#{prefix}#{value}"
      end
      result
    end
  end
end
 

В гуглогруппе ror2ru упоминался инструмент Translate (веб интерфейс для перевода локалей в виде rails плагина), кроме собственно веб интерфейса он предоставляет несколько полезных rake задач (в том числе и поиск не переведенных кусков текста). Мне он не подошел, так как слишком тяжел и перегружен для моих текущих требований.

Быстро глянув в код, я обнаружил более страшный недостаток: translate считает, что переводы должны лежать в одном файле (то есть config/locales/en.yml и т.д.), я же предпочитаю раскладывать их по каталогам внутри config/locales, поэтому в своей rake задаче привязался к i18n.load_path.

Ссылки по теме:

 

Permalink | Leave a comment  »

Ссылки за неделю # 10/01/22

Сим постом открываю еженедельные посты с подборками интересных ссылок. Тематика будет соответствовать блогу, т.е. разработка в целом и ruby/rails в частности.

Ruby/rails

Другое

Ну и немного юмора: How a Common Lisp Programmer Views Users of Other Languages

Permalink | Leave a comment  »

Мой новый джем: PrettyDiff

Мой новый джем: PrettyDiff

AppConfig rails plugin

Когда-то давно, мы с товарищем, взяв за основу статью Dmytro Shteflyuk, сделали rails плагин для хранения глобальных настроек приложения. Наконец-то дошли руки выложить его на github http://github.com/ptzn/app_config, не прошло и трех лет да.

Плагин прост как деревяшка, но от этого не теряет своей юзабельности и полезности. Если нужно хранить какие-то глобальные настройки безо всяких изысков, будь-то емейл адреса, урлы, какие-то параметры и т.п. – этот плагин то что нужно.

После установки первое, что надо сделать – это создать config.yml. Это можно сделать двумя способами:

По умолчанию содержимое файла следующее:

http://gist.github.com/268501

Доступ к параметрам осуществляется очень просто: AppConfig.NAME (AppConfig.support_email, AppConfig.root_url, etc), причем значение, например, AppConfig.root_url в production окружении будет отличаться от development.

Permalink | Leave a comment  »

Вызов метода класса из C

Предположим у нас есть следующий класс:

1
2
3
4
5
6
7
8
9
module Foo
  class Bar
    def self.baz
      puts 'In Foo::Bar'
    end
  end
end
 
>> Foo::Bar.baz # => In Foo::Bar

Мы хотим вызывать этот метод из C, используя Ruby API.

Для вызова любого руби метода существует функция rb_funcall:
VALUE rb_funcall( VALUE recv, ID id, int argc, ... ) – Вызывает метод, переданный по id на объекте recv, с указанным количеством аргументов argc и самими аргументами (если таковые есть).

Для получения id по имени чего-либо (метод, имя класса, etc) используется функция rb_internID rb_intern(const char *name).

Так как мы хотим вызвать метод класса, то нам нужен объект этого класса. Получить его мы можем, используя функцию rb_const_getVALUE rb_const_get(VALUE obj, ID id).

Итак, используя вышеперечисленное, пробуем:

1
2
VALUE object_klass = rb_const_get(rb_cObject, rb_intern("Foo::Bar"));
rb_funcall(object_klass, rb_intern("baz"), 0);

Упс. Код не просто не работает, а сообщает нам о том, что не может найти "Foo::Bar". Все дело в том, что функция rb_intern не парсит переданную строку на наличие символов "::", поэтому каждый раз придется создавать иерархию вручную:

1
2
3
VALUE module_klass = rb_const_get(rb_cObject, rb_intern("Foo"));
VALUE object_klass = rb_const_get(module_klass, rb_intern("Bar"));
rb_funcall(object_klass, rb_intern("baz"), 0);

Permalink | Leave a comment  »

Метод ловушек для избежания капчи

Submitting a patch to the Open Source project: composite_primary_keys

Not so far ago I have found a weird bug in the Open Source Ruby gem called composite_primary_keys, occurred when you specify :primary_key option for has_one or has_many association. There are two ways to get it fixed: submit an issue and wait till someone will work out this problem or fix it by yourself and [...]

Проблемы с locale на базовой системе

На одном из VPS, предоставляющих базовый образ системы (в данном случае это была Ubuntu 9.04), столкнулся с тем, что на каждый вызов apt'а или dpkg получал вот такой прекрасный выхлоп:

perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
  LANGUAGE = (unset),
  LC_ALL = (unset),
  LANG = "en_US.UTF-8"
are supported and installed on your system.
Вылечилось просто:
$ sudo locale-gen en_US.UTF-8
$ sudo dpkg-reconfigure locales

Permalink | Leave a comment  »

Проблемы с locale на базовой системе

Обезвреживаем одинарные кавычки в Bash

Обезвреживаем одинарные кавычки в Bash

Гудбай Америка

Пол Грэмм о стартапах

следующая страница »