123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362 |
- # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
- class Translation < ApplicationModel
- before_create :set_initial
- after_create :cache_clear
- after_update :cache_clear
- after_destroy :cache_clear
- =begin
- sync translations from local if exists, otherwise from online
- all:
- Translation.sync
- Translation.sync(locale) # e. g. 'en-us' or 'de-de'
- =end
- def self.sync(dedicated_locale = nil)
- return true if load_from_file(dedicated_locale)
- load
- end
- =begin
- load translations from online
- all:
- Translation.load
- dedicated:
- Translation.load(locale) # e. g. 'en-us' or 'de-de'
- =end
- def self.load(dedicated_locale = nil)
- locals_to_sync(dedicated_locale).each { |locale|
- fetch(locale)
- load_from_file(locale)
- }
- true
- end
- =begin
- push translations to online
- Translation.push(locale)
- =end
- def self.push(locale)
- # only push changed translations
- translations = Translation.where(locale: locale)
- translations_to_push = []
- translations.each { |translation|
- if translation.target != translation.target_initial
- translations_to_push.push translation
- end
- }
- return true if translations_to_push.empty?
- url = 'https://i18n.zammad.com/api/v1/translations/thanks_for_your_support'
- translator_key = Setting.get('translator_key')
- result = UserAgent.post(
- url,
- {
- locale: locale,
- translations: translations_to_push,
- fqdn: Setting.get('fqdn'),
- translator_key: translator_key,
- },
- {
- json: true,
- open_timeout: 6,
- read_timeout: 16,
- }
- )
- raise "Can't push translations to #{url}: #{result.error}" if !result.success?
- # set new translator_key if given
- if result.data['translator_key']
- translator_key = Setting.set('translator_key', result.data['translator_key'])
- end
- true
- end
- =begin
- reset translations to origin
- Translation.reset(locale)
- =end
- def self.reset(locale)
- # only push changed translations
- translations = Translation.where(locale: locale)
- translations.each { |translation|
- if !translation.target_initial || translation.target_initial.empty?
- translation.destroy
- elsif translation.target != translation.target_initial
- translation.target = translation.target_initial
- translation.save
- end
- }
- true
- end
- =begin
- get list of translations
- list = Translation.lang('de-de')
- =end
- def self.lang(locale, admin = false)
- # use cache if not admin page is requested
- if !admin
- data = cache_get(locale)
- return data if data
- end
- # show total translations as reference count
- data = {
- 'total' => Translation.where(locale: 'de-de').count,
- }
- list = []
- translations = if admin
- Translation.where(locale: locale.downcase).order(:source)
- else
- Translation.where(locale: locale.downcase).where.not(target: '').order(:source)
- end
- translations.each { |item|
- translation_item = []
- translation_item = if admin
- [
- item.id,
- item.source,
- item.target,
- item.target_initial,
- item.format,
- ]
- else
- [
- item.id,
- item.source,
- item.target,
- item.format,
- ]
- end
- list.push translation_item
- }
- # add presorted on top
- presorted_list = []
- %w(yes no or Year Years Month Months Day Days Hour Hours Minute Minutes Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec January February March April May June July August September October November December Mon Tue Wed Thu Fri Sat Sun Monday Tuesday Wednesday Thursday Friday Saturday Sunday).each { |presort|
- list.each { |item|
- next if item[1] != presort
- presorted_list.push item
- list.delete item
- #list.unshift presort
- }
- }
- data['list'] = presorted_list.concat list
- # set cache
- if !admin
- cache_set(locale, data)
- end
- data
- end
- =begin
- translate strings in ruby context, e. g. for notifications
- translated = Translation.translate('de-de', 'New')
- =end
- def self.translate(locale, string)
- # translate string
- records = Translation.where(locale: locale, source: string)
- records.each { |record|
- return record.target if record.source == string
- }
- # fallback lookup in en
- records = Translation.where(locale: 'en', source: string)
- records.each { |record|
- return record.target if record.source == string
- }
- string
- end
- =begin
- load locales from local
- all:
- Translation.load_from_file
- or
- Translation.load_from_file(locale) # e. g. 'en-us' or 'de-de'
- =end
- def self.load_from_file(dedicated_locale = nil)
- version = Version.get
- directory = Rails.root.join('config/translations')
- locals_to_sync(dedicated_locale).each { |locale|
- file = Rails.root.join("#{directory}/#{locale}-#{version}.yml")
- return false if !File.exist?(file)
- data = YAML.load_file(file)
- to_database(locale, data)
- }
- true
- end
- =begin
- fetch translation from remote and store them in local file system
- all:
- Translation.fetch
- or
- Translation.fetch(locale) # e. g. 'en-us' or 'de-de'
- =end
- def self.fetch(dedicated_locale = nil)
- version = Version.get
- locals_to_sync(dedicated_locale).each { |locale|
- url = "https://i18n.zammad.com/api/v1/translations/#{locale}"
- if !UserInfo.current_user_id
- UserInfo.current_user_id = 1
- end
- result = UserAgent.get(
- url,
- {
- version: version,
- },
- {
- json: true,
- open_timeout: 8,
- read_timeout: 24,
- }
- )
- raise "Can't load translations from #{url}: #{result.error}" if !result.success?
- directory = Rails.root.join('config/translations')
- if !File.directory?(directory)
- Dir.mkdir(directory, 0o755)
- end
- file = Rails.root.join("#{directory}/#{locale}-#{version}.yml")
- File.open(file, 'w') do |out|
- YAML.dump(result.data, out)
- end
- }
- true
- end
- private_class_method def self.to_database(locale, data)
- translations = Translation.where(locale: locale).all
- ActiveRecord::Base.transaction do
- data.each { |translation_raw|
- # handle case insensitive sql
- translation = nil
- translations.each { |item|
- next if item.format != translation_raw['format']
- next if item.source != translation_raw['source']
- translation = item
- break
- }
- if translation
- # verify if update is needed
- update_needed = false
- translation_raw.each { |key, _value|
- # if translation target has changes
- next unless translation_raw[key] != translation.target
- # do not update translations which are already changed by user
- if translation.target == translation.target_initial
- update_needed = true
- break
- end
- }
- if update_needed
- translation.update_attributes(translation_raw.symbolize_keys!)
- translation.save
- end
- else
- if !UserInfo.current_user_id
- translation_raw['updated_by_id'] = 1
- translation_raw['created_by_id'] = 1
- end
- Translation.create(translation_raw.symbolize_keys!)
- end
- }
- end
- end
- private_class_method def self.locals_to_sync(dedicated_locale = nil)
- locales_list = []
- if !dedicated_locale
- locales = Locale.to_sync
- locales.each { |locale|
- locales_list.push locale.locale
- }
- else
- locales_list = [dedicated_locale]
- end
- locales_list
- end
- private
- def set_initial
- return if target_initial
- return if target_initial == ''
- self.target_initial = target
- end
- def cache_clear
- Cache.delete('TranslationMapOnlyContent::' + locale.downcase)
- end
- def self.cache_set(locale, data)
- Cache.write('TranslationMapOnlyContent::' + locale.downcase, data)
- end
- private_class_method :cache_set
- def self.cache_get(locale)
- Cache.get('TranslationMapOnlyContent::' + locale.downcase)
- end
- private_class_method :cache_get
- end
|