# Copyright (c) 2005-2006 David Barri require 'yaml' require 'gloc-internal' require 'gloc-helpers' module GLoc UTF_8= 'utf-8' SHIFT_JIS= 'sjis' EUC_JP= 'euc-jp' # This module will be included in both instances and classes of GLoc includees. # It is also included as class methods in the GLoc module itself. module InstanceMethods include Helpers # Returns a localized string. def l(symbol, *arguments) return GLoc._l(symbol,current_language,*arguments) end # Returns a localized string in a specified language. # This does not effect current_language. def ll(lang, symbol, *arguments) return GLoc._l(symbol,lang.to_sym,*arguments) end # Returns a localized string if the argument is a Symbol, else just returns the argument. def ltry(possible_key) possible_key.is_a?(Symbol) ? l(possible_key) : possible_key end # Uses the default GLoc rule to return a localized string. # See lwr_() for more info. def lwr(symbol, *arguments) lwr_(:default, symbol, *arguments) end # Uses a rule to return a localized string. # A rule is a function that uses specified arguments to return a localization key prefix. # The prefix is appended to the localization key originally specified, to create a new key which # is then used to lookup a localized string. def lwr_(rule, symbol, *arguments) GLoc._l("#{symbol}#{GLoc::_l_rule(rule,current_language).call(*arguments)}",current_language,*arguments) end # Returns true if a localized string with the specified key exists. def l_has_string?(symbol) return GLoc._l_has_string?(symbol,current_language) end # Sets the current language for this instance/class. # Setting the language of a class effects all instances unless the instance has its own language defined. def set_language(language) @gloc_language= language.nil? ? nil : language.to_sym end # Sets the current language if the language passed is a valid language. # If the language was valid, this method returns true else it will return false. # Note that nil is not a valid language. # See set_language(language) for more info. def set_language_if_valid(language) if GLoc.valid_language?(language) set_language(language) true else false end end end #--------------------------------------------------------------------------- # Instance include ::GLoc::InstanceMethods # Returns the instance-level current language, or if not set, returns the class-level current language. def current_language @gloc_language || self.class.current_language end #--------------------------------------------------------------------------- # Class # All classes/modules that include GLoc will also gain these class methods. # Notice that the GLoc::InstanceMethods module is also included. module ClassMethods include ::GLoc::InstanceMethods # Returns the current language, or if not set, returns the GLoc current language. def current_language @gloc_language || GLoc.current_language end end def self.included(target) #:nodoc: super class << target include ::GLoc::ClassMethods end end #--------------------------------------------------------------------------- # GLoc module class << self include ::GLoc::InstanceMethods # Returns the default language def current_language GLoc::CONFIG[:default_language] end # Adds a collection of localized strings to the in-memory string store. def add_localized_strings(lang, symbol_hash, override=true, strings_charset=nil) _verbose_msg {"Adding #{symbol_hash.size} #{lang} strings."} _add_localized_strings(lang, symbol_hash, override, strings_charset) _verbose_msg :stats end # Creates a backup of the internal state of GLoc (ie. strings, langs, rules, config) # and optionally clears everything. def backup_state(clear=false) s= _get_internal_state_vars.map{|o| o.clone} _get_internal_state_vars.each{|o| o.clear} if clear s end # Removes all localized strings from memory, either of a certain language (or languages), # or entirely. def clear_strings(*languages) if languages.empty? _verbose_msg {"Clearing all strings"} LOCALIZED_STRINGS.clear LOWERCASE_LANGUAGES.clear else languages.each {|l| _verbose_msg {"Clearing :#{l} strings"} l= l.to_sym LOCALIZED_STRINGS.delete l LOWERCASE_LANGUAGES.each_pair {|k,v| LOWERCASE_LANGUAGES.delete k if v == l} } end end alias :_clear_strings :clear_strings # Removes all localized strings from memory, except for those of certain specified languages. def clear_strings_except(*languages) clear= (LOCALIZED_STRINGS.keys - languages) _clear_strings(*clear) unless clear.empty? end # Returns the charset used to store localized strings in memory. def get_charset(lang) CONFIG[:internal_charset_per_lang][lang] || CONFIG[:internal_charset] end # Returns a GLoc configuration value. def get_config(key) CONFIG[key] end # Loads the localized strings that are included in the GLoc library. def load_gloc_default_localized_strings(override=false) GLoc.load_localized_strings "#{File.dirname(__FILE__)}/../lang", override end # Loads localized strings from all yml files in the specifed directory. def load_localized_strings(dir=nil, override=true) _charset_required _get_lang_file_list(dir).each {|filename| # Load file raw_hash = YAML::load(File.read(filename)) raw_hash={} unless raw_hash.kind_of?(Hash) filename =~ /([^\/\\]+)\.ya?ml$/ lang = $1.to_sym file_charset = raw_hash['file_charset'] || UTF_8 # Convert string keys to symbols dest_charset= get_charset(lang) _verbose_msg {"Reading file #{filename} [charset: #{file_charset} --> #{dest_charset}]"} symbol_hash = {} Iconv.open(dest_charset, file_charset) do |i| raw_hash.each {|key, value| symbol_hash[key.to_sym] = i.iconv(value) } end # Add strings to repos _add_localized_strings(lang, symbol_hash, override) } _verbose_msg :stats end # Restores a backup of GLoc's internal state that was made with backup_state. def restore_state(state) _get_internal_state_vars.each do |o| o.clear o.send o.respond_to?(:merge!) ? :merge! : :concat, state.shift end end # Sets the charset used to internally store localized strings. # You can set the charset to use for a specific language or languages, # or if none are specified the charset for ALL localized strings will be set. def set_charset(new_charset, *langs) CONFIG[:internal_charset_per_lang] ||= {} # Convert symbol shortcuts if new_charset.is_a?(Symbol) new_charset= case new_charset when :utf8, :utf_8 then UTF_8 when :sjis, :shift_jis, :shiftjis then SHIFT_JIS when :eucjp, :euc_jp then EUC_JP else new_charset.to_s end end # Convert existing strings (langs.empty? ? LOCALIZED_STRINGS.keys : langs).each do |lang| cur_charset= get_charset(lang) if cur_charset && new_charset != cur_charset _verbose_msg {"Converting :#{lang} strings from #{cur_charset} to #{new_charset}"} Iconv.open(new_charset, cur_charset) do |i| bundle= LOCALIZED_STRINGS[lang] bundle.each_pair {|k,v| bundle[k]= i.iconv(v)} end end end # Set new charset value if langs.empty? _verbose_msg {"Setting GLoc charset for all languages to #{new_charset}"} CONFIG[:internal_charset]= new_charset CONFIG[:internal_charset_per_lang].clear else langs.each do |lang| _verbose_msg {"Setting GLoc charset for :#{lang} strings to #{new_charset}"} CONFIG[:internal_charset_per_lang][lang]= new_charset end end end # Sets GLoc configuration values. def set_config(hash) CONFIG.merge! hash end # Sets the $KCODE global variable according to a specified charset, or else the # current default charset for the default language. def set_kcode(charset=nil) _charset_required charset ||= get_charset(current_language) $KCODE= case charset when UTF_8 then 'u' when SHIFT_JIS then 's' when EUC_JP then 'e' else 'n' end _verbose_msg {"$KCODE set to #{$KCODE}"} end # Tries to find a valid language that is similar to the argument passed. # Eg. :en, :en_au, :EN_US are all similar languages. # Returns nil if no similar languages are found. def similar_language(lang) return nil if lang.nil? return lang.to_sym if valid_language?(lang) # Check lowercase without dashes lang= lang.to_s.downcase.gsub('-','_') return LOWERCASE_LANGUAGES[lang] if LOWERCASE_LANGUAGES.has_key?(lang) # Check without dialect if lang.to_s =~ /^([a-z]+?)[^a-z].*/ lang= $1 return LOWERCASE_LANGUAGES[lang] if LOWERCASE_LANGUAGES.has_key?(lang) end # Check other dialects lang= "#{lang}_" LOWERCASE_LANGUAGES.keys.each {|k| return LOWERCASE_LANGUAGES[k] if k.starts_with?(lang)} # Nothing found nil end # Returns an array of (currently) valid languages (ie. languages for which localized data exists). def valid_languages LOCALIZED_STRINGS.keys end # Returns true if there are any localized strings for a specified language. # Note that although set_langauge nil is perfectly valid, nil is not a valid language. def valid_language?(language) LOCALIZED_STRINGS.has_key? language.to_sym rescue false end end end