fast_gettext 0.4.16
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/CHANGELOG +6 -0
- data/README.markdown +181 -0
- data/Rakefile +42 -0
- data/VERSION +1 -0
- data/benchmark/base.rb +42 -0
- data/benchmark/baseline.rb +5 -0
- data/benchmark/fast_gettext.rb +18 -0
- data/benchmark/i18n_simple.rb +7 -0
- data/benchmark/ideal.rb +22 -0
- data/benchmark/locale/de.yml +127 -0
- data/benchmark/locale/de/LC_MESSAGES/large.mo +0 -0
- data/benchmark/misc/threadsave.rb +21 -0
- data/benchmark/namespace/fast_gettext.rb +15 -0
- data/benchmark/namespace/original.rb +14 -0
- data/benchmark/original.rb +15 -0
- data/examples/db/migration.rb +22 -0
- data/examples/missing_translation_logger.rb +13 -0
- data/fast_gettext.gemspec +114 -0
- data/lib/fast_gettext.rb +30 -0
- data/lib/fast_gettext/mo_file.rb +67 -0
- data/lib/fast_gettext/po_file.rb +14 -0
- data/lib/fast_gettext/storage.rb +188 -0
- data/lib/fast_gettext/translation.rb +53 -0
- data/lib/fast_gettext/translation_repository.rb +15 -0
- data/lib/fast_gettext/translation_repository/base.rb +49 -0
- data/lib/fast_gettext/translation_repository/chain.rb +43 -0
- data/lib/fast_gettext/translation_repository/db.rb +57 -0
- data/lib/fast_gettext/translation_repository/db_models/translation_key.rb +26 -0
- data/lib/fast_gettext/translation_repository/db_models/translation_text.rb +9 -0
- data/lib/fast_gettext/translation_repository/logger.rb +27 -0
- data/lib/fast_gettext/translation_repository/mo.rb +35 -0
- data/lib/fast_gettext/translation_repository/po.rb +18 -0
- data/spec/aa_unconfigued_spec.rb +21 -0
- data/spec/fast_gettext/mo_file_spec.rb +36 -0
- data/spec/fast_gettext/storage_spec.rb +309 -0
- data/spec/fast_gettext/translation_repository/base_spec.rb +21 -0
- data/spec/fast_gettext/translation_repository/chain_spec.rb +82 -0
- data/spec/fast_gettext/translation_repository/db_spec.rb +71 -0
- data/spec/fast_gettext/translation_repository/logger_spec.rb +41 -0
- data/spec/fast_gettext/translation_repository/mo_spec.rb +31 -0
- data/spec/fast_gettext/translation_repository/po_spec.rb +31 -0
- data/spec/fast_gettext/translation_spec.rb +152 -0
- data/spec/fast_gettext_spec.rb +44 -0
- data/spec/locale/de/LC_MESSAGES/test.mo +0 -0
- data/spec/locale/de/test.po +61 -0
- data/spec/locale/en/LC_MESSAGES/plural_test.mo +0 -0
- data/spec/locale/en/LC_MESSAGES/test.mo +0 -0
- data/spec/locale/en/plural_test.po +20 -0
- data/spec/locale/en/test.po +59 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/vendor/fake_load_path/iconv.rb +2 -0
- data/spec/vendor/iconv_spec.rb +27 -0
- data/spec/vendor/string_spec.rb +67 -0
- data/vendor/README.rdoc +236 -0
- data/vendor/empty.mo +0 -0
- data/vendor/iconv.rb +107 -0
- data/vendor/mofile.rb +296 -0
- data/vendor/poparser.rb +331 -0
- data/vendor/string.rb +58 -0
- metadata +130 -0
Binary file
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
BASELINE = 0
|
3
|
+
def test
|
4
|
+
result = Benchmark.measure {1_000_000.times{ yield }}
|
5
|
+
result.to_s.strip.split(' ').first.to_f - BASELINE
|
6
|
+
end
|
7
|
+
|
8
|
+
BASELINE = (test{})
|
9
|
+
Thread.current[:library_name]={}
|
10
|
+
other = "x"
|
11
|
+
puts "Ruby #{VERSION}"
|
12
|
+
|
13
|
+
puts "generic:"
|
14
|
+
puts " Symbol: #{test{Thread.current[:library_name][:just_a_symbol]}}s"
|
15
|
+
puts " String concat: #{test{Thread.current["xxxxxx"<<other.to_s]}}s"
|
16
|
+
puts " String add: #{test{Thread.current["xxxxxx"+other.to_s]}}s"
|
17
|
+
puts " String insert: #{test{Thread.current["xxxxxx#{other}"]}}s"
|
18
|
+
|
19
|
+
puts "single:"
|
20
|
+
puts " Symbol: #{test{Thread.current[:long_unique_symbol]}}s"
|
21
|
+
puts " String: #{test{Thread.current["xxxxxx"]}}s"
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#Iconv will not be defined, unless it is found -> normalize test results for users that have Iconv/those who do not have it
|
2
|
+
begin;require 'iconv';rescue;LoadError;end
|
3
|
+
initial = methods.count + Module.constants.count
|
4
|
+
|
5
|
+
#FastGettext
|
6
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__),'..','..','lib')
|
7
|
+
require 'fast_gettext'
|
8
|
+
FastGettext.locale = 'de'
|
9
|
+
FastGettext.add_text_domain 'test', :path=>'spec/locale'
|
10
|
+
FastGettext.text_domain = 'test'
|
11
|
+
include FastGettext::Translation
|
12
|
+
raise unless _('car')=='Auto'
|
13
|
+
|
14
|
+
puts "FastGettext"
|
15
|
+
puts methods.count + Module.constants.count - initial
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
initial = methods.count + Module.constants.count
|
3
|
+
|
4
|
+
#GetText
|
5
|
+
gem 'gettext', '>=2.0.0'
|
6
|
+
require 'gettext'
|
7
|
+
GetText.locale = 'de'
|
8
|
+
GetText.bindtextdomain('test',:path=>'spec/locale')
|
9
|
+
include GetText
|
10
|
+
raise unless _('car') == 'Auto'
|
11
|
+
|
12
|
+
|
13
|
+
puts "GetText"
|
14
|
+
puts methods.count + Module.constants.count - initial
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'benchmark/base'
|
2
|
+
|
3
|
+
gem 'gettext', '>=2.0.0'
|
4
|
+
require 'gettext'
|
5
|
+
include GetText
|
6
|
+
|
7
|
+
self.locale = 'de'
|
8
|
+
|
9
|
+
puts "GetText #{GetText::VERSION}:"
|
10
|
+
bindtextdomain('test',:path=>locale_folder('test'))
|
11
|
+
results_test{_('car') == 'Auto'}
|
12
|
+
|
13
|
+
#i cannot add the large file, since its an internal applications mo file
|
14
|
+
bindtextdomain('large',:path=>locale_folder('large'))
|
15
|
+
results_large
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class CreateTranslationTables < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :translation_keys do |t|
|
4
|
+
t.string :key, :unique=>true, :null=>false
|
5
|
+
t.timestamps
|
6
|
+
end
|
7
|
+
add_index :translation_keys, :key #I am not sure if this helps....
|
8
|
+
|
9
|
+
create_table :translation_texts do |t|
|
10
|
+
t.text :text
|
11
|
+
t.string :locale
|
12
|
+
t.integer :translation_key_id, :null=>false
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
add_index :translation_texts, :translation_key_id
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.down
|
19
|
+
drop_table :translation_keys
|
20
|
+
drop_table :translation_texts
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class MissingTranslationLogger
|
2
|
+
def call(unfound)
|
3
|
+
logger.warn "#{FastGettext.locale}: #{unfound}" unless FastGettext.locale == 'en'
|
4
|
+
end
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def logger
|
9
|
+
return @logger if @logger
|
10
|
+
require 'logger'
|
11
|
+
@logger = Logger.new("log/unfound_translations", 2, 5*(1024**2))#max 2x 5mb logfile
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{fast_gettext}
|
8
|
+
s.version = "0.4.16"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Michael Grosser"]
|
12
|
+
s.date = %q{2009-10-16}
|
13
|
+
s.email = %q{grosser.michael@gmail.com}
|
14
|
+
s.extra_rdoc_files = [
|
15
|
+
"README.markdown"
|
16
|
+
]
|
17
|
+
s.files = [
|
18
|
+
".gitignore",
|
19
|
+
"CHANGELOG",
|
20
|
+
"README.markdown",
|
21
|
+
"Rakefile",
|
22
|
+
"VERSION",
|
23
|
+
"benchmark/base.rb",
|
24
|
+
"benchmark/baseline.rb",
|
25
|
+
"benchmark/fast_gettext.rb",
|
26
|
+
"benchmark/i18n_simple.rb",
|
27
|
+
"benchmark/ideal.rb",
|
28
|
+
"benchmark/locale/de.yml",
|
29
|
+
"benchmark/locale/de/LC_MESSAGES/large.mo",
|
30
|
+
"benchmark/misc/threadsave.rb",
|
31
|
+
"benchmark/namespace/fast_gettext.rb",
|
32
|
+
"benchmark/namespace/original.rb",
|
33
|
+
"benchmark/original.rb",
|
34
|
+
"examples/db/migration.rb",
|
35
|
+
"examples/missing_translation_logger.rb",
|
36
|
+
"fast_gettext.gemspec",
|
37
|
+
"lib/fast_gettext.rb",
|
38
|
+
"lib/fast_gettext/mo_file.rb",
|
39
|
+
"lib/fast_gettext/po_file.rb",
|
40
|
+
"lib/fast_gettext/storage.rb",
|
41
|
+
"lib/fast_gettext/translation.rb",
|
42
|
+
"lib/fast_gettext/translation_repository.rb",
|
43
|
+
"lib/fast_gettext/translation_repository/base.rb",
|
44
|
+
"lib/fast_gettext/translation_repository/chain.rb",
|
45
|
+
"lib/fast_gettext/translation_repository/db.rb",
|
46
|
+
"lib/fast_gettext/translation_repository/db_models/translation_key.rb",
|
47
|
+
"lib/fast_gettext/translation_repository/db_models/translation_text.rb",
|
48
|
+
"lib/fast_gettext/translation_repository/logger.rb",
|
49
|
+
"lib/fast_gettext/translation_repository/mo.rb",
|
50
|
+
"lib/fast_gettext/translation_repository/po.rb",
|
51
|
+
"spec/aa_unconfigued_spec.rb",
|
52
|
+
"spec/fast_gettext/mo_file_spec.rb",
|
53
|
+
"spec/fast_gettext/storage_spec.rb",
|
54
|
+
"spec/fast_gettext/translation_repository/base_spec.rb",
|
55
|
+
"spec/fast_gettext/translation_repository/chain_spec.rb",
|
56
|
+
"spec/fast_gettext/translation_repository/db_spec.rb",
|
57
|
+
"spec/fast_gettext/translation_repository/logger_spec.rb",
|
58
|
+
"spec/fast_gettext/translation_repository/mo_spec.rb",
|
59
|
+
"spec/fast_gettext/translation_repository/po_spec.rb",
|
60
|
+
"spec/fast_gettext/translation_spec.rb",
|
61
|
+
"spec/fast_gettext_spec.rb",
|
62
|
+
"spec/locale/de/LC_MESSAGES/test.mo",
|
63
|
+
"spec/locale/de/test.po",
|
64
|
+
"spec/locale/en/LC_MESSAGES/plural_test.mo",
|
65
|
+
"spec/locale/en/LC_MESSAGES/test.mo",
|
66
|
+
"spec/locale/en/plural_test.po",
|
67
|
+
"spec/locale/en/test.po",
|
68
|
+
"spec/spec_helper.rb",
|
69
|
+
"spec/vendor/fake_load_path/iconv.rb",
|
70
|
+
"spec/vendor/iconv_spec.rb",
|
71
|
+
"spec/vendor/string_spec.rb",
|
72
|
+
"vendor/README.rdoc",
|
73
|
+
"vendor/empty.mo",
|
74
|
+
"vendor/iconv.rb",
|
75
|
+
"vendor/mofile.rb",
|
76
|
+
"vendor/poparser.rb",
|
77
|
+
"vendor/string.rb"
|
78
|
+
]
|
79
|
+
s.homepage = %q{http://github.com/grosser/fast_gettext}
|
80
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
81
|
+
s.require_paths = ["lib"]
|
82
|
+
s.rubyforge_project = %q{fast-gettext}
|
83
|
+
s.rubygems_version = %q{1.3.5}
|
84
|
+
s.summary = %q{A simple, fast and threadsafe implementation of GetText}
|
85
|
+
s.test_files = [
|
86
|
+
"spec/fast_gettext_spec.rb",
|
87
|
+
"spec/spec_helper.rb",
|
88
|
+
"spec/fast_gettext/translation_spec.rb",
|
89
|
+
"spec/fast_gettext/storage_spec.rb",
|
90
|
+
"spec/fast_gettext/translation_repository/chain_spec.rb",
|
91
|
+
"spec/fast_gettext/translation_repository/logger_spec.rb",
|
92
|
+
"spec/fast_gettext/translation_repository/base_spec.rb",
|
93
|
+
"spec/fast_gettext/translation_repository/po_spec.rb",
|
94
|
+
"spec/fast_gettext/translation_repository/db_spec.rb",
|
95
|
+
"spec/fast_gettext/translation_repository/mo_spec.rb",
|
96
|
+
"spec/fast_gettext/mo_file_spec.rb",
|
97
|
+
"spec/aa_unconfigued_spec.rb",
|
98
|
+
"spec/vendor/iconv_spec.rb",
|
99
|
+
"spec/vendor/fake_load_path/iconv.rb",
|
100
|
+
"spec/vendor/string_spec.rb",
|
101
|
+
"examples/db/migration.rb",
|
102
|
+
"examples/missing_translation_logger.rb"
|
103
|
+
]
|
104
|
+
|
105
|
+
if s.respond_to? :specification_version then
|
106
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
107
|
+
s.specification_version = 3
|
108
|
+
|
109
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
110
|
+
else
|
111
|
+
end
|
112
|
+
else
|
113
|
+
end
|
114
|
+
end
|
data/lib/fast_gettext.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'fast_gettext/mo_file'
|
2
|
+
require 'fast_gettext/storage'
|
3
|
+
require 'fast_gettext/translation'
|
4
|
+
require 'fast_gettext/translation_repository'
|
5
|
+
require File.join(File.dirname(__FILE__),'..','vendor','string')
|
6
|
+
|
7
|
+
module FastGettext
|
8
|
+
include FastGettext::Storage
|
9
|
+
extend self
|
10
|
+
|
11
|
+
VERSION = File.read( File.join(File.dirname(__FILE__),'..','VERSION') ).strip
|
12
|
+
LOCALE_REX = /^[a-z]{2}$|^[a-z]{2}_[A-Z]{2}$/
|
13
|
+
NAMESPACE_SEPERATOR = '|'
|
14
|
+
|
15
|
+
# users should not include FastGettext, since this would conterminate their namespace
|
16
|
+
# rather use
|
17
|
+
# FastGettext.locale = ..
|
18
|
+
# FastGettext.text_domain = ..
|
19
|
+
# and
|
20
|
+
# include FastGettext::Translation
|
21
|
+
FastGettext::Translation.public_instance_methods.each do |method|
|
22
|
+
define_method method do |*args|
|
23
|
+
Translation.send(method,*args)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_text_domain(name,options)
|
28
|
+
translation_repositories[name] = TranslationRepository.build(name,options)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'..','..','vendor','mofile')
|
2
|
+
module FastGettext
|
3
|
+
# Responsibility:
|
4
|
+
# - abstract mo files for Mo Repository
|
5
|
+
class MoFile
|
6
|
+
PLURAL_SEPERATOR = "\000"
|
7
|
+
|
8
|
+
# file => path or FastGettext::GetText::MOFile
|
9
|
+
def initialize(file)
|
10
|
+
if file.is_a? FastGettext::GetText::MOFile
|
11
|
+
@data = file
|
12
|
+
else
|
13
|
+
@data = FastGettext::GetText::MOFile.open(file, "UTF-8")
|
14
|
+
end
|
15
|
+
make_singular_and_plural_available
|
16
|
+
end
|
17
|
+
|
18
|
+
def [](key)
|
19
|
+
@data[key]
|
20
|
+
end
|
21
|
+
|
22
|
+
#returns the plural forms or all singlgular translations that where found
|
23
|
+
def plural(*msgids)
|
24
|
+
translations = plural_translations(msgids)
|
25
|
+
return translations unless translations.empty?
|
26
|
+
msgids.map{|msgid| self[msgid] || msgid} #try to translate each id
|
27
|
+
end
|
28
|
+
|
29
|
+
def pluralisation_rule
|
30
|
+
#gettext uses 0 as default rule, which would turn off all pluralisation, very clever...
|
31
|
+
#additionally parsing fails when directly accessing po files, so this line was taken from gettext/mofile
|
32
|
+
(@data['']||'').split("\n").each do |line|
|
33
|
+
return lambda{|n|eval($2)} if /^Plural-Forms:\s*nplurals\s*\=\s*(\d*);\s*plural\s*\=\s*([^;]*)\n?/ =~ line
|
34
|
+
end
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.empty
|
39
|
+
MoFile.new(File.join(File.dirname(__FILE__),'..','..','vendor','empty.mo'))
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
#(if plural==singular, prefer singular)
|
45
|
+
def make_singular_and_plural_available
|
46
|
+
data = {}
|
47
|
+
@data.each do |key,translation|
|
48
|
+
next unless key.include? PLURAL_SEPERATOR
|
49
|
+
singular, plural = split_plurals(key)
|
50
|
+
translation = split_plurals(translation)
|
51
|
+
data[singular] ||= translation[0]
|
52
|
+
data[plural] ||= translation[1]
|
53
|
+
end
|
54
|
+
@data.merge!(data){|key,old,new| old}
|
55
|
+
end
|
56
|
+
|
57
|
+
def split_plurals(singular_plural)
|
58
|
+
singular_plural.split(PLURAL_SEPERATOR)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Car, Cars => [Auto,Autos] or []
|
62
|
+
def plural_translations(msgids)
|
63
|
+
plurals = self[msgids*PLURAL_SEPERATOR]
|
64
|
+
if plurals then split_plurals(plurals) else [] end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'fast_gettext/mo_file'
|
2
|
+
module FastGettext
|
3
|
+
# Responsibility:
|
4
|
+
# - abstract po files for Po Repository
|
5
|
+
# TODO refactor...
|
6
|
+
class PoFile
|
7
|
+
def self.to_mo_file(file)
|
8
|
+
require File.join(File.dirname(__FILE__),'..','..','vendor','poparser')
|
9
|
+
mo_file = FastGettext::GetText::MOFile.new
|
10
|
+
FastGettext::GetText::PoParser.new.parse(File.read(file),mo_file)
|
11
|
+
MoFile.new(mo_file)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
module FastGettext
|
2
|
+
# Responsibility:
|
3
|
+
# - store data threadsave
|
4
|
+
# - provide error messages when repositories are unconfigured
|
5
|
+
# - accept/reject locales that are set by the user
|
6
|
+
module Storage
|
7
|
+
class NoTextDomainConfigured < RuntimeError
|
8
|
+
def to_s
|
9
|
+
"Current textdomain (#{FastGettext.text_domain.inspect}) was not added, use FastGettext.add_text_domain !"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
[:available_locales, :_locale, :text_domain, :pluralisation_rule].each do |method_name|
|
14
|
+
key = "fast_gettext_#{method_name}".to_sym
|
15
|
+
define_method method_name do
|
16
|
+
Thread.current[key]
|
17
|
+
end
|
18
|
+
|
19
|
+
define_method "#{method_name}=" do |value|
|
20
|
+
Thread.current[key]=value
|
21
|
+
update_current_cache
|
22
|
+
end
|
23
|
+
end
|
24
|
+
private :_locale, :_locale=
|
25
|
+
|
26
|
+
|
27
|
+
def available_locales
|
28
|
+
Thread.current[:fast_gettext_available_locales] || default_available_locales
|
29
|
+
end
|
30
|
+
|
31
|
+
# == cattr_accessor :default_available_locales
|
32
|
+
@@default_available_locales = nil
|
33
|
+
def default_available_locales=(avail_locales)
|
34
|
+
@@default_available_locales = avail_locales
|
35
|
+
update_current_cache
|
36
|
+
end
|
37
|
+
|
38
|
+
def default_available_locales
|
39
|
+
@@default_available_locales
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
def text_domain
|
44
|
+
Thread.current[:fast_gettext_text_domain] || default_text_domain
|
45
|
+
end
|
46
|
+
|
47
|
+
# == cattr_accessor :default_text_domain
|
48
|
+
@@default_text_domain = nil
|
49
|
+
def default_text_domain=(domain)
|
50
|
+
@@default_text_domain = domain
|
51
|
+
update_current_cache
|
52
|
+
end
|
53
|
+
|
54
|
+
def default_text_domain
|
55
|
+
@@default_text_domain
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
def pluralisation_rule
|
60
|
+
Thread.current[:fast_gettext_pluralisation_rule] || current_repository.pluralisation_rule || lambda{|i| i!=1}
|
61
|
+
end
|
62
|
+
|
63
|
+
def current_cache
|
64
|
+
Thread.current[:fast_gettext_current_cache] || {}
|
65
|
+
end
|
66
|
+
|
67
|
+
def current_cache=(cache)
|
68
|
+
Thread.current[:fast_gettext_current_cache] = cache
|
69
|
+
end
|
70
|
+
|
71
|
+
#global, since re-parsing whole folders takes too much time...
|
72
|
+
@@translation_repositories={}
|
73
|
+
def translation_repositories
|
74
|
+
@@translation_repositories
|
75
|
+
end
|
76
|
+
|
77
|
+
# used to speedup simple translations, does not work for pluralisation
|
78
|
+
# caches[text_domain][locale][key]=translation
|
79
|
+
@@caches={}
|
80
|
+
def caches
|
81
|
+
@@caches
|
82
|
+
end
|
83
|
+
|
84
|
+
def current_repository
|
85
|
+
translation_repositories[text_domain] || raise(NoTextDomainConfigured)
|
86
|
+
end
|
87
|
+
|
88
|
+
def key_exist?(key)
|
89
|
+
!!(cached_find key)
|
90
|
+
end
|
91
|
+
|
92
|
+
def cached_find(key)
|
93
|
+
translation = current_cache[key]
|
94
|
+
return translation if translation or translation == false #found or was not found before
|
95
|
+
current_cache[key] = current_repository[key] || false
|
96
|
+
end
|
97
|
+
|
98
|
+
def cached_plural_find(*keys)
|
99
|
+
key = '||||' + keys * '||||'
|
100
|
+
translation = current_cache[key]
|
101
|
+
return translation if translation or translation == false #found or was not found before
|
102
|
+
current_cache[key] = current_repository.plural(*keys) || false
|
103
|
+
end
|
104
|
+
|
105
|
+
def locale
|
106
|
+
_locale || ( default_locale || (available_locales||[]).first || 'en' )
|
107
|
+
end
|
108
|
+
|
109
|
+
def locale=(new_locale)
|
110
|
+
new_locale = best_locale_in(new_locale)
|
111
|
+
self._locale = new_locale if new_locale
|
112
|
+
end
|
113
|
+
|
114
|
+
# for chaining: puts set_locale('xx') == 'xx' ? 'applied' : 'rejected'
|
115
|
+
# returns the current locale, not the one that was supplied
|
116
|
+
# like locale=(), whoes behavior cannot be changed
|
117
|
+
def set_locale(new_locale)
|
118
|
+
self.locale = new_locale
|
119
|
+
locale
|
120
|
+
end
|
121
|
+
|
122
|
+
@@default_locale = nil
|
123
|
+
def default_locale=(new_locale)
|
124
|
+
@@default_locale = best_locale_in(new_locale)
|
125
|
+
update_current_cache
|
126
|
+
end
|
127
|
+
|
128
|
+
def default_locale
|
129
|
+
@@default_locale
|
130
|
+
end
|
131
|
+
|
132
|
+
#Opera: de-DE,de;q=0.9,en;q=0.8
|
133
|
+
#Firefox de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
|
134
|
+
#IE6/7 de
|
135
|
+
#nil if nothing matches
|
136
|
+
def best_locale_in(locales)
|
137
|
+
formatted_sorted_locales(locales).each do |candidate|
|
138
|
+
return candidate if not available_locales
|
139
|
+
return candidate if available_locales.include?(candidate)
|
140
|
+
return candidate[0..1] if available_locales.include?(candidate[0..1])#available locales include a langauge
|
141
|
+
end
|
142
|
+
return nil#nothing found im sorry :P
|
143
|
+
end
|
144
|
+
|
145
|
+
#turn off translation if none was defined to disable all resulting errors
|
146
|
+
def silence_errors
|
147
|
+
require 'fast_gettext/translation_repository/base'
|
148
|
+
translation_repositories[text_domain] = TranslationRepository::Base.new('x')
|
149
|
+
end
|
150
|
+
|
151
|
+
private
|
152
|
+
|
153
|
+
# de-de,DE-CH;q=0.9 -> ['de_DE','de_CH']
|
154
|
+
def formatted_sorted_locales(locales)
|
155
|
+
found = weighted_locales(locales).reject{|x|x.empty?}.sort_by{|l|l.last}.reverse #sort them by weight which is the last entry
|
156
|
+
found.flatten.map{|l| format_locale(l)}
|
157
|
+
end
|
158
|
+
|
159
|
+
#split the locale and seperate it into different languages
|
160
|
+
#de-de,de;q=0.9,en;q=0.8 => [['de-de','de','0.5'], ['en','0.8']]
|
161
|
+
def weighted_locales(locales)
|
162
|
+
locales = locales.to_s.gsub(/\s/,'')
|
163
|
+
found = [[]]
|
164
|
+
locales.split(',').each do |part|
|
165
|
+
if part =~ /;q=/ #contains language and weight ?
|
166
|
+
found.last << part.split(/;q=/)
|
167
|
+
found.last.flatten!
|
168
|
+
found << []
|
169
|
+
else
|
170
|
+
found.last << part
|
171
|
+
end
|
172
|
+
end
|
173
|
+
found
|
174
|
+
end
|
175
|
+
|
176
|
+
#de-de -> de_DE
|
177
|
+
def format_locale(locale)
|
178
|
+
locale.sub(/^([a-zA-Z]{2})[-_]([a-zA-Z]{2})$/){$1.downcase+'_'+$2.upcase}
|
179
|
+
end
|
180
|
+
|
181
|
+
def update_current_cache
|
182
|
+
caches[text_domain] ||= {}
|
183
|
+
caches[text_domain][locale] ||= {}
|
184
|
+
caches[text_domain][locale][""] = false #ignore gettext meta key when translating
|
185
|
+
self.current_cache = caches[text_domain][locale]
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|