add FormatedString class, automatically translate to new locale when locale is set

This commit is contained in:
Xuan Sang LE 2018-03-10 20:42:09 +01:00
parent 88cf90ae50
commit 6367c321da
12 changed files with 75 additions and 39 deletions

View File

@ -87,7 +87,7 @@ class PromptDialog extends BasicDialog
resizable: false, resizable: false,
buttons: [ buttons: [
{ {
label: __("Ok"), label: "__(Ok)",
onclick: (d) -> onclick: (d) ->
txt = (d.find "content1").value txt = (d.find "content1").value
return d.quit() if txt is "" return d.quit() if txt is ""
@ -95,7 +95,7 @@ class PromptDialog extends BasicDialog
d.quit() d.quit()
}, },
{ {
label: __("Cancel"), label: "__(Cancel)",
onclick: (d) -> d.quit() onclick: (d) -> d.quit()
} }
], ],
@ -119,7 +119,7 @@ class CalendarDialog extends BasicDialog
resizable: false, resizable: false,
buttons: [ buttons: [
{ {
label: __('Ok'), label: "__(Ok)",
onclick: (d) -> onclick: (d) ->
date = (d.find "content0").get "selectedDate" date = (d.find "content0").get "selectedDate"
if date if date
@ -129,7 +129,7 @@ class CalendarDialog extends BasicDialog
d.notify __("Please select a date") d.notify __("Please select a date")
}, },
{ {
label: __('Cancel'), label: "__(Cancel)",
onclick: (d) -> d.quit() onclick: (d) -> d.quit()
} }
] ]
@ -145,7 +145,7 @@ class ColorPickerDialog extends BasicDialog
resizable: false, resizable: false,
buttons: [ buttons: [
{ {
label: __('Ok'), label: "__(Ok)",
onclick: (d) -> onclick: (d) ->
c = (d.find "content0").get "selectedColor" c = (d.find "content0").get "selectedColor"
if c if c
@ -155,7 +155,7 @@ class ColorPickerDialog extends BasicDialog
d.notify "Please select a color" d.notify "Please select a color"
}, },
{ {
label: __('Cancel'), label: "__(Cancel)",
onclick: (d) -> d.quit() onclick: (d) -> d.quit()
} }
] ]
@ -169,7 +169,7 @@ class InfoDialog extends BasicDialog
width: 250, width: 250,
height: 300, height: 300,
resizable: true, resizable: true,
buttons: [ { label: __('Cancel'), onclick: (d) -> d.quit() } ], buttons: [ { label: "__(Cancel)", onclick: (d) -> d.quit() } ],
filldata: (d) -> filldata: (d) ->
return unless d.data return unless d.data
rows = [] rows = []
@ -188,12 +188,12 @@ class YesNoDialog extends BasicDialog
resizable: true, resizable: true,
buttons: [ buttons: [
{ {
label: __("Yes"), onclick: (d) -> label: "__(Yes)", onclick: (d) ->
d.handler true if d.handler d.handler true if d.handler
d.quit() d.quit()
}, },
{ {
label: __("No"), onclick: (d) -> label: "__(No)", onclick: (d) ->
d.handler false if d.handler d.handler false if d.handler
d.quit() d.quit()
} }
@ -215,14 +215,14 @@ class SelectionDialog extends BasicDialog
resizable: false, resizable: false,
buttons: [ buttons: [
{ {
label: __("Ok"), onclick: (d) -> label: "__(Ok)", onclick: (d) ->
el = d.find "content0" el = d.find "content0"
it = el.get "selected" it = el.get "selected"
return unless it return unless it
d.handler it if d.handler d.handler it if d.handler
d.quit() d.quit()
}, },
{ label: __("Cancel"), onclick: (d) -> d.quit() } { label: "__(Cancel)", onclick: (d) -> d.quit() }
], ],
filldata: (d) -> filldata: (d) ->
return unless d.data return unless d.data

View File

@ -1,3 +1,32 @@
class FormatedString
constructor: (@fs, args) ->
@values = []
return unless args
@values[i] = args[i] for i in [0..args.length - 1]
toString: ()->
@
__: () ->
me = @
return __(@fs).replace /{(\d+)}/g, (match, number) ->
return if typeof me.values[number] != 'undefined' then me.values[number] else match
hash: () ->
@__().hash()
asBase64: () ->
@__().asBase64()
unescape: () ->
@__().unescape()
asUint8Array: () ->
@__().asUint8Array()
format: () ->
args = arguments
@values[i] = args[i] for i in [0..args.length - 1]
String.prototype.hash = () -> String.prototype.hash = () ->
hash = 5381 hash = 5381
i = this.length i = this.length
@ -19,7 +48,7 @@ String.prototype.unescape = () ->
d = d.replace /\\f/g, "\f" d = d.replace /\\f/g, "\f"
d = d.replace /\\r/g, "\r" d = d.replace /\\r/g, "\r"
d d
String.prototype.asUnit8Array = () -> String.prototype.asUint8Array = () ->
bytes = [] bytes = []
for i in [0..(@length - 1)] for i in [0..(@length - 1)]
bytes.push @charCodeAt i bytes.push @charCodeAt i
@ -29,14 +58,18 @@ String.prototype.asUnit8Array = () ->
if not String.prototype.format if not String.prototype.format
String.prototype.format = () -> String.prototype.format = () ->
args = arguments args = arguments
return @replace /{(\d+)}/g, (match, number) -> return new FormatedString(@, args)
return if typeof args[number] != 'undefined' then args[number] else match
String.prototype.f = () ->
args = arguments
return new FormatedString(@, args)
String.prototype.__ = () -> String.prototype.__ = () ->
match = @match(/^__\((.*)\)$/) match = @match(/^__\((.*)\)$/)
return window.__(match[1]) if match return window.__(match[1]) if match
return @ return @
# language directive # language directive
this.__ = () -> this.__ = () ->
_API = window.OS.API _API = window.OS.API
args = arguments args = arguments
@ -44,7 +77,7 @@ this.__ = () ->
d = args[0] d = args[0]
_API.lang[d] = d unless _API.lang[d] _API.lang[d] = d unless _API.lang[d]
return _API.lang[d] unless args.length > 1 return _API.lang[d] unless args.length > 1
return String.prototype.format.apply _API.lang[d], (args[i] for i in [1 .. args.length - 1]) return String.prototype.format.apply d, (args[i] for i in [1 .. args.length - 1])
Date.prototype.toString = () -> Date.prototype.toString = () ->
dd = @getDate() dd = @getDate()

View File

@ -408,7 +408,7 @@ self.OS.GUI =
_GUI.buildSystemMenu() _GUI.buildSystemMenu()
# push startup services # push startup services
# TODO: get services list from user setting # TODO: get services list from user setting
_GUI.pushServices (v for v in _OS.setting.system.startup.services) #_GUI.pushServices (v for v in _OS.setting.system.startup.services)
(_GUI.launch a) for a in _OS.setting.system.startup.apps (_GUI.launch a) for a in _OS.setting.system.startup.apps
#_GUI.launch "DummyApp" #_GUI.launch "DummyApp"
# initDM # initDM

View File

@ -5,8 +5,8 @@
<afx-file-view data-id = "fileview" view='tree' status = false></afx-file-view> <afx-file-view data-id = "fileview" view='tree' status = false></afx-file-view>
<input data-height = '26' type = "text" data-id = "filename" style="margin-left:5px; margin-right:5px;display:none;" /> <input data-height = '26' type = "text" data-id = "filename" style="margin-left:5px; margin-right:5px;display:none;" />
<div data-height = '30' style=' text-align:right;padding-top:3px;'> <div data-height = '30' style=' text-align:right;padding-top:3px;'>
<afx-button data-id = "bt-ok" text = "Ok"></afx-button> <afx-button data-id = "bt-ok" text = "__(Ok)"></afx-button>
<afx-button data-id = "bt-cancel" text = "Cancel"></afx-button> <afx-button data-id = "bt-cancel" text = "__(Cancel)"></afx-button>
</div> </div>
</afx-vbox> </afx-vbox>
</afx-hbox> </afx-hbox>

View File

@ -4,7 +4,7 @@
<div class = "treecontainer" ref="treecontainer"> <div class = "treecontainer" ref="treecontainer">
<afx-tree-view ref = "treeview" observable = {root.observable}></afx-tree-view> <afx-tree-view ref = "treeview" observable = {root.observable}></afx-tree-view>
</div> </div>
<div if = {status == true} class = "status" ref = "stbar"></div> <afx-label if = {status == true} class = "status" ref = "stbar"></afx-label>
<script> <script>
var self = this var self = this
self.root.observable = opts.observable || riot.observable() self.root.observable = opts.observable || riot.observable()
@ -49,7 +49,7 @@
var h = $(self.root).outerHeight() var h = $(self.root).outerHeight()
var w = $(self.root).width() var w = $(self.root).width()
if(self.refs.stbar) if(self.refs.stbar)
h -= ($(self.refs.stbar).height() + 10) h -= ($(self.refs.stbar.root).height() + 10)
$(self.refs.listview.root).css("height", h + "px") $(self.refs.listview.root).css("height", h + "px")
$(self.refs.gridview.root).css("height", h + "px") $(self.refs.gridview.root).css("height", h + "px")
$(self.refs.treecontainer).css("height", h + "px") $(self.refs.treecontainer).css("height", h + "px")
@ -126,7 +126,8 @@
f(getTreeData(d)) f(getTreeData(d))
}) })
}) })
$(self.refs.stbar).html("") if(self.refs.stbar)
self.refs.stbar.root.set("text", "")
switch (self.view) { switch (self.view) {
case 'icon': case 'icon':
$(self.refs.listview.root).show() $(self.refs.listview.root).show()
@ -200,8 +201,8 @@
self.selectedFile = e.data self.selectedFile = e.data
if(self.onfileselect) if(self.onfileselect)
self.onfileselect(e.data) self.onfileselect(e.data)
$(self.refs.stbar).empty() if(self.refs.stbar)
$(self.refs.stbar).append($("<span>").append(__("Selected: {0} ({1} bytes)", e.data.filename, e.data.size?e.data.size:"0")))//.html() self.refs.stbar.root.set("text", __("Selected: {0} ({1} bytes)", e.data.filename, e.data.size?e.data.size:"0"))//.html()
}) })
self.root.observable.on("filedbclick", function(e){ self.root.observable.on("filedbclick", function(e){
if(e.id != self.rid ) return if(e.id != self.rid ) return

View File

@ -33,7 +33,8 @@ class BaseFileHandler
@genealogy = re.split("/") @genealogy = re.split("/")
@basename = @genealogy[@genealogy.length - 1] unless @isRoot() @basename = @genealogy[@genealogy.length - 1] unless @isRoot()
@ext = @basename.split( "." ).pop() unless @basename.lastIndexOf(".") is 0 or @basename.indexOf( "." ) is -1 @ext = @basename.split( "." ).pop() unless @basename.lastIndexOf(".") is 0 or @basename.indexOf( "." ) is -1
asFileHandler: () ->
@
isRoot: () -> (not @genealogy) or (@genealogy.size is 0) isRoot: () -> (not @genealogy) or (@genealogy.size is 0)
child: (name) -> child: (name) ->

View File

@ -164,7 +164,7 @@ class GoogleDriveHandler extends this.OS.API.VFS.BaseFileHandler
.then (r) -> .then (r) ->
_API.loaded q, "OK" _API.loaded q, "OK"
return f r.body unless p is "binary" return f r.body unless p is "binary"
f r.body.asUnit8Array() f r.body.asUint8Array()
.catch (err) -> .catch (err) ->
_API.loaded q, "FAIL" _API.loaded q, "FAIL"
_courrier.oserror __("VFS cannot read : {0}", me.path), (_API.throwe "OS.VFS"), err _courrier.oserror __("VFS cannot read : {0}", me.path), (_API.throwe "OS.VFS"), err

View File

@ -196,7 +196,7 @@ class Files extends this.OS.GUI.BaseApplication
file.path.asFileHandler() file.path.asFileHandler()
.move "#{me.currdir.path}/#{d}", (r) -> .move "#{me.currdir.path}/#{d}", (r) ->
me.error __("Fail to rename to {0}: {1}", d, r.error) if r.error me.error __("Fail to rename to {0}: {1}", d, r.error) if r.error
, __("Rename"), { label: __("File name"), value: file.filename } , "__(Rename)", { label: "__(File name)", value: file.filename }
when "#{@name}-rm" when "#{@name}-rm"
return unless file return unless file
@ -206,7 +206,7 @@ class Files extends this.OS.GUI.BaseApplication
file.path.asFileHandler() file.path.asFileHandler()
.remove (r) -> .remove (r) ->
me.error __("Fail to delete {0}: {1}", file.filename, r.error) if r.error me.error __("Fail to delete {0}: {1}", file.filename, r.error) if r.error
, __("Delete") , ,"__(Delete)" ,
{ iconclass: "fa fa-question-circle", text: __("Do you really want to delete: {0}?", file.filename) } { iconclass: "fa fa-question-circle", text: __("Do you really want to delete: {0}?", file.filename) }
when "#{@name}-cut" when "#{@name}-cut"
@ -247,7 +247,7 @@ class Files extends this.OS.GUI.BaseApplication
(d) -> (d) ->
me.currdir.mk d, (r) -> me.currdir.mk d, (r) ->
me.error __("Fail to create {0}: {1}", d, r.error) if r.error me.error __("Fail to create {0}: {1}", d, r.error) if r.error
, __("New folder"), { label: __("Folder name") } , "__(New folder)", { label: "__(Folder name)" }
when "#{@name}-mkf" when "#{@name}-mkf"
@openDialog "PromptDialog", @openDialog "PromptDialog",
@ -255,7 +255,7 @@ class Files extends this.OS.GUI.BaseApplication
fp = "#{me.currdir.path}/#{d}".asFileHandler() fp = "#{me.currdir.path}/#{d}".asFileHandler()
fp.write "text/plain", (r) -> fp.write "text/plain", (r) ->
me.error __("Fail to create {0}: {1}", d, r.error) if r.error me.error __("Fail to create {0}: {1}", d, r.error) if r.error
, __("New file"), { label: __("File name") } , "__(New file)", { label: "__(File name)" }
when "#{@name}-info" when "#{@name}-info"
return unless file return unless file

View File

@ -58,7 +58,7 @@ class NotePad extends this.OS.GUI.BaseApplication
stup = (e) -> stup = (e) ->
c = me.editor.session.selection.getCursor() c = me.editor.session.selection.getCursor()
l = me.editor.session.getLength() l = me.editor.session.getLength()
$(stat).html __("Row {0}, col {1}, lines: {2}", c.row, c.column, l) stat.set "text", __("Row {0}, col {1}, lines: {2}", c.row, c.column, l)
stup(0) stup(0)
@.editor.getSession().selection.on "changeCursor", (e) -> stup(e) @.editor.getSession().selection.on "changeCursor", (e) -> stup(e)
@editormux = false @editormux = false
@ -133,6 +133,7 @@ class NotePad extends this.OS.GUI.BaseApplication
me = @ me = @
file = @fileview.get "selectedFile" file = @fileview.get "selectedFile"
dir = if file then file.path.asFileHandler() else (@fileview.get "path").asFileHandler() dir = if file then file.path.asFileHandler() else (@fileview.get "path").asFileHandler()
console.log dir
dir = dir.parent().asFileHandler() if file and file.type isnt "dir" dir = dir.parent().asFileHandler() if file and file.type isnt "dir"
switch e.item.data.dataid switch e.item.data.dataid
@ -141,7 +142,7 @@ class NotePad extends this.OS.GUI.BaseApplication
(d) -> (d) ->
dir.mk d, (r) -> dir.mk d, (r) ->
me.error __("Fail to create {0}: {1}", d, r.error) if r.error me.error __("Fail to create {0}: {1}", d, r.error) if r.error
, __("New folder") , "__(New folder)"
when "#{@name}-mkf" when "#{@name}-mkf"
@openDialog "PromptDialog", @openDialog "PromptDialog",
@ -149,7 +150,7 @@ class NotePad extends this.OS.GUI.BaseApplication
fp = "#{dir.path}/#{d}".asFileHandler() fp = "#{dir.path}/#{d}".asFileHandler()
fp.write "", (r) -> fp.write "", (r) ->
me.error __("Fail to create {0}: {1}", d, r.error) if r.error me.error __("Fail to create {0}: {1}", d, r.error) if r.error
, __("New file") , "__(New file)"
when "#{@name}-rm" when "#{@name}-rm"
return unless file return unless file
@openDialog "YesNoDialog", @openDialog "YesNoDialog",
@ -158,7 +159,7 @@ class NotePad extends this.OS.GUI.BaseApplication
file.path.asFileHandler() file.path.asFileHandler()
.remove (r) -> .remove (r) ->
me.error __("Fail to delete {0}: {1}", file.filename, r.error) if r.error me.error __("Fail to delete {0}: {1}", file.filename, r.error) if r.error
, __("Delete") , , "__(Delete)" ,
{ iconclass: "fa fa-question-circle", text: __("Do you really want to delete: {0}?", file.filename) } { iconclass: "fa fa-question-circle", text: __("Do you really want to delete: {0}?", file.filename) }
when "#{@name}-refresh" when "#{@name}-refresh"
@.chdir ( @fileview.get "path" ) @.chdir ( @fileview.get "path" )
@ -267,12 +268,12 @@ class NotePad extends this.OS.GUI.BaseApplication
me.tabarea.replaceItem me.currfile, file, false me.tabarea.replaceItem me.currfile, file, false
me.currfile = file me.currfile = file
me.save me.currfile me.save me.currfile
, __("Save as"), { file: me.currfile } , "__(Save as)", { file: me.currfile }
switch e switch e
when "#{@name}-Open" when "#{@name}-Open"
@openDialog "FileDiaLog", ( d, f ) -> @openDialog "FileDiaLog", ( d, f ) ->
me.open "#{d}/#{f}".asFileHandler() me.open "#{d}/#{f}".asFileHandler()
, __("Open file") , "__(Open file)"
when "#{@name}-Save" when "#{@name}-Save"
@currfile.cache = @editor.getValue() @currfile.cache = @editor.getValue()
return @save @currfile if @currfile.basename return @save @currfile if @currfile.basename
@ -292,7 +293,7 @@ class NotePad extends this.OS.GUI.BaseApplication
if d if d
v.dirty = false for v in dirties v.dirty = false for v in dirties
me.quit() me.quit()
, __("Quit"), { text: __("Ignore all {0} unsaved files ?", dirties.length) } , "__(Quit)", { text: __("Ignore all {0} unsaved files ?", dirties.length) }
NotePad.singleton = false NotePad.singleton = false
NotePad.dependencies = [ NotePad.dependencies = [

View File

@ -11,7 +11,7 @@ afx-app-window[data-id="notepad"] afx-resizer{
background-color: transparent; background-color: transparent;
border-right: 1px solid #a6a6a6; border-right: 1px solid #a6a6a6;
} }
afx-app-window[data-id="notepad"] span[data-id="editorstat"]{ afx-app-window[data-id="notepad"] afx-label[data-id="editorstat"]{
padding:5px; padding:5px;
display: inline-block; display: inline-block;
} }

View File

@ -9,7 +9,7 @@
<afx-tab-container data-id="tabarea" data-height="26" closable = true></afx-tab-container> <afx-tab-container data-id="tabarea" data-height="26" closable = true></afx-tab-container>
<div data-id="datarea"></div> <div data-id="datarea"></div>
<afx-hbox data-height="30" data-id="bottom-vbox"> <afx-hbox data-height="30" data-id="bottom-vbox">
<div ><span data-id = "editorstat"></span></div> <afx-label data-id="editorstat"></afx-label>
<afx-list-view data-width="160" data-id = "themelist" dropdown = "true" width="135"></afx-list-view> <afx-list-view data-width="160" data-id = "themelist" dropdown = "true" width="135"></afx-list-view>
<afx-list-view data-width="125" data-id = "modelist" dropdown = "true" width="100"></afx-list-view> <afx-list-view data-width="125" data-id = "modelist" dropdown = "true" width="100"></afx-list-view>

View File

@ -1,7 +1,7 @@
afx-file-view { afx-file-view {
position: relative; position: relative;
} }
afx-file-view div.status{ afx-file-view afx-label.status{
position: absolute; position: absolute;
bottom: 1px; bottom: 1px;
left:0px; left:0px;