2022-01-01 13:38:12 +00:00
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
2021-06-01 12:20:20 +00:00
2012-09-20 12:08:02 +00:00
class Translation < ApplicationModel
2021-11-15 15:58:19 +00:00
include Translation :: SynchronizesFromPo
2012-05-18 14:24:00 +00:00
before_create :set_initial
2022-03-29 17:44:58 +00:00
validates :locale , presence : true
2015-04-27 06:20:52 +00:00
= begin
2015-06-28 00:16:47 +00:00
reset translations to origin
Translation . reset ( locale )
= end
def self . reset ( locale )
# only push changed translations
translations = Translation . where ( locale : locale )
2017-10-01 12:25:52 +00:00
translations . each do | translation |
2017-11-15 14:06:53 +00:00
if translation . target_initial . blank?
2015-06-28 00:16:47 +00:00
translation . destroy
elsif translation . target != translation . target_initial
translation . target = translation . target_initial
translation . save
end
2017-10-01 12:25:52 +00:00
end
2015-06-28 00:16:47 +00:00
2015-04-27 06:20:52 +00:00
true
end
= begin
get list of translations
2015-11-18 13:27:46 +00:00
list = Translation . lang ( 'de-de' )
2015-04-27 06:20:52 +00:00
= end
2015-11-18 13:27:46 +00:00
def self . lang ( locale , admin = false )
2013-08-06 14:17:30 +00:00
2015-06-28 00:16:47 +00:00
# use cache if not admin page is requested
2015-04-12 08:41:59 +00:00
if ! admin
2022-03-16 16:35:50 +00:00
data = lang_cache_get ( locale )
2015-11-18 13:27:46 +00:00
return data if data
2015-04-12 08:41:59 +00:00
end
2015-06-28 00:16:47 +00:00
2015-11-18 13:27:46 +00:00
# show total translations as reference count
data = {
'total' = > Translation . where ( locale : 'de-de' ) . count ,
}
list = [ ]
2016-01-15 17:22:57 +00:00
translations = if admin
Translation . where ( locale : locale . downcase ) . order ( :source )
else
Translation . where ( locale : locale . downcase ) . where . not ( target : '' ) . order ( :source )
end
2017-10-01 12:25:52 +00:00
translations . each do | item |
2016-01-15 17:22:57 +00:00
translation_item = if admin
[
item . id ,
item . source ,
item . target ,
item . target_initial ,
]
else
[
item . id ,
item . source ,
item . target ,
]
end
list . push translation_item
2017-10-01 12:25:52 +00:00
end
2016-03-07 01:25:52 +00:00
# add presorted on top
presorted_list = [ ]
2017-11-23 08:09:44 +00:00
%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 do | presort |
2017-10-01 12:25:52 +00:00
list . each do | item |
2016-03-07 01:25:52 +00:00
next if item [ 1 ] != presort
2018-10-09 06:17:41 +00:00
2016-03-07 01:25:52 +00:00
presorted_list . push item
list . delete item
2021-07-16 13:44:10 +00:00
# list.unshift presort
2017-10-01 12:25:52 +00:00
end
end
2016-03-07 01:25:52 +00:00
data [ 'list' ] = presorted_list . concat list
2015-11-18 13:27:46 +00:00
# set cache
if ! admin
2022-03-16 16:35:50 +00:00
lang_cache_set ( locale , data )
2013-08-06 14:17:30 +00:00
end
2013-08-06 08:18:50 +00:00
2015-06-28 00:16:47 +00:00
data
2013-08-06 08:18:50 +00:00
end
2015-04-27 06:20:52 +00:00
= begin
2021-11-15 15:58:19 +00:00
translate strings in Ruby context , e . g . for notifications
2015-04-27 06:20:52 +00:00
2015-04-27 13:06:37 +00:00
translated = Translation . translate ( 'de-de' , 'New' )
2015-04-27 06:20:52 +00:00
= end
2013-01-04 13:14:20 +00:00
def self . translate ( locale , string )
2021-11-15 15:58:19 +00:00
find_source ( locale , string ) & . target || find_source ( 'en' , string ) & . target || string
end
2013-01-04 13:14:20 +00:00
2021-11-15 15:58:19 +00:00
= begin
2013-01-04 13:14:20 +00:00
2021-11-15 15:58:19 +00:00
find a translation record for a given locale and source string . 'find_by' might not be enough ,
because it could produce wrong matches on case insensitive MySQL databases .
2013-01-04 13:14:20 +00:00
2021-11-15 15:58:19 +00:00
= end
def self . find_source ( locale , string )
# MySQL might find the wrong record with find_by with case insensitive locales, so use a direct comparison.
where ( locale : locale , source : string ) . find { | t | t . source . eql? string }
2013-01-04 13:14:20 +00:00
end
2016-12-03 19:37:37 +00:00
= begin
2019-02-10 11:01:38 +00:00
translate timestampes in ruby context , e . g . for notifications
translated = Translation . timestamp ( 'de-de' , 'Europe/Berlin' , '2018-10-10T10:00:00Z0' )
or
translated = Translation . timestamp ( 'de-de' , 'Europe/Berlin' , Time . zone . parse ( '2018-10-10T10:00:00Z0' ) )
= end
def self . timestamp ( locale , timezone , timestamp )
2020-10-22 13:57:01 +00:00
if timestamp . instance_of? ( String )
2019-02-10 11:01:38 +00:00
begin
timestamp_parsed = Time . zone . parse ( timestamp )
return timestamp . to_s if ! timestamp_parsed
timestamp = timestamp_parsed
rescue
return timestamp . to_s
end
end
begin
timestamp = timestamp . in_time_zone ( timezone )
rescue
return timestamp . to_s
end
2020-01-27 09:28:17 +00:00
2021-11-15 15:58:19 +00:00
record = Translation . where ( locale : locale , source : 'FORMAT_DATETIME' ) . pick ( :target )
2020-01-27 09:28:17 +00:00
return timestamp . to_s if ! record
2020-02-18 19:51:31 +00:00
record . sub! ( 'dd' , format ( '%<day>02d' , day : timestamp . day ) )
2019-02-10 11:01:38 +00:00
record . sub! ( 'd' , timestamp . day . to_s )
2020-02-18 19:51:31 +00:00
record . sub! ( 'mm' , format ( '%<month>02d' , month : timestamp . month ) )
2019-02-10 11:01:38 +00:00
record . sub! ( 'm' , timestamp . month . to_s )
record . sub! ( 'yyyy' , timestamp . year . to_s )
record . sub! ( 'yy' , timestamp . year . to_s . last ( 2 ) )
2020-02-18 19:51:31 +00:00
record . sub! ( 'SS' , format ( '%<second>02d' , second : timestamp . sec . to_s ) )
record . sub! ( 'MM' , format ( '%<minute>02d' , minute : timestamp . min . to_s ) )
record . sub! ( 'HH' , format ( '%<hour>02d' , hour : timestamp . hour . to_s ) )
2022-01-12 10:53:36 +00:00
record . sub! ( 'l' , timestamp . strftime ( '%l' ) )
record . sub! ( 'P' , timestamp . strftime ( '%P' ) )
2019-02-10 11:01:38 +00:00
" #{ record } ( #{ timezone } ) "
end
= begin
translate date in ruby context , e . g . for notifications
translated = Translation . date ( 'de-de' , '2018-10-10' )
or
translated = Translation . date ( 'de-de' , Date . parse ( '2018-10-10' ) )
= end
def self . date ( locale , date )
2020-10-22 13:57:01 +00:00
if date . instance_of? ( String )
2019-02-10 11:01:38 +00:00
begin
date_parsed = Date . parse ( date )
return date . to_s if ! date_parsed
date = date_parsed
rescue
return date . to_s
end
end
return date . to_s if date . class != Date
2021-11-15 15:58:19 +00:00
record = Translation . where ( locale : locale , source : 'FORMAT_DATE' ) . pick ( :target )
2019-02-10 11:01:38 +00:00
return date . to_s if ! record
2020-02-18 19:51:31 +00:00
record . sub! ( 'dd' , format ( '%<day>02d' , day : date . day ) )
2019-02-10 11:01:38 +00:00
record . sub! ( 'd' , date . day . to_s )
2020-02-18 19:51:31 +00:00
record . sub! ( 'mm' , format ( '%<month>02d' , month : date . month ) )
2019-02-10 11:01:38 +00:00
record . sub! ( 'm' , date . month . to_s )
record . sub! ( 'yyyy' , date . year . to_s )
record . sub! ( 'yy' , date . year . to_s . last ( 2 ) )
record
end
2018-09-04 11:37:51 +00:00
def self . remote_translation_need_update? ( raw , translations )
translations . each do | row |
next if row [ 1 ] != raw [ 'locale' ]
next if row [ 2 ] != raw [ 'source' ]
2021-11-15 15:58:19 +00:00
return false if row [ 3 ] == raw [ 'target' ] # no update if target is still the same
return false if row [ 3 ] != row [ 4 ] # no update if translation has already changed
2018-10-09 06:17:41 +00:00
2018-09-04 11:37:51 +00:00
return [ true , Translation . find ( row [ 0 ] ) ]
end
[ true , nil ]
end
2022-03-16 16:35:50 +00:00
def self . import ( locale , translations )
bulk_import translations
lang_cache_clear ( locale )
end
def self . lang_cache_clear ( locale )
Cache . delete lang_cache_key ( locale )
end
def self . lang_cache_set ( locale , data )
Cache . write lang_cache_key ( locale ) , data
end
def self . lang_cache_get ( locale )
Cache . read lang_cache_key ( locale )
end
2012-05-18 14:24:00 +00:00
private
2015-05-01 12:31:46 +00:00
2013-06-12 15:59:58 +00:00
def set_initial
2018-09-04 11:37:51 +00:00
return true if target_initial . present?
2017-06-16 22:53:20 +00:00
return true if target_initial == ''
2018-10-09 06:17:41 +00:00
2015-05-07 12:10:38 +00:00
self . target_initial = target
2017-06-16 22:53:20 +00:00
true
2013-06-12 15:59:58 +00:00
end
2015-05-07 10:27:12 +00:00
2022-03-16 16:35:50 +00:00
def cache_delete
super
self . class . lang_cache_clear ( locale ) # delete whole lang cache as well
2013-08-06 14:17:30 +00:00
end
2015-09-09 18:16:20 +00:00
2022-03-16 16:35:50 +00:00
def self . lang_cache_key ( locale )
" TranslationMapOnlyContent:: #{ locale . downcase } "
2013-08-06 14:17:30 +00:00
end
2022-03-16 16:35:50 +00:00
private_class_method :lang_cache_key
2012-05-18 14:24:00 +00:00
end