Improved admin interface for translations.
This commit is contained in:
parent
c1d700c82e
commit
466bde7feb
6 changed files with 234 additions and 27 deletions
|
@ -1,8 +1,4 @@
|
|||
class Index extends App.ControllerContent
|
||||
events:
|
||||
'blur input': 'update'
|
||||
'click .js-Reset': 'reset'
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
|
||||
|
@ -12,23 +8,144 @@ class Index extends App.ControllerContent
|
|||
@title 'Translations'
|
||||
|
||||
@render()
|
||||
|
||||
render: =>
|
||||
@html App.view('translation/index')()
|
||||
configure_attributes = [
|
||||
{ name: 'locale', display: '', tag: 'select', null: false, class: 'input', options: { de: 'Deutsch', en: 'English (United States)', 'en-CA': 'English (Canada)', 'en-GB': 'English (United Kingdom)' }, default: App.i18n.get() },
|
||||
]
|
||||
load = (params) =>
|
||||
new TranslationToDo(
|
||||
el: @$('.js-ToDo')
|
||||
locale: params.locale
|
||||
)
|
||||
new TranslationList(
|
||||
el: @$('.js-List')
|
||||
locale: params.locale
|
||||
)
|
||||
|
||||
new App.ControllerForm(
|
||||
el: @$('.language')
|
||||
model: { configure_attributes: configure_attributes }
|
||||
autofocus: false
|
||||
handlers: [load]
|
||||
)
|
||||
|
||||
release: =>
|
||||
App.Event.trigger('ui:rerender')
|
||||
|
||||
class TranslationToDo extends App.Controller
|
||||
events:
|
||||
'click .js-Create': 'create'
|
||||
'click .js-TheSame': 'same'
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
@render()
|
||||
@bind(
|
||||
'i18n:translation_todo_reload',
|
||||
=>
|
||||
@render()
|
||||
)
|
||||
|
||||
render: =>
|
||||
listNotTranslated = []
|
||||
for key, value of App.i18n.getNotTranslated(@locale)
|
||||
item = [ '', key, '', '']
|
||||
listNotTranslated.push item
|
||||
|
||||
@html App.view('translation/todo')(
|
||||
list: listNotTranslated
|
||||
)
|
||||
|
||||
create: (e) =>
|
||||
e.preventDefault()
|
||||
field = $(e.target).closest('tr').find('.js-Item')
|
||||
source = field.data('source')
|
||||
target = field.val()
|
||||
|
||||
# remove from not translated list
|
||||
$(e.target).closest('tr').remove()
|
||||
|
||||
# local update
|
||||
App.i18n.removeNotTranslated( @locale, source )
|
||||
App.i18n.setMap( source, target )
|
||||
|
||||
# remote update
|
||||
params =
|
||||
locale: @locale
|
||||
source: source
|
||||
target: target
|
||||
target_initial: ''
|
||||
|
||||
@ajax(
|
||||
id: 'translations'
|
||||
type: 'POST'
|
||||
url: @apiPath + '/translations'
|
||||
data: JSON.stringify(params)
|
||||
processData: false
|
||||
success: (data, status, xhr) =>
|
||||
App.Event.trigger('i18n:translation_list_reload')
|
||||
)
|
||||
|
||||
same: (e) =>
|
||||
e.preventDefault()
|
||||
field = $(e.target).closest('tr').find('.js-Item')
|
||||
source = field.data('source')
|
||||
|
||||
# remove from not translated list
|
||||
$(e.target).closest('tr').remove()
|
||||
|
||||
# local update
|
||||
App.i18n.removeNotTranslated( @locale, source )
|
||||
App.i18n.setMap( source, source )
|
||||
|
||||
# remote update
|
||||
params =
|
||||
locale: @locale
|
||||
source: source
|
||||
target: source
|
||||
target_initial: ''
|
||||
|
||||
@ajax(
|
||||
id: 'translations'
|
||||
type: 'POST'
|
||||
url: @apiPath + '/translations'
|
||||
data: JSON.stringify(params)
|
||||
processData: false
|
||||
success: (data, status, xhr) =>
|
||||
App.Event.trigger('i18n:translation_list_reload')
|
||||
)
|
||||
|
||||
class TranslationList extends App.Controller
|
||||
events:
|
||||
'blur .js-translated input': 'update'
|
||||
'click .js-translated .js-Reset': 'reset'
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
@load()
|
||||
@bind(
|
||||
'i18n:translation_list_reload',
|
||||
=>
|
||||
@load()
|
||||
)
|
||||
|
||||
load: =>
|
||||
@ajax(
|
||||
id: 'translations_admin'
|
||||
type: 'GET'
|
||||
url: @apiPath + '/translations/admin/lang/de'
|
||||
url: @apiPath + "/translations/admin/lang/#{@locale}"
|
||||
processData: true
|
||||
success: (data, status, xhr) =>
|
||||
@render(data)
|
||||
)
|
||||
|
||||
render: (data = {}) =>
|
||||
@html App.view('translation')(
|
||||
list: data.list
|
||||
timestampFormat: data.timestampFormat
|
||||
dateFormat: data.dateFormat
|
||||
@html App.view('translation/list')(
|
||||
list: data.list
|
||||
timestampFormat: data.timestampFormat
|
||||
dateFormat: data.dateFormat
|
||||
)
|
||||
ui = @
|
||||
@$('.js-Item').each( (e) ->
|
||||
|
@ -40,7 +157,31 @@ class Index extends App.ControllerContent
|
|||
e.preventDefault()
|
||||
field = $(e.target).closest('tr').find('.js-Item')
|
||||
id = field.data('id')
|
||||
source = field.data('source')
|
||||
initial = field.data('initial')
|
||||
|
||||
# if it's translated by user it self, delete it
|
||||
if !initial || initial is ''
|
||||
$(e.target).closest('tr').remove()
|
||||
App.i18n.setMap( source, '' )
|
||||
params =
|
||||
id: id
|
||||
@ajax(
|
||||
id: 'translations'
|
||||
type: 'DELETE'
|
||||
url: @apiPath + '/translations/' + id
|
||||
data: JSON.stringify(params)
|
||||
processData: false
|
||||
success: =>
|
||||
console.log('aaa', @locale, source)
|
||||
App.i18n.setNotTranslated( @locale, source )
|
||||
App.Event.trigger('i18n:translation_todo_reload')
|
||||
)
|
||||
return
|
||||
|
||||
# update item
|
||||
App.i18n.setMap( source, initial )
|
||||
|
||||
field.val( initial )
|
||||
@updateRow(id)
|
||||
params =
|
||||
|
@ -58,8 +199,14 @@ class Index extends App.ControllerContent
|
|||
update: (e) ->
|
||||
e.preventDefault()
|
||||
id = $( e.target ).data('id')
|
||||
source = $( e.target ).data('source')
|
||||
target = $( e.target ).val()
|
||||
@updateRow(id)
|
||||
|
||||
# local update
|
||||
App.i18n.setMap( source, target )
|
||||
|
||||
# remote update
|
||||
params =
|
||||
id: id
|
||||
target: target
|
||||
|
@ -84,5 +231,4 @@ class Index extends App.ControllerContent
|
|||
reset.hide()
|
||||
reset.closest('tr').removeClass('warning')
|
||||
|
||||
|
||||
App.Config.set( 'Translation', { prio: 1800, parent: '#system', name: 'Translations', target: '#system/translation', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )
|
||||
App.Config.set( 'Translation', { prio: 1800, parent: '#system', name: 'Translations', target: '#system/translation', controller: Index, role: ['Admin'] }, 'NavBarAdmin' )
|
|
@ -6,44 +6,65 @@ class App.i18n
|
|||
|
||||
@translateContent: ( string, args... ) ->
|
||||
if _instance == undefined
|
||||
_instance ?= new _i18nSingleton
|
||||
_instance ?= new _i18nSingleton()
|
||||
_instance.translateContent( string, args )
|
||||
|
||||
@translatePlain: ( string, args... ) ->
|
||||
if _instance == undefined
|
||||
_instance ?= new _i18nSingleton
|
||||
_instance ?= new _i18nSingleton()
|
||||
_instance.translatePlain( string, args )
|
||||
|
||||
@translateInline: ( string, args... ) ->
|
||||
if _instance == undefined
|
||||
_instance ?= new _i18nSingleton
|
||||
_instance ?= new _i18nSingleton()
|
||||
_instance.translateInline( string, args )
|
||||
|
||||
@translateTimestamp: ( args, offset = 0 ) ->
|
||||
if _instance == undefined
|
||||
_instance ?= new _i18nSingleton
|
||||
_instance ?= new _i18nSingleton()
|
||||
_instance.timestamp( args, offset )
|
||||
|
||||
@translateDate: ( args, offset = 0 ) ->
|
||||
if _instance == undefined
|
||||
_instance ?= new _i18nSingleton
|
||||
_instance ?= new _i18nSingleton()
|
||||
_instance.date( args, offset )
|
||||
|
||||
@get: ->
|
||||
if _instance == undefined
|
||||
_instance ?= new _i18nSingleton
|
||||
_instance ?= new _i18nSingleton()
|
||||
_instance.get()
|
||||
|
||||
@set: ( args ) ->
|
||||
if _instance == undefined
|
||||
_instance ?= new _i18nSingleton( args )
|
||||
_instance ?= new _i18nSingleton()
|
||||
_instance.set( args )
|
||||
|
||||
@setMap: (source, target) ->
|
||||
if _instance == undefined
|
||||
_instance ?= new _i18nSingleton()
|
||||
_instance.setMap( source, target )
|
||||
|
||||
@getNotTranslated: (locale) ->
|
||||
if _instance == undefined
|
||||
_instance ?= new _i18nSingleton()
|
||||
_instance.getNotTranslated( locale )
|
||||
|
||||
@removeNotTranslated: (locale, key) ->
|
||||
if _instance == undefined
|
||||
_instance ?= new _i18nSingleton()
|
||||
_instance.removeNotTranslated( locale, key )
|
||||
|
||||
@setNotTranslated: (locale, key) ->
|
||||
if _instance == undefined
|
||||
_instance ?= new _i18nSingleton()
|
||||
_instance.setNotTranslated( locale, key )
|
||||
|
||||
class _i18nSingleton extends Spine.Module
|
||||
@include App.LogInclude
|
||||
|
||||
constructor: ( locale ) ->
|
||||
@map = {}
|
||||
@map = {}
|
||||
@_notTranslated = {}
|
||||
@dateFormat = 'yyyy-mm-dd'
|
||||
@timestampFormat = 'yyyy-mm-dd HH:MM'
|
||||
|
||||
|
@ -165,6 +186,9 @@ class _i18nSingleton extends Spine.Module
|
|||
@_translated = false
|
||||
translated = string
|
||||
if App.Config.get('developer_mode') is true
|
||||
if !@_notTranslated[@locale]
|
||||
@_notTranslated[@locale] = {}
|
||||
@_notTranslated[@locale][string] = true
|
||||
@log 'notice', "translation for '#{string}' in '#{@locale}' is missing"
|
||||
|
||||
# search %s
|
||||
|
@ -176,6 +200,18 @@ class _i18nSingleton extends Spine.Module
|
|||
# return translated string
|
||||
return translated
|
||||
|
||||
setMap: ( source, target ) =>
|
||||
@map[source] = target
|
||||
|
||||
getNotTranslated: ( locale ) =>
|
||||
@_notTranslated[locale || @locale]
|
||||
|
||||
removeNotTranslated: ( locale, key ) =>
|
||||
delete @_notTranslated[locale][key]
|
||||
|
||||
setNotTranslated: ( locale, key ) =>
|
||||
@_notTranslated[locale][key] = true
|
||||
|
||||
date: ( time, offset ) =>
|
||||
@convert(time, offset, @dateFormat)
|
||||
|
||||
|
|
10
app/assets/javascripts/app/views/translation/index.jst.eco
Normal file
10
app/assets/javascripts/app/views/translation/index.jst.eco
Normal file
|
@ -0,0 +1,10 @@
|
|||
<div class="horizontal">
|
||||
<div class="page-header-title">
|
||||
<h1><%- @T('Translations') %> <small></small></h1>
|
||||
</div>
|
||||
<div class="page-header-meta">
|
||||
<div class="language"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="js-ToDo"></div>
|
||||
<div class="js-List"></div>
|
|
@ -1,6 +1,3 @@
|
|||
<div class="page-header-title">
|
||||
<h1><%- @T('Translations') %><small></small></h1>
|
||||
</div>
|
||||
<h2><%- @T('Date & Datetime') %></h2>
|
||||
<table class="translationOverview table table-striped table-hover">
|
||||
<thead>
|
||||
|
@ -28,7 +25,7 @@
|
|||
</table>
|
||||
|
||||
<h2><%- @T('Words') %></h2>
|
||||
<table class="translationOverview table table-striped table-hover">
|
||||
<table class="translationOverview js-translated table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="translationOverview-source"><%- @T('Source') %></th>
|
||||
|
@ -42,7 +39,7 @@
|
|||
<% for item in @list: %>
|
||||
<tr>
|
||||
<td title="<%= item[1] %>"><%= item[1] %></td>
|
||||
<td class="translationOverview-itemContainer"><input class="js-Item translationOverview-item form-control" value="<%= item[2] %>" data-initial="<%= item[3] %>" data-id="<%= item[0] %>"></td>
|
||||
<td class="translationOverview-itemContainer"><input class="js-Item translationOverview-item form-control" value="<%= item[2] %>" data-source="<%= item[1] %>" data-initial="<%= item[3] %>" data-id="<%= item[0] %>"></td>
|
||||
<td title="<%= item[3] %>"><%= item[3]%></td>
|
||||
<td><a href="#" class="js-Reset"><%- @T('Reset') %></a></td>
|
||||
</tr>
|
21
app/assets/javascripts/app/views/translation/todo.jst.eco
Normal file
21
app/assets/javascripts/app/views/translation/todo.jst.eco
Normal file
|
@ -0,0 +1,21 @@
|
|||
<h2><%- @T('Words') %> <small><%- @T('not translated') %></small></h2>
|
||||
<table class="translationOverview table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="translationOverview-source"><%- @T('Source') %></th>
|
||||
<th class="translationOverview-target"><%- @T('Target') %></th>
|
||||
<th class="translationOverview-action"><%- @T('Action') %></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% if @list: %>
|
||||
<% for item in @list: %>
|
||||
<tr>
|
||||
<td title="<%= item[1] %>"><%= item[1] %></td>
|
||||
<td class="translationOverview-itemContainer"><input class="js-Item translationOverview-item form-control" value="<%= item[2] %>" data-source="<%= item[1] %>"></td>
|
||||
<td><a href="#" class="js-Create"><%- @T('Create') %></a> / <a href="#" class="js-TheSame"><%- @T('is the same') %></a></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
|
@ -5282,9 +5282,6 @@ label + .wizard-buttonList {
|
|||
.translationOverview-initial {
|
||||
width: 25%;
|
||||
}
|
||||
.translationOverview-action {
|
||||
width: 15%;
|
||||
}
|
||||
.translationOverview-item {
|
||||
width: 100%;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue