fast_gettext 0.4.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|